122705Sdist /* 222705Sdist ** Sendmail 322705Sdist ** Copyright (c) 1983 Eric P. Allman 422705Sdist ** Berkeley, California 522705Sdist ** 622705Sdist ** Copyright (c) 1983 Regents of the University of California. 722705Sdist ** All rights reserved. The Berkeley software License Agreement 822705Sdist ** specifies the terms and conditions for redistribution. 922705Sdist */ 1022705Sdist 1122705Sdist #ifndef lint 12*25526Smiriam static char SccsId[] = "@(#)err.c 5.7 (Berkeley) 11/22/85"; 1322705Sdist #endif not lint 1422705Sdist 153311Seric # include "sendmail.h" 1624943Seric # include <errno.h> 17*25526Smiriam # include <netdb.h> 18295Seric 19295Seric /* 201514Seric ** SYSERR -- Print error message. 21295Seric ** 22295Seric ** Prints an error message via printf to the diagnostic 23295Seric ** output. If LOG is defined, it logs it also. 24295Seric ** 25295Seric ** Parameters: 26295Seric ** f -- the format string 27295Seric ** a, b, c, d, e -- parameters 28295Seric ** 29295Seric ** Returns: 304084Seric ** none 317762Seric ** Through TopFrame if QuickAbort is set. 32295Seric ** 33295Seric ** Side Effects: 341514Seric ** increments Errors. 351514Seric ** sets ExitStat. 36295Seric */ 37295Seric 384084Seric # ifdef lint 394084Seric int sys_nerr; 404084Seric char *sys_errlist[]; 414084Seric # endif lint 4210147Seric char MsgBuf[BUFSIZ*2]; /* text of most recent message */ 434084Seric 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 1107762Seric if (QuickAbort) 1117762Seric longjmp(TopFrame, 1); 1124063Seric } 1134063Seric /* 1144063Seric ** MESSAGE -- print message (not necessarily an error) 1154063Seric ** 1164063Seric ** Parameters: 1174063Seric ** num -- the default ARPANET error number (in ascii) 1184063Seric ** msg -- the message (printf fmt) -- if it begins 1194063Seric ** with a digit, this number overrides num. 1204063Seric ** a, b, c, d, e -- printf arguments 1214063Seric ** 1224063Seric ** Returns: 1234063Seric ** none 1244063Seric ** 1254063Seric ** Side Effects: 1264063Seric ** none. 1274063Seric */ 1284063Seric 1294084Seric /*VARARGS2*/ 1304063Seric message(num, msg, a, b, c, d, e) 1314063Seric register char *num; 1324063Seric register char *msg; 1334063Seric { 1344711Seric errno = 0; 13516901Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e); 1369108Seric putmsg(MsgBuf, FALSE); 1377613Seric } 1387613Seric /* 1398239Seric ** NMESSAGE -- print message (not necessarily an error) 1408239Seric ** 1418239Seric ** Just like "message" except it never puts the to... tag on. 1428239Seric ** 1438239Seric ** Parameters: 1448239Seric ** num -- the default ARPANET error number (in ascii) 1458239Seric ** msg -- the message (printf fmt) -- if it begins 14624943Seric ** with three digits, this number overrides num. 1478239Seric ** a, b, c, d, e -- printf arguments 1488239Seric ** 1498239Seric ** Returns: 1508239Seric ** none 1518239Seric ** 1528239Seric ** Side Effects: 1538239Seric ** none. 1548239Seric */ 1558239Seric 1568239Seric /*VARARGS2*/ 1578239Seric nmessage(num, msg, a, b, c, d, e) 1588239Seric register char *num; 1598239Seric register char *msg; 1608239Seric { 1618239Seric errno = 0; 16216901Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e); 1639108Seric putmsg(MsgBuf, FALSE); 1648239Seric } 1658239Seric /* 1667613Seric ** PUTMSG -- output error message to transcript and channel 1677613Seric ** 1687613Seric ** Parameters: 1697613Seric ** msg -- message to output (in SMTP format). 1709108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 1719108Seric ** our output channel. 1727613Seric ** 1737613Seric ** Returns: 1747613Seric ** none. 1757613Seric ** 1767613Seric ** Side Effects: 1777613Seric ** Outputs msg to the transcript. 1787613Seric ** If appropriate, outputs it to the channel. 1797613Seric ** Deletes SMTP reply code number as appropriate. 1807613Seric */ 1814711Seric 1829108Seric putmsg(msg, holdmsg) 1837613Seric char *msg; 1849108Seric bool holdmsg; 1857613Seric { 18614900Seric /* output to transcript if serious */ 18714900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 18814900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 1894711Seric 1904711Seric /* output to channel if appropriate */ 1919108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 1924063Seric { 1937275Seric (void) fflush(stdout); 1949277Seric if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 1957613Seric fprintf(OutChannel, "%s\r\n", msg); 1964711Seric else 1977613Seric fprintf(OutChannel, "%s\n", &msg[4]); 1984711Seric (void) fflush(OutChannel); 1994063Seric } 2009389Seric } 2019389Seric /* 2029389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2039389Seric ** 2049389Seric ** Parameters: 2059389Seric ** msg -- the message to output. 2069389Seric ** 2079389Seric ** Returns: 2089389Seric ** none. 2099389Seric ** 2109389Seric ** Side Effects: 2119389Seric ** Sets the fatal error bit in the envelope as appropriate. 2129389Seric */ 2138239Seric 2149389Seric puterrmsg(msg) 2159389Seric char *msg; 2169389Seric { 2179389Seric /* output the message as usual */ 2189389Seric putmsg(msg, HoldErrs); 2199389Seric 2209389Seric /* signal the error */ 2219389Seric Errors++; 2229389Seric if (msg[0] == '5') 2239336Seric CurEnv->e_flags |= EF_FATALERRS; 2244711Seric } 2254711Seric /* 2264711Seric ** FMTMSG -- format a message into buffer. 2274711Seric ** 2284711Seric ** Parameters: 2294711Seric ** eb -- error buffer to get result. 2304711Seric ** to -- the recipient tag for this message. 2314711Seric ** num -- arpanet error number. 23216901Seric ** en -- the error number to display. 2334711Seric ** fmt -- format of string. 2344711Seric ** a, b, c, d, e -- arguments. 2354711Seric ** 2364711Seric ** Returns: 2374711Seric ** none. 2384711Seric ** 2394711Seric ** Side Effects: 2404711Seric ** none. 2414711Seric */ 2424063Seric 24316901Seric /*VARARGS5*/ 2444711Seric static 24516901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e) 2464711Seric register char *eb; 2474711Seric char *to; 2484711Seric char *num; 24916904Seric int eno; 2504711Seric char *fmt; 2514711Seric { 2524711Seric char del; 2534711Seric 2544711Seric /* output the reply code */ 25524943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2564577Seric { 2574711Seric num = fmt; 2584711Seric fmt += 4; 2594711Seric } 2604711Seric if (num[3] == '-') 2614711Seric del = '-'; 2624711Seric else 2634711Seric del = ' '; 2644711Seric (void) sprintf(eb, "%3.3s%c", num, del); 2654711Seric eb += 4; 2664063Seric 2679372Seric /* output the file name and line number */ 2689372Seric if (FileName != NULL) 2699372Seric { 2709372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 2719372Seric eb += strlen(eb); 2729372Seric } 2739372Seric 2744711Seric /* output the "to" person */ 2754711Seric if (to != NULL && to[0] != '\0') 2764711Seric { 2774711Seric (void) sprintf(eb, "%s... ", to); 2785201Seric while (*eb != '\0') 2795201Seric *eb++ &= 0177; 2804711Seric } 2814711Seric 2824711Seric /* output the message */ 2834711Seric (void) sprintf(eb, fmt, a, b, c, d, e); 2845201Seric while (*eb != '\0') 2855201Seric *eb++ &= 0177; 2864711Seric 2874711Seric /* output the error code, if any */ 28816904Seric if (eno != 0) 2894711Seric { 29015136Seric extern char *errstring(); 29115136Seric 29216904Seric (void) sprintf(eb, ": %s", errstring(eno)); 2934711Seric eb += strlen(eb); 2944577Seric } 295295Seric } 29615136Seric /* 29715136Seric ** ERRSTRING -- return string description of error code 29815136Seric ** 29915136Seric ** Parameters: 30015136Seric ** errno -- the error number to translate 30115136Seric ** 30215136Seric ** Returns: 30315136Seric ** A string description of errno. 30415136Seric ** 30515136Seric ** Side Effects: 30615136Seric ** none. 30715136Seric */ 30815136Seric 30915136Seric char * 31015136Seric errstring(errno) 31115136Seric int errno; 31215136Seric { 31315136Seric extern char *sys_errlist[]; 31415136Seric extern int sys_nerr; 31524943Seric static char buf[100]; 31624943Seric # ifdef SMTP 31724943Seric extern char *SmtpPhase; 31824943Seric # endif SMTP 31915136Seric 32024943Seric # ifdef DAEMON 32124943Seric # ifdef VMUNIX 32224943Seric /* 32324943Seric ** Handle special network error codes. 32424943Seric ** 32524943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 32624943Seric */ 32724943Seric 32824943Seric switch (errno) 32924943Seric { 33024943Seric case ETIMEDOUT: 33124943Seric case ECONNRESET: 33224943Seric (void) strcpy(buf, sys_errlist[errno]); 33324943Seric if (SmtpPhase != NULL) 33424943Seric { 33524943Seric (void) strcat(buf, " during "); 33624943Seric (void) strcat(buf, SmtpPhase); 33724943Seric } 33825050Seric if (CurHostName != NULL) 33924943Seric { 34024943Seric (void) strcat(buf, " with "); 34125050Seric (void) strcat(buf, CurHostName); 34224943Seric } 34324943Seric return (buf); 34424943Seric 34524943Seric case EHOSTDOWN: 34625050Seric if (CurHostName == NULL) 34724943Seric break; 34825050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 34924943Seric return (buf); 35024943Seric 35124943Seric case ECONNREFUSED: 35225050Seric if (CurHostName == NULL) 35324943Seric break; 35425050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 35524943Seric return (buf); 356*25526Smiriam 357*25526Smiriam case (TRY_AGAIN+MAX_ERRNO): 358*25526Smiriam (void) sprintf(buf, "Host Name Lookup Failure"); 359*25526Smiriam return (buf); 36024943Seric } 36124943Seric # endif VMUNIX 36224943Seric # endif DAEMON 36324943Seric 36415136Seric if (errno > 0 && errno < sys_nerr) 36515136Seric return (sys_errlist[errno]); 36615136Seric 36715136Seric (void) sprintf(buf, "Error %d", errno); 36815136Seric return (buf); 36915136Seric } 370