1 /* 2 ** Sendmail 3 ** Copyright (c) 1983 Eric P. Allman 4 ** Berkeley, California 5 ** 6 ** Copyright (c) 1983 Regents of the University of California. 7 ** All rights reserved. The Berkeley software License Agreement 8 ** specifies the terms and conditions for redistribution. 9 */ 10 11 #ifndef lint 12 static char SccsId[] = "@(#)err.c 5.4 (Berkeley) 09/19/85"; 13 #endif not lint 14 15 # include "sendmail.h" 16 # include <errno.h> 17 18 /* 19 ** SYSERR -- Print error message. 20 ** 21 ** Prints an error message via printf to the diagnostic 22 ** output. If LOG is defined, it logs it also. 23 ** 24 ** Parameters: 25 ** f -- the format string 26 ** a, b, c, d, e -- parameters 27 ** 28 ** Returns: 29 ** none 30 ** Through TopFrame if QuickAbort is set. 31 ** 32 ** Side Effects: 33 ** increments Errors. 34 ** sets ExitStat. 35 */ 36 37 # ifdef lint 38 int sys_nerr; 39 char *sys_errlist[]; 40 # endif lint 41 char MsgBuf[BUFSIZ*2]; /* text of most recent message */ 42 43 /*VARARGS1*/ 44 syserr(fmt, a, b, c, d, e) 45 char *fmt; 46 { 47 register char *p; 48 int olderrno = errno; 49 extern char Arpa_PSyserr[]; 50 extern char Arpa_TSyserr[]; 51 52 /* format and output the error message */ 53 if (olderrno == 0) 54 p = Arpa_PSyserr; 55 else 56 p = Arpa_TSyserr; 57 fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e); 58 puterrmsg(MsgBuf); 59 60 /* determine exit status if not already set */ 61 if (ExitStat == EX_OK) 62 { 63 if (olderrno == 0) 64 ExitStat = EX_SOFTWARE; 65 else 66 ExitStat = EX_OSERR; 67 } 68 69 /* insure that we have a queue id for logging */ 70 (void) queuename(CurEnv, '\0'); 71 # ifdef LOG 72 if (LogLevel > 0) 73 syslog(LOG_CRIT, "%s: SYSERR: %s", CurEnv->e_id, &MsgBuf[4]); 74 # endif LOG 75 errno = 0; 76 if (QuickAbort) 77 longjmp(TopFrame, 2); 78 } 79 /* 80 ** USRERR -- Signal user error. 81 ** 82 ** This is much like syserr except it is for user errors. 83 ** 84 ** Parameters: 85 ** fmt, a, b, c, d -- printf strings 86 ** 87 ** Returns: 88 ** none 89 ** Through TopFrame if QuickAbort is set. 90 ** 91 ** Side Effects: 92 ** increments Errors. 93 */ 94 95 /*VARARGS1*/ 96 usrerr(fmt, a, b, c, d, e) 97 char *fmt; 98 { 99 extern char SuprErrs; 100 extern char Arpa_Usrerr[]; 101 extern int errno; 102 103 if (SuprErrs) 104 return; 105 106 fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e); 107 puterrmsg(MsgBuf); 108 109 if (QuickAbort) 110 longjmp(TopFrame, 1); 111 } 112 /* 113 ** MESSAGE -- print message (not necessarily an error) 114 ** 115 ** Parameters: 116 ** num -- the default ARPANET error number (in ascii) 117 ** msg -- the message (printf fmt) -- if it begins 118 ** with a digit, this number overrides num. 119 ** a, b, c, d, e -- printf arguments 120 ** 121 ** Returns: 122 ** none 123 ** 124 ** Side Effects: 125 ** none. 126 */ 127 128 /*VARARGS2*/ 129 message(num, msg, a, b, c, d, e) 130 register char *num; 131 register char *msg; 132 { 133 errno = 0; 134 fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e); 135 putmsg(MsgBuf, FALSE); 136 } 137 /* 138 ** NMESSAGE -- print message (not necessarily an error) 139 ** 140 ** Just like "message" except it never puts the to... tag on. 141 ** 142 ** Parameters: 143 ** num -- the default ARPANET error number (in ascii) 144 ** msg -- the message (printf fmt) -- if it begins 145 ** with three digits, this number overrides num. 146 ** a, b, c, d, e -- printf arguments 147 ** 148 ** Returns: 149 ** none 150 ** 151 ** Side Effects: 152 ** none. 153 */ 154 155 /*VARARGS2*/ 156 nmessage(num, msg, a, b, c, d, e) 157 register char *num; 158 register char *msg; 159 { 160 errno = 0; 161 fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e); 162 putmsg(MsgBuf, FALSE); 163 } 164 /* 165 ** PUTMSG -- output error message to transcript and channel 166 ** 167 ** Parameters: 168 ** msg -- message to output (in SMTP format). 169 ** holdmsg -- if TRUE, don't output a copy of the message to 170 ** our output channel. 171 ** 172 ** Returns: 173 ** none. 174 ** 175 ** Side Effects: 176 ** Outputs msg to the transcript. 177 ** If appropriate, outputs it to the channel. 178 ** Deletes SMTP reply code number as appropriate. 179 */ 180 181 putmsg(msg, holdmsg) 182 char *msg; 183 bool holdmsg; 184 { 185 /* output to transcript if serious */ 186 if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 187 fprintf(CurEnv->e_xfp, "%s\n", msg); 188 189 /* output to channel if appropriate */ 190 if (!holdmsg && (Verbose || msg[0] != '0')) 191 { 192 (void) fflush(stdout); 193 if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 194 fprintf(OutChannel, "%s\r\n", msg); 195 else 196 fprintf(OutChannel, "%s\n", &msg[4]); 197 (void) fflush(OutChannel); 198 } 199 } 200 /* 201 ** PUTERRMSG -- like putmsg, but does special processing for error messages 202 ** 203 ** Parameters: 204 ** msg -- the message to output. 205 ** 206 ** Returns: 207 ** none. 208 ** 209 ** Side Effects: 210 ** Sets the fatal error bit in the envelope as appropriate. 211 */ 212 213 puterrmsg(msg) 214 char *msg; 215 { 216 /* output the message as usual */ 217 putmsg(msg, HoldErrs); 218 219 /* signal the error */ 220 Errors++; 221 if (msg[0] == '5') 222 CurEnv->e_flags |= EF_FATALERRS; 223 } 224 /* 225 ** FMTMSG -- format a message into buffer. 226 ** 227 ** Parameters: 228 ** eb -- error buffer to get result. 229 ** to -- the recipient tag for this message. 230 ** num -- arpanet error number. 231 ** en -- the error number to display. 232 ** fmt -- format of string. 233 ** a, b, c, d, e -- arguments. 234 ** 235 ** Returns: 236 ** none. 237 ** 238 ** Side Effects: 239 ** none. 240 */ 241 242 /*VARARGS5*/ 243 static 244 fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e) 245 register char *eb; 246 char *to; 247 char *num; 248 int eno; 249 char *fmt; 250 { 251 char del; 252 253 /* output the reply code */ 254 if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 255 { 256 num = fmt; 257 fmt += 4; 258 } 259 if (num[3] == '-') 260 del = '-'; 261 else 262 del = ' '; 263 (void) sprintf(eb, "%3.3s%c", num, del); 264 eb += 4; 265 266 /* output the file name and line number */ 267 if (FileName != NULL) 268 { 269 (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 270 eb += strlen(eb); 271 } 272 273 /* output the "to" person */ 274 if (to != NULL && to[0] != '\0') 275 { 276 (void) sprintf(eb, "%s... ", to); 277 while (*eb != '\0') 278 *eb++ &= 0177; 279 } 280 281 /* output the message */ 282 (void) sprintf(eb, fmt, a, b, c, d, e); 283 while (*eb != '\0') 284 *eb++ &= 0177; 285 286 /* output the error code, if any */ 287 if (eno != 0) 288 { 289 extern char *errstring(); 290 291 (void) sprintf(eb, ": %s", errstring(eno)); 292 eb += strlen(eb); 293 } 294 } 295 /* 296 ** ERRSTRING -- return string description of error code 297 ** 298 ** Parameters: 299 ** errno -- the error number to translate 300 ** 301 ** Returns: 302 ** A string description of errno. 303 ** 304 ** Side Effects: 305 ** none. 306 */ 307 308 char * 309 errstring(errno) 310 int errno; 311 { 312 extern char *sys_errlist[]; 313 extern int sys_nerr; 314 static char buf[100]; 315 # ifdef SMTP 316 extern char *SmtpPhase; 317 extern char *RealHostName; 318 # endif SMTP 319 320 # ifdef DAEMON 321 # ifdef VMUNIX 322 /* 323 ** Handle special network error codes. 324 ** 325 ** These are 4.2/4.3bsd specific; they should be in daemon.c. 326 */ 327 328 switch (errno) 329 { 330 case ETIMEDOUT: 331 case ECONNRESET: 332 (void) strcpy(buf, sys_errlist[errno]); 333 if (SmtpPhase != NULL) 334 { 335 (void) strcat(buf, " during "); 336 (void) strcat(buf, SmtpPhase); 337 } 338 if (RealHostName != NULL) 339 { 340 (void) strcat(buf, " with "); 341 (void) strcat(buf, RealHostName); 342 } 343 return (buf); 344 345 case EHOSTDOWN: 346 if (RealHostName == NULL) 347 break; 348 (void) sprintf(buf, "Host %s is down", RealHostName); 349 return (buf); 350 351 case ECONNREFUSED: 352 if (RealHostName == NULL) 353 break; 354 (void) sprintf(buf, "Connection refused by %s", RealHostName); 355 return (buf); 356 } 357 # endif VMUNIX 358 # endif DAEMON 359 360 if (errno > 0 && errno < sys_nerr) 361 return (sys_errlist[errno]); 362 363 (void) sprintf(buf, "Error %d", errno); 364 return (buf); 365 } 366