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