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