122705Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 333729Sbostic * Copyright (c) 1988 Regents of the University of California. 433729Sbostic * All rights reserved. 533729Sbostic * 6*42826Sbostic * %sccs.include.redist.c% 733729Sbostic */ 822705Sdist 922705Sdist #ifndef lint 10*42826Sbostic static char sccsid[] = "@(#)err.c 5.10 (Berkeley) 06/01/90"; 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 42295Seric /*VARARGS1*/ 43295Seric syserr(fmt, a, b, c, d, e) 44295Seric char *fmt; 45295Seric { 4616901Seric register char *p; 4716901Seric int olderrno = errno; 487957Seric extern char Arpa_PSyserr[]; 497957Seric extern char Arpa_TSyserr[]; 50295Seric 517525Seric /* format and output the error message */ 5216901Seric if (olderrno == 0) 537957Seric p = Arpa_PSyserr; 547957Seric else 557957Seric p = Arpa_TSyserr; 5616901Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e); 579389Seric puterrmsg(MsgBuf); 584063Seric 59295Seric /* determine exit status if not already set */ 60295Seric if (ExitStat == EX_OK) 61295Seric { 6216901Seric if (olderrno == 0) 63295Seric ExitStat = EX_SOFTWARE; 64295Seric else 651598Seric ExitStat = EX_OSERR; 66295Seric } 67295Seric 68295Seric # ifdef LOG 697674Seric if (LogLevel > 0) 7025277Seric syslog(LOG_CRIT, "%s: SYSERR: %s", 7125277Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 7225277Seric &MsgBuf[4]); 73295Seric # endif LOG 74295Seric errno = 0; 757762Seric if (QuickAbort) 767762Seric longjmp(TopFrame, 2); 77295Seric } 78295Seric /* 79295Seric ** USRERR -- Signal user error. 80295Seric ** 81295Seric ** This is much like syserr except it is for user errors. 82295Seric ** 83295Seric ** Parameters: 84295Seric ** fmt, a, b, c, d -- printf strings 85295Seric ** 86295Seric ** Returns: 874084Seric ** none 887762Seric ** Through TopFrame if QuickAbort is set. 89295Seric ** 90295Seric ** Side Effects: 911514Seric ** increments Errors. 92295Seric */ 93295Seric 94295Seric /*VARARGS1*/ 95295Seric usrerr(fmt, a, b, c, d, e) 96295Seric char *fmt; 97295Seric { 98295Seric extern char SuprErrs; 994167Seric extern char Arpa_Usrerr[]; 10016901Seric extern int errno; 101295Seric 102295Seric if (SuprErrs) 1034084Seric return; 104295Seric 10516901Seric fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e); 1069389Seric puterrmsg(MsgBuf); 1078239Seric 1087762Seric if (QuickAbort) 1097762Seric longjmp(TopFrame, 1); 1104063Seric } 1114063Seric /* 1124063Seric ** MESSAGE -- print message (not necessarily an error) 1134063Seric ** 1144063Seric ** Parameters: 1154063Seric ** num -- the default ARPANET error number (in ascii) 1164063Seric ** msg -- the message (printf fmt) -- if it begins 1174063Seric ** with a digit, this number overrides num. 1184063Seric ** a, b, c, d, e -- printf arguments 1194063Seric ** 1204063Seric ** Returns: 1214063Seric ** none 1224063Seric ** 1234063Seric ** Side Effects: 1244063Seric ** none. 1254063Seric */ 1264063Seric 1274084Seric /*VARARGS2*/ 1284063Seric message(num, msg, a, b, c, d, e) 1294063Seric register char *num; 1304063Seric register char *msg; 1314063Seric { 1324711Seric errno = 0; 13316901Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e); 1349108Seric putmsg(MsgBuf, FALSE); 1357613Seric } 1367613Seric /* 1378239Seric ** NMESSAGE -- print message (not necessarily an error) 1388239Seric ** 1398239Seric ** Just like "message" except it never puts the to... tag on. 1408239Seric ** 1418239Seric ** Parameters: 1428239Seric ** num -- the default ARPANET error number (in ascii) 1438239Seric ** msg -- the message (printf fmt) -- if it begins 14424943Seric ** with three digits, this number overrides num. 1458239Seric ** a, b, c, d, e -- printf arguments 1468239Seric ** 1478239Seric ** Returns: 1488239Seric ** none 1498239Seric ** 1508239Seric ** Side Effects: 1518239Seric ** none. 1528239Seric */ 1538239Seric 1548239Seric /*VARARGS2*/ 1558239Seric nmessage(num, msg, a, b, c, d, e) 1568239Seric register char *num; 1578239Seric register char *msg; 1588239Seric { 1598239Seric errno = 0; 16016901Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e); 1619108Seric putmsg(MsgBuf, FALSE); 1628239Seric } 1638239Seric /* 1647613Seric ** PUTMSG -- output error message to transcript and channel 1657613Seric ** 1667613Seric ** Parameters: 1677613Seric ** msg -- message to output (in SMTP format). 1689108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 1699108Seric ** our output channel. 1707613Seric ** 1717613Seric ** Returns: 1727613Seric ** none. 1737613Seric ** 1747613Seric ** Side Effects: 1757613Seric ** Outputs msg to the transcript. 1767613Seric ** If appropriate, outputs it to the channel. 1777613Seric ** Deletes SMTP reply code number as appropriate. 1787613Seric */ 1794711Seric 1809108Seric putmsg(msg, holdmsg) 1817613Seric char *msg; 1829108Seric bool holdmsg; 1837613Seric { 18414900Seric /* output to transcript if serious */ 18514900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 18614900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 1874711Seric 1884711Seric /* output to channel if appropriate */ 1899108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 1904063Seric { 1917275Seric (void) fflush(stdout); 1929277Seric if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 1937613Seric fprintf(OutChannel, "%s\r\n", msg); 1944711Seric else 1957613Seric fprintf(OutChannel, "%s\n", &msg[4]); 1964711Seric (void) fflush(OutChannel); 1974063Seric } 1989389Seric } 1999389Seric /* 2009389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2019389Seric ** 2029389Seric ** Parameters: 2039389Seric ** msg -- the message to output. 2049389Seric ** 2059389Seric ** Returns: 2069389Seric ** none. 2079389Seric ** 2089389Seric ** Side Effects: 2099389Seric ** Sets the fatal error bit in the envelope as appropriate. 2109389Seric */ 2118239Seric 2129389Seric puterrmsg(msg) 2139389Seric char *msg; 2149389Seric { 2159389Seric /* output the message as usual */ 2169389Seric putmsg(msg, HoldErrs); 2179389Seric 2189389Seric /* signal the error */ 2199389Seric Errors++; 2209389Seric if (msg[0] == '5') 2219336Seric CurEnv->e_flags |= EF_FATALERRS; 2224711Seric } 2234711Seric /* 2244711Seric ** FMTMSG -- format a message into buffer. 2254711Seric ** 2264711Seric ** Parameters: 2274711Seric ** eb -- error buffer to get result. 2284711Seric ** to -- the recipient tag for this message. 2294711Seric ** num -- arpanet error number. 23016901Seric ** en -- the error number to display. 2314711Seric ** fmt -- format of string. 2324711Seric ** a, b, c, d, e -- arguments. 2334711Seric ** 2344711Seric ** Returns: 2354711Seric ** none. 2364711Seric ** 2374711Seric ** Side Effects: 2384711Seric ** none. 2394711Seric */ 2404063Seric 24116901Seric /*VARARGS5*/ 2424711Seric static 24316901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e) 2444711Seric register char *eb; 2454711Seric char *to; 2464711Seric char *num; 24716904Seric int eno; 2484711Seric char *fmt; 2494711Seric { 2504711Seric char del; 2514711Seric 2524711Seric /* output the reply code */ 25324943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2544577Seric { 2554711Seric num = fmt; 2564711Seric fmt += 4; 2574711Seric } 2584711Seric if (num[3] == '-') 2594711Seric del = '-'; 2604711Seric else 2614711Seric del = ' '; 2624711Seric (void) sprintf(eb, "%3.3s%c", num, del); 2634711Seric eb += 4; 2644063Seric 2659372Seric /* output the file name and line number */ 2669372Seric if (FileName != NULL) 2679372Seric { 2689372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 2699372Seric eb += strlen(eb); 2709372Seric } 2719372Seric 2724711Seric /* output the "to" person */ 2734711Seric if (to != NULL && to[0] != '\0') 2744711Seric { 2754711Seric (void) sprintf(eb, "%s... ", to); 2765201Seric while (*eb != '\0') 2775201Seric *eb++ &= 0177; 2784711Seric } 2794711Seric 2804711Seric /* output the message */ 2814711Seric (void) sprintf(eb, fmt, a, b, c, d, e); 2825201Seric while (*eb != '\0') 2835201Seric *eb++ &= 0177; 2844711Seric 2854711Seric /* output the error code, if any */ 28616904Seric if (eno != 0) 2874711Seric { 28815136Seric extern char *errstring(); 28915136Seric 29016904Seric (void) sprintf(eb, ": %s", errstring(eno)); 2914711Seric eb += strlen(eb); 2924577Seric } 293295Seric } 29415136Seric /* 29515136Seric ** ERRSTRING -- return string description of error code 29615136Seric ** 29715136Seric ** Parameters: 29815136Seric ** errno -- the error number to translate 29915136Seric ** 30015136Seric ** Returns: 30115136Seric ** A string description of errno. 30215136Seric ** 30315136Seric ** Side Effects: 30415136Seric ** none. 30515136Seric */ 30615136Seric 30715136Seric char * 30815136Seric errstring(errno) 30915136Seric int errno; 31015136Seric { 31115136Seric extern char *sys_errlist[]; 31215136Seric extern int sys_nerr; 31324943Seric static char buf[100]; 31424943Seric # ifdef SMTP 31524943Seric extern char *SmtpPhase; 31624943Seric # endif SMTP 31715136Seric 31824943Seric # ifdef DAEMON 31924943Seric # ifdef VMUNIX 32024943Seric /* 32124943Seric ** Handle special network error codes. 32224943Seric ** 32324943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 32424943Seric */ 32524943Seric 32624943Seric switch (errno) 32724943Seric { 32824943Seric case ETIMEDOUT: 32924943Seric case ECONNRESET: 33024943Seric (void) strcpy(buf, sys_errlist[errno]); 33124943Seric if (SmtpPhase != NULL) 33224943Seric { 33324943Seric (void) strcat(buf, " during "); 33424943Seric (void) strcat(buf, SmtpPhase); 33524943Seric } 33625050Seric if (CurHostName != NULL) 33724943Seric { 33824943Seric (void) strcat(buf, " with "); 33925050Seric (void) strcat(buf, CurHostName); 34024943Seric } 34124943Seric return (buf); 34224943Seric 34324943Seric case EHOSTDOWN: 34425050Seric if (CurHostName == NULL) 34524943Seric break; 34625050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 34724943Seric return (buf); 34824943Seric 34924943Seric case ECONNREFUSED: 35025050Seric if (CurHostName == NULL) 35124943Seric break; 35225050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 35324943Seric return (buf); 35425526Smiriam 35525526Smiriam case (TRY_AGAIN+MAX_ERRNO): 35625526Smiriam (void) sprintf(buf, "Host Name Lookup Failure"); 35725526Smiriam return (buf); 35824943Seric } 35924943Seric # endif VMUNIX 36024943Seric # endif DAEMON 36124943Seric 36215136Seric if (errno > 0 && errno < sys_nerr) 36315136Seric return (sys_errlist[errno]); 36415136Seric 36515136Seric (void) sprintf(buf, "Error %d", errno); 36615136Seric return (buf); 36715136Seric } 368