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