122705Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 333729Sbostic * Copyright (c) 1988 Regents of the University of California. 433729Sbostic * All rights reserved. 533729Sbostic * 642826Sbostic * %sccs.include.redist.c% 733729Sbostic */ 822705Sdist 922705Sdist #ifndef lint 10*57232Seric static char sccsid[] = "@(#)err.c 5.17 (Berkeley) 12/20/92"; 1133729Sbostic #endif /* not lint */ 1222705Sdist 133311Seric # include "sendmail.h" 1424943Seric # include <errno.h> 1525526Smiriam # include <netdb.h> 16295Seric 17295Seric /* 181514Seric ** SYSERR -- Print error message. 19295Seric ** 20295Seric ** Prints an error message via printf to the diagnostic 21295Seric ** output. If LOG is defined, it logs it also. 22295Seric ** 23295Seric ** Parameters: 24295Seric ** f -- the format string 25295Seric ** a, b, c, d, e -- parameters 26295Seric ** 27295Seric ** Returns: 284084Seric ** none 297762Seric ** Through TopFrame if QuickAbort is set. 30295Seric ** 31295Seric ** Side Effects: 321514Seric ** increments Errors. 331514Seric ** sets ExitStat. 34295Seric */ 35295Seric 364084Seric # ifdef lint 374084Seric int sys_nerr; 384084Seric char *sys_errlist[]; 394084Seric # endif lint 4010147Seric char MsgBuf[BUFSIZ*2]; /* text of most recent message */ 414084Seric 4246928Sbostic static void fmtmsg(); 4346928Sbostic 44295Seric /*VARARGS1*/ 4556852Seric syserr(fmt VA_ARG_FORMAL) 46295Seric char *fmt; 4756852Seric VA_ARG_DECL 48295Seric { 4916901Seric register char *p; 5016901Seric int olderrno = errno; 5156852Seric VA_LOCAL_DECL 527957Seric extern char Arpa_PSyserr[]; 537957Seric extern char Arpa_TSyserr[]; 54295Seric 557525Seric /* format and output the error message */ 5616901Seric if (olderrno == 0) 577957Seric p = Arpa_PSyserr; 587957Seric else 597957Seric p = Arpa_TSyserr; 6056852Seric VA_START(fmt); 6156852Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap); 6256852Seric VA_END; 639389Seric puterrmsg(MsgBuf); 644063Seric 65295Seric /* determine exit status if not already set */ 66295Seric if (ExitStat == EX_OK) 67295Seric { 6816901Seric if (olderrno == 0) 69295Seric ExitStat = EX_SOFTWARE; 70295Seric else 711598Seric ExitStat = EX_OSERR; 72295Seric } 73295Seric 74295Seric # ifdef LOG 757674Seric if (LogLevel > 0) 7625277Seric syslog(LOG_CRIT, "%s: SYSERR: %s", 7725277Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 7825277Seric &MsgBuf[4]); 7956795Seric # endif /* LOG */ 80295Seric errno = 0; 817762Seric if (QuickAbort) 827762Seric longjmp(TopFrame, 2); 83295Seric } 84295Seric /* 85295Seric ** USRERR -- Signal user error. 86295Seric ** 87295Seric ** This is much like syserr except it is for user errors. 88295Seric ** 89295Seric ** Parameters: 90295Seric ** fmt, a, b, c, d -- printf strings 91295Seric ** 92295Seric ** Returns: 934084Seric ** none 947762Seric ** Through TopFrame if QuickAbort is set. 95295Seric ** 96295Seric ** Side Effects: 971514Seric ** increments Errors. 98295Seric */ 99295Seric 100295Seric /*VARARGS1*/ 10156852Seric usrerr(fmt VA_ARG_FORMAL) 102295Seric char *fmt; 10356852Seric VA_ARG_DECL 104295Seric { 10556852Seric VA_LOCAL_DECL 106295Seric extern char SuprErrs; 1074167Seric extern char Arpa_Usrerr[]; 10816901Seric extern int errno; 109295Seric 110295Seric if (SuprErrs) 1114084Seric return; 112295Seric 11356852Seric VA_START(fmt); 11456852Seric fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, ap); 11556852Seric VA_END; 1169389Seric puterrmsg(MsgBuf); 1178239Seric 11851951Seric # ifdef LOG 11951951Seric if (LogLevel > 1 && LogUsrErrs) 12051951Seric syslog(LOG_NOTICE, "%s: %s", 12151951Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 12251951Seric &MsgBuf[4]); 12356795Seric # endif /* LOG */ 12451951Seric 1257762Seric if (QuickAbort) 1267762Seric longjmp(TopFrame, 1); 1274063Seric } 1284063Seric /* 1294063Seric ** MESSAGE -- print message (not necessarily an error) 1304063Seric ** 1314063Seric ** Parameters: 1324063Seric ** num -- the default ARPANET error number (in ascii) 1334063Seric ** msg -- the message (printf fmt) -- if it begins 1344063Seric ** with a digit, this number overrides num. 1354063Seric ** a, b, c, d, e -- printf arguments 1364063Seric ** 1374063Seric ** Returns: 1384063Seric ** none 1394063Seric ** 1404063Seric ** Side Effects: 1414063Seric ** none. 1424063Seric */ 1434063Seric 1444084Seric /*VARARGS2*/ 14556852Seric message(num, msg VA_ARG_FORMAL) 14656852Seric char *num; 14756852Seric char *msg; 14856852Seric VA_ARG_DECL 1494063Seric { 15056852Seric VA_LOCAL_DECL 15156852Seric 1524711Seric errno = 0; 15356852Seric VA_START(msg); 15456852Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, ap); 15556852Seric VA_END; 1569108Seric putmsg(MsgBuf, FALSE); 1577613Seric } 1587613Seric /* 1598239Seric ** NMESSAGE -- print message (not necessarily an error) 1608239Seric ** 1618239Seric ** Just like "message" except it never puts the to... tag on. 1628239Seric ** 1638239Seric ** Parameters: 1648239Seric ** num -- the default ARPANET error number (in ascii) 1658239Seric ** msg -- the message (printf fmt) -- if it begins 16624943Seric ** with three digits, this number overrides num. 1678239Seric ** a, b, c, d, e -- printf arguments 1688239Seric ** 1698239Seric ** Returns: 1708239Seric ** none 1718239Seric ** 1728239Seric ** Side Effects: 1738239Seric ** none. 1748239Seric */ 1758239Seric 1768239Seric /*VARARGS2*/ 17756852Seric nmessage(num, msg VA_ARG_FORMAL) 17856852Seric char *num; 17956852Seric char *msg; 18056852Seric VA_ARG_DECL 1818239Seric { 18256852Seric VA_LOCAL_DECL 18356852Seric 1848239Seric errno = 0; 18556852Seric VA_START(msg); 18656852Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, ap); 18756852Seric VA_END; 1889108Seric putmsg(MsgBuf, FALSE); 1898239Seric } 1908239Seric /* 1917613Seric ** PUTMSG -- output error message to transcript and channel 1927613Seric ** 1937613Seric ** Parameters: 1947613Seric ** msg -- message to output (in SMTP format). 1959108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 1969108Seric ** our output channel. 1977613Seric ** 1987613Seric ** Returns: 1997613Seric ** none. 2007613Seric ** 2017613Seric ** Side Effects: 2027613Seric ** Outputs msg to the transcript. 2037613Seric ** If appropriate, outputs it to the channel. 2047613Seric ** Deletes SMTP reply code number as appropriate. 2057613Seric */ 2064711Seric 2079108Seric putmsg(msg, holdmsg) 2087613Seric char *msg; 2099108Seric bool holdmsg; 2107613Seric { 21114900Seric /* output to transcript if serious */ 21214900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 21314900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 2144711Seric 2154711Seric /* output to channel if appropriate */ 2169108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 2174063Seric { 2187275Seric (void) fflush(stdout); 21952220Seric if (OpMode == MD_SMTP) 2207613Seric fprintf(OutChannel, "%s\r\n", msg); 2214711Seric else 2227613Seric fprintf(OutChannel, "%s\n", &msg[4]); 2234711Seric (void) fflush(OutChannel); 2244063Seric } 2259389Seric } 2269389Seric /* 2279389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2289389Seric ** 2299389Seric ** Parameters: 2309389Seric ** msg -- the message to output. 2319389Seric ** 2329389Seric ** Returns: 2339389Seric ** none. 2349389Seric ** 2359389Seric ** Side Effects: 2369389Seric ** Sets the fatal error bit in the envelope as appropriate. 2379389Seric */ 2388239Seric 2399389Seric puterrmsg(msg) 2409389Seric char *msg; 2419389Seric { 2429389Seric /* output the message as usual */ 2439389Seric putmsg(msg, HoldErrs); 2449389Seric 2459389Seric /* signal the error */ 2469389Seric Errors++; 2479389Seric if (msg[0] == '5') 2489336Seric CurEnv->e_flags |= EF_FATALERRS; 2494711Seric } 2504711Seric /* 2514711Seric ** FMTMSG -- format a message into buffer. 2524711Seric ** 2534711Seric ** Parameters: 2544711Seric ** eb -- error buffer to get result. 2554711Seric ** to -- the recipient tag for this message. 2564711Seric ** num -- arpanet error number. 25716901Seric ** en -- the error number to display. 2584711Seric ** fmt -- format of string. 2594711Seric ** a, b, c, d, e -- arguments. 2604711Seric ** 2614711Seric ** Returns: 2624711Seric ** none. 2634711Seric ** 2644711Seric ** Side Effects: 2654711Seric ** none. 2664711Seric */ 2674063Seric 26846928Sbostic static void 26956852Seric fmtmsg(eb, to, num, eno, fmt, ap) 2704711Seric register char *eb; 2714711Seric char *to; 2724711Seric char *num; 27316904Seric int eno; 2744711Seric char *fmt; 27556852Seric va_list ap; 2764711Seric { 2774711Seric char del; 2784711Seric 2794711Seric /* output the reply code */ 28024943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2814577Seric { 2824711Seric num = fmt; 2834711Seric fmt += 4; 2844711Seric } 2854711Seric if (num[3] == '-') 2864711Seric del = '-'; 2874711Seric else 2884711Seric del = ' '; 2894711Seric (void) sprintf(eb, "%3.3s%c", num, del); 2904711Seric eb += 4; 2914063Seric 2929372Seric /* output the file name and line number */ 2939372Seric if (FileName != NULL) 2949372Seric { 2959372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 2969372Seric eb += strlen(eb); 2979372Seric } 2989372Seric 2994711Seric /* output the "to" person */ 3004711Seric if (to != NULL && to[0] != '\0') 3014711Seric { 3024711Seric (void) sprintf(eb, "%s... ", to); 3035201Seric while (*eb != '\0') 3045201Seric *eb++ &= 0177; 3054711Seric } 3064711Seric 3074711Seric /* output the message */ 30856852Seric (void) vsprintf(eb, fmt, ap); 3095201Seric while (*eb != '\0') 3105201Seric *eb++ &= 0177; 3114711Seric 3124711Seric /* output the error code, if any */ 31316904Seric if (eno != 0) 3144711Seric { 31515136Seric extern char *errstring(); 31615136Seric 31716904Seric (void) sprintf(eb, ": %s", errstring(eno)); 3184711Seric eb += strlen(eb); 3194577Seric } 320295Seric } 32115136Seric /* 32215136Seric ** ERRSTRING -- return string description of error code 32315136Seric ** 32415136Seric ** Parameters: 32515136Seric ** errno -- the error number to translate 32615136Seric ** 32715136Seric ** Returns: 32815136Seric ** A string description of errno. 32915136Seric ** 33015136Seric ** Side Effects: 33115136Seric ** none. 33215136Seric */ 33315136Seric 33415136Seric char * 33515136Seric errstring(errno) 33615136Seric int errno; 33715136Seric { 33815136Seric extern char *sys_errlist[]; 33915136Seric extern int sys_nerr; 340*57232Seric static char buf[MAXLINE]; 34124943Seric # ifdef SMTP 34224943Seric extern char *SmtpPhase; 34356795Seric # endif /* SMTP */ 34415136Seric 34524943Seric # ifdef DAEMON 34652107Seric # ifdef ETIMEDOUT 34724943Seric /* 34824943Seric ** Handle special network error codes. 34924943Seric ** 35024943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 35124943Seric */ 35224943Seric 35324943Seric switch (errno) 35424943Seric { 35524943Seric case ETIMEDOUT: 35624943Seric case ECONNRESET: 35724943Seric (void) strcpy(buf, sys_errlist[errno]); 35824943Seric if (SmtpPhase != NULL) 35924943Seric { 36024943Seric (void) strcat(buf, " during "); 36124943Seric (void) strcat(buf, SmtpPhase); 36224943Seric } 36325050Seric if (CurHostName != NULL) 36424943Seric { 36524943Seric (void) strcat(buf, " with "); 36625050Seric (void) strcat(buf, CurHostName); 36724943Seric } 36824943Seric return (buf); 36924943Seric 37024943Seric case EHOSTDOWN: 37125050Seric if (CurHostName == NULL) 37224943Seric break; 37325050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 37424943Seric return (buf); 37524943Seric 37624943Seric case ECONNREFUSED: 37725050Seric if (CurHostName == NULL) 37824943Seric break; 37925050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 38024943Seric return (buf); 38125526Smiriam 38225526Smiriam case (TRY_AGAIN+MAX_ERRNO): 38325526Smiriam (void) sprintf(buf, "Host Name Lookup Failure"); 38425526Smiriam return (buf); 38524943Seric } 38652107Seric # endif 38752107Seric # endif 38824943Seric 38915136Seric if (errno > 0 && errno < sys_nerr) 39015136Seric return (sys_errlist[errno]); 39115136Seric 39215136Seric (void) sprintf(buf, "Error %d", errno); 39315136Seric return (buf); 39415136Seric } 395