1/* errstr.c 2 Return a string for a uuconf error. 3 4 Copyright (C) 1992 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP uuconf library. 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Library General Public License 10 as published by the Free Software Foundation; either version 2 of 11 the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Library General Public License for more details. 17 18 You should have received a copy of the GNU Library General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucnfi.h" 26 27#if USE_RCS_ID 28const char _uuconf_errstr_rcsid[] = "$Id: errstr.c,v 1.6 2002/03/05 19:10:42 ian Rel $"; 29#endif 30 31static char *zeprint_num P((char *zbuf, size_t cbuf, int ival)); 32 33/* Return an error string for a uuconf error. This does not return a 34 uuconf error code, but instead returns the total buffer length. */ 35 36int 37uuconf_error_string (pglobal, ierr, zbuf, cbuf) 38 pointer pglobal; 39 int ierr; 40 char *zbuf; 41 size_t cbuf; 42{ 43 struct sglobal *qglobal = (struct sglobal *) pglobal; 44 const char *zfile; 45 size_t cfile; 46 const char *zlineno; 47 char ablineno[100]; 48 size_t clineno; 49 const char *zmsg; 50 char abmsg[100]; 51 size_t cmsg; 52 const char *zerrno; 53 size_t cerrno; 54 size_t cret; 55 size_t ccopy; 56 57 /* The format of the message is 58 59 filename:lineno: message: errno 60 61 If there is no filename, the trailing colon is not output. If 62 there is no linenumber, the trailing colon is not output. If 63 there is no filename, the linenumber is not output, and neither 64 is the space before message. If there is no errno, the 65 preceeding colon and space are not output. */ 66 67 /* Get the filename to put in the error message, if any. */ 68 if ((ierr & UUCONF_ERROR_FILENAME) == 0 69 || qglobal == NULL 70 || qglobal->zfilename == NULL) 71 { 72 zfile = ""; 73 cfile = 0; 74 } 75 else 76 { 77 zfile = qglobal->zfilename; 78 cfile = strlen (zfile) + 1; 79 } 80 81 /* Get the line number to put in the error message, if any. */ 82 if (cfile == 0 83 || (ierr & UUCONF_ERROR_LINENO) == 0 84 || qglobal == NULL 85 || qglobal->ilineno <= 0) 86 { 87 zlineno = ""; 88 clineno = 0; 89 } 90 else 91 { 92 zlineno = zeprint_num (ablineno, sizeof ablineno, qglobal->ilineno); 93 clineno = strlen (zlineno) + 1; 94 } 95 96 /* Get the main message. */ 97 switch (UUCONF_ERROR_VALUE (ierr)) 98 { 99 case UUCONF_SUCCESS: 100 zmsg = "no error"; 101 break; 102 case UUCONF_NOT_FOUND: 103 zmsg = "not found"; 104 break; 105 case UUCONF_FOPEN_FAILED: 106 zmsg = "fopen"; 107 break; 108 case UUCONF_FSEEK_FAILED: 109 zmsg = "fseek"; 110 break; 111 case UUCONF_MALLOC_FAILED: 112 zmsg = "malloc"; 113 break; 114 case UUCONF_SYNTAX_ERROR: 115 zmsg = "syntax error"; 116 break; 117 default: 118 zmsg = zeprint_num (abmsg, sizeof abmsg, UUCONF_ERROR_VALUE (ierr)); 119 zmsg -= sizeof "error " - 1; 120 memcpy ((pointer) zmsg, (pointer) "error ", sizeof "error " - 1); 121 break; 122 } 123 124 cmsg = strlen (zmsg); 125 if (cfile > 0) 126 ++cmsg; 127 128 /* Get the errno string. Note that strerror is not necessarily 129 reentrant. */ 130 if ((ierr & UUCONF_ERROR_ERRNO) == 0 131 || qglobal == NULL) 132 { 133 zerrno = ""; 134 cerrno = 0; 135 } 136 else 137 { 138 zerrno = strerror (qglobal->ierrno); 139 cerrno = strlen (zerrno) + 2; 140 } 141 142 cret = cfile + clineno + cmsg + cerrno + 1; 143 144 if (cbuf == 0) 145 return cret; 146 147 /* Leave room for the null byte. */ 148 --cbuf; 149 150 if (cfile > 0) 151 { 152 ccopy = cfile - 1; 153 if (ccopy > cbuf) 154 ccopy = cbuf; 155 memcpy ((pointer) zbuf, (pointer) zfile, ccopy); 156 zbuf += ccopy; 157 cbuf -= ccopy; 158 if (cbuf > 0) 159 { 160 *zbuf++ = ':'; 161 --cbuf; 162 } 163 } 164 165 if (clineno > 0) 166 { 167 ccopy = clineno - 1; 168 if (ccopy > cbuf) 169 ccopy = cbuf; 170 memcpy ((pointer) zbuf, (pointer) zlineno, ccopy); 171 zbuf += ccopy; 172 cbuf -= ccopy; 173 if (cbuf > 0) 174 { 175 *zbuf++ = ':'; 176 --cbuf; 177 } 178 } 179 180 if (cbuf > 0 && cfile > 0) 181 { 182 *zbuf++ = ' '; 183 --cbuf; 184 --cmsg; 185 } 186 ccopy = cmsg; 187 if (ccopy > cbuf) 188 ccopy = cbuf; 189 memcpy ((pointer) zbuf, (pointer) zmsg, ccopy); 190 zbuf += ccopy; 191 cbuf -= ccopy; 192 193 if (cerrno > 0) 194 { 195 if (cbuf > 0) 196 { 197 *zbuf++ = ':'; 198 --cbuf; 199 } 200 if (cbuf > 0) 201 { 202 *zbuf++ = ' '; 203 --cbuf; 204 } 205 ccopy = cerrno - 2; 206 if (ccopy > cbuf) 207 ccopy = cbuf; 208 memcpy ((pointer) zbuf, (pointer) zerrno, ccopy); 209 zbuf += ccopy; 210 cbuf -= ccopy; 211 } 212 213 *zbuf = '\0'; 214 215 return cret; 216} 217 218/* Turn a number into a string. This should really call sprintf, but 219 since nothing else in the uuconf library calls any print routine, 220 it's more interesting to not call it here either. */ 221 222static char * 223zeprint_num (ab, c, i) 224 char *ab; 225 size_t c; 226 register int i; 227{ 228 register char *z; 229 230 z = ab + c; 231 *--z = '\0'; 232 do 233 { 234 *--z = i % 10 + '0'; 235 i /= 10; 236 } 237 while (i != 0); 238 239 return z; 240} 241