122705Sdist /* 2*34921Sbostic * Copyright (c) 1983 Eric P. Allman 333729Sbostic * Copyright (c) 1988 Regents of the University of California. 433729Sbostic * All rights reserved. 533729Sbostic * 633729Sbostic * Redistribution and use in source and binary forms are permitted 7*34921Sbostic * provided that the above copyright notice and this paragraph are 8*34921Sbostic * duplicated in all such forms and that any documentation, 9*34921Sbostic * advertising materials, and other materials related to such 10*34921Sbostic * distribution and use acknowledge that the software was developed 11*34921Sbostic * by the University of California, Berkeley. The name of the 12*34921Sbostic * University may not be used to endorse or promote products derived 13*34921Sbostic * from this software without specific prior written permission. 14*34921Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15*34921Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16*34921Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1733729Sbostic */ 1822705Sdist 1922705Sdist #ifndef lint 20*34921Sbostic static char sccsid[] = "@(#)err.c 5.9 (Berkeley) 06/30/88"; 2133729Sbostic #endif /* not lint */ 2222705Sdist 233311Seric # include "sendmail.h" 2424943Seric # include <errno.h> 2525526Smiriam # include <netdb.h> 26295Seric 27295Seric /* 281514Seric ** SYSERR -- Print error message. 29295Seric ** 30295Seric ** Prints an error message via printf to the diagnostic 31295Seric ** output. If LOG is defined, it logs it also. 32295Seric ** 33295Seric ** Parameters: 34295Seric ** f -- the format string 35295Seric ** a, b, c, d, e -- parameters 36295Seric ** 37295Seric ** Returns: 384084Seric ** none 397762Seric ** Through TopFrame if QuickAbort is set. 40295Seric ** 41295Seric ** Side Effects: 421514Seric ** increments Errors. 431514Seric ** sets ExitStat. 44295Seric */ 45295Seric 464084Seric # ifdef lint 474084Seric int sys_nerr; 484084Seric char *sys_errlist[]; 494084Seric # endif lint 5010147Seric char MsgBuf[BUFSIZ*2]; /* text of most recent message */ 514084Seric 52295Seric /*VARARGS1*/ 53295Seric syserr(fmt, a, b, c, d, e) 54295Seric char *fmt; 55295Seric { 5616901Seric register char *p; 5716901Seric int olderrno = errno; 587957Seric extern char Arpa_PSyserr[]; 597957Seric extern char Arpa_TSyserr[]; 60295Seric 617525Seric /* format and output the error message */ 6216901Seric if (olderrno == 0) 637957Seric p = Arpa_PSyserr; 647957Seric else 657957Seric p = Arpa_TSyserr; 6616901Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e); 679389Seric puterrmsg(MsgBuf); 684063Seric 69295Seric /* determine exit status if not already set */ 70295Seric if (ExitStat == EX_OK) 71295Seric { 7216901Seric if (olderrno == 0) 73295Seric ExitStat = EX_SOFTWARE; 74295Seric else 751598Seric ExitStat = EX_OSERR; 76295Seric } 77295Seric 78295Seric # ifdef LOG 797674Seric if (LogLevel > 0) 8025277Seric syslog(LOG_CRIT, "%s: SYSERR: %s", 8125277Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 8225277Seric &MsgBuf[4]); 83295Seric # endif LOG 84295Seric errno = 0; 857762Seric if (QuickAbort) 867762Seric longjmp(TopFrame, 2); 87295Seric } 88295Seric /* 89295Seric ** USRERR -- Signal user error. 90295Seric ** 91295Seric ** This is much like syserr except it is for user errors. 92295Seric ** 93295Seric ** Parameters: 94295Seric ** fmt, a, b, c, d -- printf strings 95295Seric ** 96295Seric ** Returns: 974084Seric ** none 987762Seric ** Through TopFrame if QuickAbort is set. 99295Seric ** 100295Seric ** Side Effects: 1011514Seric ** increments Errors. 102295Seric */ 103295Seric 104295Seric /*VARARGS1*/ 105295Seric usrerr(fmt, a, b, c, d, e) 106295Seric char *fmt; 107295Seric { 108295Seric extern char SuprErrs; 1094167Seric extern char Arpa_Usrerr[]; 11016901Seric extern int errno; 111295Seric 112295Seric if (SuprErrs) 1134084Seric return; 114295Seric 11516901Seric fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e); 1169389Seric puterrmsg(MsgBuf); 1178239Seric 1187762Seric if (QuickAbort) 1197762Seric longjmp(TopFrame, 1); 1204063Seric } 1214063Seric /* 1224063Seric ** MESSAGE -- print message (not necessarily an error) 1234063Seric ** 1244063Seric ** Parameters: 1254063Seric ** num -- the default ARPANET error number (in ascii) 1264063Seric ** msg -- the message (printf fmt) -- if it begins 1274063Seric ** with a digit, this number overrides num. 1284063Seric ** a, b, c, d, e -- printf arguments 1294063Seric ** 1304063Seric ** Returns: 1314063Seric ** none 1324063Seric ** 1334063Seric ** Side Effects: 1344063Seric ** none. 1354063Seric */ 1364063Seric 1374084Seric /*VARARGS2*/ 1384063Seric message(num, msg, a, b, c, d, e) 1394063Seric register char *num; 1404063Seric register char *msg; 1414063Seric { 1424711Seric errno = 0; 14316901Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e); 1449108Seric putmsg(MsgBuf, FALSE); 1457613Seric } 1467613Seric /* 1478239Seric ** NMESSAGE -- print message (not necessarily an error) 1488239Seric ** 1498239Seric ** Just like "message" except it never puts the to... tag on. 1508239Seric ** 1518239Seric ** Parameters: 1528239Seric ** num -- the default ARPANET error number (in ascii) 1538239Seric ** msg -- the message (printf fmt) -- if it begins 15424943Seric ** with three digits, this number overrides num. 1558239Seric ** a, b, c, d, e -- printf arguments 1568239Seric ** 1578239Seric ** Returns: 1588239Seric ** none 1598239Seric ** 1608239Seric ** Side Effects: 1618239Seric ** none. 1628239Seric */ 1638239Seric 1648239Seric /*VARARGS2*/ 1658239Seric nmessage(num, msg, a, b, c, d, e) 1668239Seric register char *num; 1678239Seric register char *msg; 1688239Seric { 1698239Seric errno = 0; 17016901Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e); 1719108Seric putmsg(MsgBuf, FALSE); 1728239Seric } 1738239Seric /* 1747613Seric ** PUTMSG -- output error message to transcript and channel 1757613Seric ** 1767613Seric ** Parameters: 1777613Seric ** msg -- message to output (in SMTP format). 1789108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 1799108Seric ** our output channel. 1807613Seric ** 1817613Seric ** Returns: 1827613Seric ** none. 1837613Seric ** 1847613Seric ** Side Effects: 1857613Seric ** Outputs msg to the transcript. 1867613Seric ** If appropriate, outputs it to the channel. 1877613Seric ** Deletes SMTP reply code number as appropriate. 1887613Seric */ 1894711Seric 1909108Seric putmsg(msg, holdmsg) 1917613Seric char *msg; 1929108Seric bool holdmsg; 1937613Seric { 19414900Seric /* output to transcript if serious */ 19514900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 19614900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 1974711Seric 1984711Seric /* output to channel if appropriate */ 1999108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 2004063Seric { 2017275Seric (void) fflush(stdout); 2029277Seric if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 2037613Seric fprintf(OutChannel, "%s\r\n", msg); 2044711Seric else 2057613Seric fprintf(OutChannel, "%s\n", &msg[4]); 2064711Seric (void) fflush(OutChannel); 2074063Seric } 2089389Seric } 2099389Seric /* 2109389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2119389Seric ** 2129389Seric ** Parameters: 2139389Seric ** msg -- the message to output. 2149389Seric ** 2159389Seric ** Returns: 2169389Seric ** none. 2179389Seric ** 2189389Seric ** Side Effects: 2199389Seric ** Sets the fatal error bit in the envelope as appropriate. 2209389Seric */ 2218239Seric 2229389Seric puterrmsg(msg) 2239389Seric char *msg; 2249389Seric { 2259389Seric /* output the message as usual */ 2269389Seric putmsg(msg, HoldErrs); 2279389Seric 2289389Seric /* signal the error */ 2299389Seric Errors++; 2309389Seric if (msg[0] == '5') 2319336Seric CurEnv->e_flags |= EF_FATALERRS; 2324711Seric } 2334711Seric /* 2344711Seric ** FMTMSG -- format a message into buffer. 2354711Seric ** 2364711Seric ** Parameters: 2374711Seric ** eb -- error buffer to get result. 2384711Seric ** to -- the recipient tag for this message. 2394711Seric ** num -- arpanet error number. 24016901Seric ** en -- the error number to display. 2414711Seric ** fmt -- format of string. 2424711Seric ** a, b, c, d, e -- arguments. 2434711Seric ** 2444711Seric ** Returns: 2454711Seric ** none. 2464711Seric ** 2474711Seric ** Side Effects: 2484711Seric ** none. 2494711Seric */ 2504063Seric 25116901Seric /*VARARGS5*/ 2524711Seric static 25316901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e) 2544711Seric register char *eb; 2554711Seric char *to; 2564711Seric char *num; 25716904Seric int eno; 2584711Seric char *fmt; 2594711Seric { 2604711Seric char del; 2614711Seric 2624711Seric /* output the reply code */ 26324943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2644577Seric { 2654711Seric num = fmt; 2664711Seric fmt += 4; 2674711Seric } 2684711Seric if (num[3] == '-') 2694711Seric del = '-'; 2704711Seric else 2714711Seric del = ' '; 2724711Seric (void) sprintf(eb, "%3.3s%c", num, del); 2734711Seric eb += 4; 2744063Seric 2759372Seric /* output the file name and line number */ 2769372Seric if (FileName != NULL) 2779372Seric { 2789372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 2799372Seric eb += strlen(eb); 2809372Seric } 2819372Seric 2824711Seric /* output the "to" person */ 2834711Seric if (to != NULL && to[0] != '\0') 2844711Seric { 2854711Seric (void) sprintf(eb, "%s... ", to); 2865201Seric while (*eb != '\0') 2875201Seric *eb++ &= 0177; 2884711Seric } 2894711Seric 2904711Seric /* output the message */ 2914711Seric (void) sprintf(eb, fmt, a, b, c, d, e); 2925201Seric while (*eb != '\0') 2935201Seric *eb++ &= 0177; 2944711Seric 2954711Seric /* output the error code, if any */ 29616904Seric if (eno != 0) 2974711Seric { 29815136Seric extern char *errstring(); 29915136Seric 30016904Seric (void) sprintf(eb, ": %s", errstring(eno)); 3014711Seric eb += strlen(eb); 3024577Seric } 303295Seric } 30415136Seric /* 30515136Seric ** ERRSTRING -- return string description of error code 30615136Seric ** 30715136Seric ** Parameters: 30815136Seric ** errno -- the error number to translate 30915136Seric ** 31015136Seric ** Returns: 31115136Seric ** A string description of errno. 31215136Seric ** 31315136Seric ** Side Effects: 31415136Seric ** none. 31515136Seric */ 31615136Seric 31715136Seric char * 31815136Seric errstring(errno) 31915136Seric int errno; 32015136Seric { 32115136Seric extern char *sys_errlist[]; 32215136Seric extern int sys_nerr; 32324943Seric static char buf[100]; 32424943Seric # ifdef SMTP 32524943Seric extern char *SmtpPhase; 32624943Seric # endif SMTP 32715136Seric 32824943Seric # ifdef DAEMON 32924943Seric # ifdef VMUNIX 33024943Seric /* 33124943Seric ** Handle special network error codes. 33224943Seric ** 33324943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 33424943Seric */ 33524943Seric 33624943Seric switch (errno) 33724943Seric { 33824943Seric case ETIMEDOUT: 33924943Seric case ECONNRESET: 34024943Seric (void) strcpy(buf, sys_errlist[errno]); 34124943Seric if (SmtpPhase != NULL) 34224943Seric { 34324943Seric (void) strcat(buf, " during "); 34424943Seric (void) strcat(buf, SmtpPhase); 34524943Seric } 34625050Seric if (CurHostName != NULL) 34724943Seric { 34824943Seric (void) strcat(buf, " with "); 34925050Seric (void) strcat(buf, CurHostName); 35024943Seric } 35124943Seric return (buf); 35224943Seric 35324943Seric case EHOSTDOWN: 35425050Seric if (CurHostName == NULL) 35524943Seric break; 35625050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 35724943Seric return (buf); 35824943Seric 35924943Seric case ECONNREFUSED: 36025050Seric if (CurHostName == NULL) 36124943Seric break; 36225050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 36324943Seric return (buf); 36425526Smiriam 36525526Smiriam case (TRY_AGAIN+MAX_ERRNO): 36625526Smiriam (void) sprintf(buf, "Host Name Lookup Failure"); 36725526Smiriam return (buf); 36824943Seric } 36924943Seric # endif VMUNIX 37024943Seric # endif DAEMON 37124943Seric 37215136Seric if (errno > 0 && errno < sys_nerr) 37315136Seric return (sys_errlist[errno]); 37415136Seric 37515136Seric (void) sprintf(buf, "Error %d", errno); 37615136Seric return (buf); 37715136Seric } 378