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*25050Seric static char SccsId[] = "@(#)err.c 5.5 (Berkeley) 09/30/85"; 1322705Sdist #endif not lint 1422705Sdist 153311Seric # include "sendmail.h" 1624943Seric # include <errno.h> 17295Seric 18295Seric /* 191514Seric ** SYSERR -- Print error message. 20295Seric ** 21295Seric ** Prints an error message via printf to the diagnostic 22295Seric ** output. If LOG is defined, it logs it also. 23295Seric ** 24295Seric ** Parameters: 25295Seric ** f -- the format string 26295Seric ** a, b, c, d, e -- parameters 27295Seric ** 28295Seric ** Returns: 294084Seric ** none 307762Seric ** Through TopFrame if QuickAbort is set. 31295Seric ** 32295Seric ** Side Effects: 331514Seric ** increments Errors. 341514Seric ** sets ExitStat. 35295Seric */ 36295Seric 374084Seric # ifdef lint 384084Seric int sys_nerr; 394084Seric char *sys_errlist[]; 404084Seric # endif lint 4110147Seric char MsgBuf[BUFSIZ*2]; /* text of most recent message */ 424084Seric 43295Seric /*VARARGS1*/ 44295Seric syserr(fmt, a, b, c, d, e) 45295Seric char *fmt; 46295Seric { 4716901Seric register char *p; 4816901Seric int olderrno = errno; 497957Seric extern char Arpa_PSyserr[]; 507957Seric extern char Arpa_TSyserr[]; 51295Seric 527525Seric /* format and output the error message */ 5316901Seric if (olderrno == 0) 547957Seric p = Arpa_PSyserr; 557957Seric else 567957Seric p = Arpa_TSyserr; 5716901Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e); 589389Seric puterrmsg(MsgBuf); 594063Seric 60295Seric /* determine exit status if not already set */ 61295Seric if (ExitStat == EX_OK) 62295Seric { 6316901Seric if (olderrno == 0) 64295Seric ExitStat = EX_SOFTWARE; 65295Seric else 661598Seric ExitStat = EX_OSERR; 67295Seric } 68295Seric 699372Seric /* insure that we have a queue id for logging */ 707810Seric (void) queuename(CurEnv, '\0'); 71295Seric # ifdef LOG 727674Seric if (LogLevel > 0) 7324945Seric syslog(LOG_CRIT, "%s: SYSERR: %s", CurEnv->e_id, &MsgBuf[4]); 74295Seric # endif LOG 75295Seric errno = 0; 767762Seric if (QuickAbort) 777762Seric longjmp(TopFrame, 2); 78295Seric } 79295Seric /* 80295Seric ** USRERR -- Signal user error. 81295Seric ** 82295Seric ** This is much like syserr except it is for user errors. 83295Seric ** 84295Seric ** Parameters: 85295Seric ** fmt, a, b, c, d -- printf strings 86295Seric ** 87295Seric ** Returns: 884084Seric ** none 897762Seric ** Through TopFrame if QuickAbort is set. 90295Seric ** 91295Seric ** Side Effects: 921514Seric ** increments Errors. 93295Seric */ 94295Seric 95295Seric /*VARARGS1*/ 96295Seric usrerr(fmt, a, b, c, d, e) 97295Seric char *fmt; 98295Seric { 99295Seric extern char SuprErrs; 1004167Seric extern char Arpa_Usrerr[]; 10116901Seric extern int errno; 102295Seric 103295Seric if (SuprErrs) 1044084Seric return; 105295Seric 10616901Seric fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e); 1079389Seric puterrmsg(MsgBuf); 1088239Seric 1097762Seric if (QuickAbort) 1107762Seric longjmp(TopFrame, 1); 1114063Seric } 1124063Seric /* 1134063Seric ** MESSAGE -- print message (not necessarily an error) 1144063Seric ** 1154063Seric ** Parameters: 1164063Seric ** num -- the default ARPANET error number (in ascii) 1174063Seric ** msg -- the message (printf fmt) -- if it begins 1184063Seric ** with a digit, this number overrides num. 1194063Seric ** a, b, c, d, e -- printf arguments 1204063Seric ** 1214063Seric ** Returns: 1224063Seric ** none 1234063Seric ** 1244063Seric ** Side Effects: 1254063Seric ** none. 1264063Seric */ 1274063Seric 1284084Seric /*VARARGS2*/ 1294063Seric message(num, msg, a, b, c, d, e) 1304063Seric register char *num; 1314063Seric register char *msg; 1324063Seric { 1334711Seric errno = 0; 13416901Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e); 1359108Seric putmsg(MsgBuf, FALSE); 1367613Seric } 1377613Seric /* 1388239Seric ** NMESSAGE -- print message (not necessarily an error) 1398239Seric ** 1408239Seric ** Just like "message" except it never puts the to... tag on. 1418239Seric ** 1428239Seric ** Parameters: 1438239Seric ** num -- the default ARPANET error number (in ascii) 1448239Seric ** msg -- the message (printf fmt) -- if it begins 14524943Seric ** with three digits, this number overrides num. 1468239Seric ** a, b, c, d, e -- printf arguments 1478239Seric ** 1488239Seric ** Returns: 1498239Seric ** none 1508239Seric ** 1518239Seric ** Side Effects: 1528239Seric ** none. 1538239Seric */ 1548239Seric 1558239Seric /*VARARGS2*/ 1568239Seric nmessage(num, msg, a, b, c, d, e) 1578239Seric register char *num; 1588239Seric register char *msg; 1598239Seric { 1608239Seric errno = 0; 16116901Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e); 1629108Seric putmsg(MsgBuf, FALSE); 1638239Seric } 1648239Seric /* 1657613Seric ** PUTMSG -- output error message to transcript and channel 1667613Seric ** 1677613Seric ** Parameters: 1687613Seric ** msg -- message to output (in SMTP format). 1699108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 1709108Seric ** our output channel. 1717613Seric ** 1727613Seric ** Returns: 1737613Seric ** none. 1747613Seric ** 1757613Seric ** Side Effects: 1767613Seric ** Outputs msg to the transcript. 1777613Seric ** If appropriate, outputs it to the channel. 1787613Seric ** Deletes SMTP reply code number as appropriate. 1797613Seric */ 1804711Seric 1819108Seric putmsg(msg, holdmsg) 1827613Seric char *msg; 1839108Seric bool holdmsg; 1847613Seric { 18514900Seric /* output to transcript if serious */ 18614900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 18714900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 1884711Seric 1894711Seric /* output to channel if appropriate */ 1909108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 1914063Seric { 1927275Seric (void) fflush(stdout); 1939277Seric if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 1947613Seric fprintf(OutChannel, "%s\r\n", msg); 1954711Seric else 1967613Seric fprintf(OutChannel, "%s\n", &msg[4]); 1974711Seric (void) fflush(OutChannel); 1984063Seric } 1999389Seric } 2009389Seric /* 2019389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2029389Seric ** 2039389Seric ** Parameters: 2049389Seric ** msg -- the message to output. 2059389Seric ** 2069389Seric ** Returns: 2079389Seric ** none. 2089389Seric ** 2099389Seric ** Side Effects: 2109389Seric ** Sets the fatal error bit in the envelope as appropriate. 2119389Seric */ 2128239Seric 2139389Seric puterrmsg(msg) 2149389Seric char *msg; 2159389Seric { 2169389Seric /* output the message as usual */ 2179389Seric putmsg(msg, HoldErrs); 2189389Seric 2199389Seric /* signal the error */ 2209389Seric Errors++; 2219389Seric if (msg[0] == '5') 2229336Seric CurEnv->e_flags |= EF_FATALERRS; 2234711Seric } 2244711Seric /* 2254711Seric ** FMTMSG -- format a message into buffer. 2264711Seric ** 2274711Seric ** Parameters: 2284711Seric ** eb -- error buffer to get result. 2294711Seric ** to -- the recipient tag for this message. 2304711Seric ** num -- arpanet error number. 23116901Seric ** en -- the error number to display. 2324711Seric ** fmt -- format of string. 2334711Seric ** a, b, c, d, e -- arguments. 2344711Seric ** 2354711Seric ** Returns: 2364711Seric ** none. 2374711Seric ** 2384711Seric ** Side Effects: 2394711Seric ** none. 2404711Seric */ 2414063Seric 24216901Seric /*VARARGS5*/ 2434711Seric static 24416901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e) 2454711Seric register char *eb; 2464711Seric char *to; 2474711Seric char *num; 24816904Seric int eno; 2494711Seric char *fmt; 2504711Seric { 2514711Seric char del; 2524711Seric 2534711Seric /* output the reply code */ 25424943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2554577Seric { 2564711Seric num = fmt; 2574711Seric fmt += 4; 2584711Seric } 2594711Seric if (num[3] == '-') 2604711Seric del = '-'; 2614711Seric else 2624711Seric del = ' '; 2634711Seric (void) sprintf(eb, "%3.3s%c", num, del); 2644711Seric eb += 4; 2654063Seric 2669372Seric /* output the file name and line number */ 2679372Seric if (FileName != NULL) 2689372Seric { 2699372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 2709372Seric eb += strlen(eb); 2719372Seric } 2729372Seric 2734711Seric /* output the "to" person */ 2744711Seric if (to != NULL && to[0] != '\0') 2754711Seric { 2764711Seric (void) sprintf(eb, "%s... ", to); 2775201Seric while (*eb != '\0') 2785201Seric *eb++ &= 0177; 2794711Seric } 2804711Seric 2814711Seric /* output the message */ 2824711Seric (void) sprintf(eb, fmt, a, b, c, d, e); 2835201Seric while (*eb != '\0') 2845201Seric *eb++ &= 0177; 2854711Seric 2864711Seric /* output the error code, if any */ 28716904Seric if (eno != 0) 2884711Seric { 28915136Seric extern char *errstring(); 29015136Seric 29116904Seric (void) sprintf(eb, ": %s", errstring(eno)); 2924711Seric eb += strlen(eb); 2934577Seric } 294295Seric } 29515136Seric /* 29615136Seric ** ERRSTRING -- return string description of error code 29715136Seric ** 29815136Seric ** Parameters: 29915136Seric ** errno -- the error number to translate 30015136Seric ** 30115136Seric ** Returns: 30215136Seric ** A string description of errno. 30315136Seric ** 30415136Seric ** Side Effects: 30515136Seric ** none. 30615136Seric */ 30715136Seric 30815136Seric char * 30915136Seric errstring(errno) 31015136Seric int errno; 31115136Seric { 31215136Seric extern char *sys_errlist[]; 31315136Seric extern int sys_nerr; 31424943Seric static char buf[100]; 31524943Seric # ifdef SMTP 31624943Seric extern char *SmtpPhase; 31724943Seric # endif SMTP 31815136Seric 31924943Seric # ifdef DAEMON 32024943Seric # ifdef VMUNIX 32124943Seric /* 32224943Seric ** Handle special network error codes. 32324943Seric ** 32424943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 32524943Seric */ 32624943Seric 32724943Seric switch (errno) 32824943Seric { 32924943Seric case ETIMEDOUT: 33024943Seric case ECONNRESET: 33124943Seric (void) strcpy(buf, sys_errlist[errno]); 33224943Seric if (SmtpPhase != NULL) 33324943Seric { 33424943Seric (void) strcat(buf, " during "); 33524943Seric (void) strcat(buf, SmtpPhase); 33624943Seric } 337*25050Seric if (CurHostName != NULL) 33824943Seric { 33924943Seric (void) strcat(buf, " with "); 340*25050Seric (void) strcat(buf, CurHostName); 34124943Seric } 34224943Seric return (buf); 34324943Seric 34424943Seric case EHOSTDOWN: 345*25050Seric if (CurHostName == NULL) 34624943Seric break; 347*25050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 34824943Seric return (buf); 34924943Seric 35024943Seric case ECONNREFUSED: 351*25050Seric if (CurHostName == NULL) 35224943Seric break; 353*25050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 35424943Seric return (buf); 35524943Seric } 35624943Seric # endif VMUNIX 35724943Seric # endif DAEMON 35824943Seric 35915136Seric if (errno > 0 && errno < sys_nerr) 36015136Seric return (sys_errlist[errno]); 36115136Seric 36215136Seric (void) sprintf(buf, "Error %d", errno); 36315136Seric return (buf); 36415136Seric } 365