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*51951Seric static char sccsid[] = "@(#)err.c 5.12 (Berkeley) 12/15/91"; 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*/ 45295Seric syserr(fmt, a, b, c, d, e) 46295Seric char *fmt; 47295Seric { 4816901Seric register char *p; 4916901Seric int olderrno = errno; 507957Seric extern char Arpa_PSyserr[]; 517957Seric extern char Arpa_TSyserr[]; 52295Seric 537525Seric /* format and output the error message */ 5416901Seric if (olderrno == 0) 557957Seric p = Arpa_PSyserr; 567957Seric else 577957Seric p = Arpa_TSyserr; 5816901Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e); 599389Seric puterrmsg(MsgBuf); 604063Seric 61295Seric /* determine exit status if not already set */ 62295Seric if (ExitStat == EX_OK) 63295Seric { 6416901Seric if (olderrno == 0) 65295Seric ExitStat = EX_SOFTWARE; 66295Seric else 671598Seric ExitStat = EX_OSERR; 68295Seric } 69295Seric 70295Seric # ifdef LOG 717674Seric if (LogLevel > 0) 7225277Seric syslog(LOG_CRIT, "%s: SYSERR: %s", 7325277Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 7425277Seric &MsgBuf[4]); 75295Seric # endif LOG 76295Seric errno = 0; 777762Seric if (QuickAbort) 787762Seric longjmp(TopFrame, 2); 79295Seric } 80295Seric /* 81295Seric ** USRERR -- Signal user error. 82295Seric ** 83295Seric ** This is much like syserr except it is for user errors. 84295Seric ** 85295Seric ** Parameters: 86295Seric ** fmt, a, b, c, d -- printf strings 87295Seric ** 88295Seric ** Returns: 894084Seric ** none 907762Seric ** Through TopFrame if QuickAbort is set. 91295Seric ** 92295Seric ** Side Effects: 931514Seric ** increments Errors. 94295Seric */ 95295Seric 96295Seric /*VARARGS1*/ 97295Seric usrerr(fmt, a, b, c, d, e) 98295Seric char *fmt; 99295Seric { 100295Seric extern char SuprErrs; 1014167Seric extern char Arpa_Usrerr[]; 10216901Seric extern int errno; 103295Seric 104295Seric if (SuprErrs) 1054084Seric return; 106295Seric 10716901Seric fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e); 1089389Seric puterrmsg(MsgBuf); 1098239Seric 110*51951Seric # ifdef LOG 111*51951Seric if (LogLevel > 1 && LogUsrErrs) 112*51951Seric syslog(LOG_NOTICE, "%s: %s", 113*51951Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 114*51951Seric &MsgBuf[4]); 115*51951Seric # endif LOG 116*51951Seric 1177762Seric if (QuickAbort) 1187762Seric longjmp(TopFrame, 1); 1194063Seric } 1204063Seric /* 1214063Seric ** MESSAGE -- print message (not necessarily an error) 1224063Seric ** 1234063Seric ** Parameters: 1244063Seric ** num -- the default ARPANET error number (in ascii) 1254063Seric ** msg -- the message (printf fmt) -- if it begins 1264063Seric ** with a digit, this number overrides num. 1274063Seric ** a, b, c, d, e -- printf arguments 1284063Seric ** 1294063Seric ** Returns: 1304063Seric ** none 1314063Seric ** 1324063Seric ** Side Effects: 1334063Seric ** none. 1344063Seric */ 1354063Seric 1364084Seric /*VARARGS2*/ 1374063Seric message(num, msg, a, b, c, d, e) 1384063Seric register char *num; 1394063Seric register char *msg; 1404063Seric { 1414711Seric errno = 0; 14216901Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e); 1439108Seric putmsg(MsgBuf, FALSE); 1447613Seric } 1457613Seric /* 1468239Seric ** NMESSAGE -- print message (not necessarily an error) 1478239Seric ** 1488239Seric ** Just like "message" except it never puts the to... tag on. 1498239Seric ** 1508239Seric ** Parameters: 1518239Seric ** num -- the default ARPANET error number (in ascii) 1528239Seric ** msg -- the message (printf fmt) -- if it begins 15324943Seric ** with three digits, this number overrides num. 1548239Seric ** a, b, c, d, e -- printf arguments 1558239Seric ** 1568239Seric ** Returns: 1578239Seric ** none 1588239Seric ** 1598239Seric ** Side Effects: 1608239Seric ** none. 1618239Seric */ 1628239Seric 1638239Seric /*VARARGS2*/ 1648239Seric nmessage(num, msg, a, b, c, d, e) 1658239Seric register char *num; 1668239Seric register char *msg; 1678239Seric { 1688239Seric errno = 0; 16916901Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e); 1709108Seric putmsg(MsgBuf, FALSE); 1718239Seric } 1728239Seric /* 1737613Seric ** PUTMSG -- output error message to transcript and channel 1747613Seric ** 1757613Seric ** Parameters: 1767613Seric ** msg -- message to output (in SMTP format). 1779108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 1789108Seric ** our output channel. 1797613Seric ** 1807613Seric ** Returns: 1817613Seric ** none. 1827613Seric ** 1837613Seric ** Side Effects: 1847613Seric ** Outputs msg to the transcript. 1857613Seric ** If appropriate, outputs it to the channel. 1867613Seric ** Deletes SMTP reply code number as appropriate. 1877613Seric */ 1884711Seric 1899108Seric putmsg(msg, holdmsg) 1907613Seric char *msg; 1919108Seric bool holdmsg; 1927613Seric { 19314900Seric /* output to transcript if serious */ 19414900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 19514900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 1964711Seric 1974711Seric /* output to channel if appropriate */ 1989108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 1994063Seric { 2007275Seric (void) fflush(stdout); 2019277Seric if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 2027613Seric fprintf(OutChannel, "%s\r\n", msg); 2034711Seric else 2047613Seric fprintf(OutChannel, "%s\n", &msg[4]); 2054711Seric (void) fflush(OutChannel); 2064063Seric } 2079389Seric } 2089389Seric /* 2099389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2109389Seric ** 2119389Seric ** Parameters: 2129389Seric ** msg -- the message to output. 2139389Seric ** 2149389Seric ** Returns: 2159389Seric ** none. 2169389Seric ** 2179389Seric ** Side Effects: 2189389Seric ** Sets the fatal error bit in the envelope as appropriate. 2199389Seric */ 2208239Seric 2219389Seric puterrmsg(msg) 2229389Seric char *msg; 2239389Seric { 2249389Seric /* output the message as usual */ 2259389Seric putmsg(msg, HoldErrs); 2269389Seric 2279389Seric /* signal the error */ 2289389Seric Errors++; 2299389Seric if (msg[0] == '5') 2309336Seric CurEnv->e_flags |= EF_FATALERRS; 2314711Seric } 2324711Seric /* 2334711Seric ** FMTMSG -- format a message into buffer. 2344711Seric ** 2354711Seric ** Parameters: 2364711Seric ** eb -- error buffer to get result. 2374711Seric ** to -- the recipient tag for this message. 2384711Seric ** num -- arpanet error number. 23916901Seric ** en -- the error number to display. 2404711Seric ** fmt -- format of string. 2414711Seric ** a, b, c, d, e -- arguments. 2424711Seric ** 2434711Seric ** Returns: 2444711Seric ** none. 2454711Seric ** 2464711Seric ** Side Effects: 2474711Seric ** none. 2484711Seric */ 2494063Seric 25016901Seric /*VARARGS5*/ 25146928Sbostic static void 25216901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e) 2534711Seric register char *eb; 2544711Seric char *to; 2554711Seric char *num; 25616904Seric int eno; 2574711Seric char *fmt; 2584711Seric { 2594711Seric char del; 2604711Seric 2614711Seric /* output the reply code */ 26224943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2634577Seric { 2644711Seric num = fmt; 2654711Seric fmt += 4; 2664711Seric } 2674711Seric if (num[3] == '-') 2684711Seric del = '-'; 2694711Seric else 2704711Seric del = ' '; 2714711Seric (void) sprintf(eb, "%3.3s%c", num, del); 2724711Seric eb += 4; 2734063Seric 2749372Seric /* output the file name and line number */ 2759372Seric if (FileName != NULL) 2769372Seric { 2779372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 2789372Seric eb += strlen(eb); 2799372Seric } 2809372Seric 2814711Seric /* output the "to" person */ 2824711Seric if (to != NULL && to[0] != '\0') 2834711Seric { 2844711Seric (void) sprintf(eb, "%s... ", to); 2855201Seric while (*eb != '\0') 2865201Seric *eb++ &= 0177; 2874711Seric } 2884711Seric 2894711Seric /* output the message */ 2904711Seric (void) sprintf(eb, fmt, a, b, c, d, e); 2915201Seric while (*eb != '\0') 2925201Seric *eb++ &= 0177; 2934711Seric 2944711Seric /* output the error code, if any */ 29516904Seric if (eno != 0) 2964711Seric { 29715136Seric extern char *errstring(); 29815136Seric 29916904Seric (void) sprintf(eb, ": %s", errstring(eno)); 3004711Seric eb += strlen(eb); 3014577Seric } 302295Seric } 30315136Seric /* 30415136Seric ** ERRSTRING -- return string description of error code 30515136Seric ** 30615136Seric ** Parameters: 30715136Seric ** errno -- the error number to translate 30815136Seric ** 30915136Seric ** Returns: 31015136Seric ** A string description of errno. 31115136Seric ** 31215136Seric ** Side Effects: 31315136Seric ** none. 31415136Seric */ 31515136Seric 31615136Seric char * 31715136Seric errstring(errno) 31815136Seric int errno; 31915136Seric { 32015136Seric extern char *sys_errlist[]; 32115136Seric extern int sys_nerr; 32224943Seric static char buf[100]; 32324943Seric # ifdef SMTP 32424943Seric extern char *SmtpPhase; 32524943Seric # endif SMTP 32615136Seric 32724943Seric # ifdef DAEMON 32824943Seric # ifdef VMUNIX 32924943Seric /* 33024943Seric ** Handle special network error codes. 33124943Seric ** 33224943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 33324943Seric */ 33424943Seric 33524943Seric switch (errno) 33624943Seric { 33724943Seric case ETIMEDOUT: 33824943Seric case ECONNRESET: 33924943Seric (void) strcpy(buf, sys_errlist[errno]); 34024943Seric if (SmtpPhase != NULL) 34124943Seric { 34224943Seric (void) strcat(buf, " during "); 34324943Seric (void) strcat(buf, SmtpPhase); 34424943Seric } 34525050Seric if (CurHostName != NULL) 34624943Seric { 34724943Seric (void) strcat(buf, " with "); 34825050Seric (void) strcat(buf, CurHostName); 34924943Seric } 35024943Seric return (buf); 35124943Seric 35224943Seric case EHOSTDOWN: 35325050Seric if (CurHostName == NULL) 35424943Seric break; 35525050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 35624943Seric return (buf); 35724943Seric 35824943Seric case ECONNREFUSED: 35925050Seric if (CurHostName == NULL) 36024943Seric break; 36125050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 36224943Seric return (buf); 36325526Smiriam 36425526Smiriam case (TRY_AGAIN+MAX_ERRNO): 36525526Smiriam (void) sprintf(buf, "Host Name Lookup Failure"); 36625526Smiriam return (buf); 36724943Seric } 36824943Seric # endif VMUNIX 36924943Seric # endif DAEMON 37024943Seric 37115136Seric if (errno > 0 && errno < sys_nerr) 37215136Seric return (sys_errlist[errno]); 37315136Seric 37415136Seric (void) sprintf(buf, "Error %d", errno); 37515136Seric return (buf); 37615136Seric } 377