122705Sdist /* 2*33729Sbostic * Copyright (c) 1988 Regents of the University of California. 3*33729Sbostic * All rights reserved. 4*33729Sbostic * 5*33729Sbostic * Redistribution and use in source and binary forms are permitted 6*33729Sbostic * provided that this notice is preserved and that due credit is given 7*33729Sbostic * to the University of California at Berkeley. The name of the University 8*33729Sbostic * may not be used to endorse or promote products derived from this 9*33729Sbostic * software without specific prior written permission. This software 10*33729Sbostic * is provided ``as is'' without express or implied warranty. 11*33729Sbostic * 12*33729Sbostic * Sendmail 13*33729Sbostic * Copyright (c) 1983 Eric P. Allman 14*33729Sbostic * Berkeley, California 15*33729Sbostic */ 1622705Sdist 1722705Sdist #ifndef lint 18*33729Sbostic static char sccsid[] = "@(#)err.c 5.8 (Berkeley) 03/13/88"; 19*33729Sbostic #endif /* not lint */ 2022705Sdist 213311Seric # include "sendmail.h" 2224943Seric # include <errno.h> 2325526Smiriam # include <netdb.h> 24295Seric 25295Seric /* 261514Seric ** SYSERR -- Print error message. 27295Seric ** 28295Seric ** Prints an error message via printf to the diagnostic 29295Seric ** output. If LOG is defined, it logs it also. 30295Seric ** 31295Seric ** Parameters: 32295Seric ** f -- the format string 33295Seric ** a, b, c, d, e -- parameters 34295Seric ** 35295Seric ** Returns: 364084Seric ** none 377762Seric ** Through TopFrame if QuickAbort is set. 38295Seric ** 39295Seric ** Side Effects: 401514Seric ** increments Errors. 411514Seric ** sets ExitStat. 42295Seric */ 43295Seric 444084Seric # ifdef lint 454084Seric int sys_nerr; 464084Seric char *sys_errlist[]; 474084Seric # endif lint 4810147Seric char MsgBuf[BUFSIZ*2]; /* text of most recent message */ 494084Seric 50295Seric /*VARARGS1*/ 51295Seric syserr(fmt, a, b, c, d, e) 52295Seric char *fmt; 53295Seric { 5416901Seric register char *p; 5516901Seric int olderrno = errno; 567957Seric extern char Arpa_PSyserr[]; 577957Seric extern char Arpa_TSyserr[]; 58295Seric 597525Seric /* format and output the error message */ 6016901Seric if (olderrno == 0) 617957Seric p = Arpa_PSyserr; 627957Seric else 637957Seric p = Arpa_TSyserr; 6416901Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e); 659389Seric puterrmsg(MsgBuf); 664063Seric 67295Seric /* determine exit status if not already set */ 68295Seric if (ExitStat == EX_OK) 69295Seric { 7016901Seric if (olderrno == 0) 71295Seric ExitStat = EX_SOFTWARE; 72295Seric else 731598Seric ExitStat = EX_OSERR; 74295Seric } 75295Seric 76295Seric # ifdef LOG 777674Seric if (LogLevel > 0) 7825277Seric syslog(LOG_CRIT, "%s: SYSERR: %s", 7925277Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 8025277Seric &MsgBuf[4]); 81295Seric # endif LOG 82295Seric errno = 0; 837762Seric if (QuickAbort) 847762Seric longjmp(TopFrame, 2); 85295Seric } 86295Seric /* 87295Seric ** USRERR -- Signal user error. 88295Seric ** 89295Seric ** This is much like syserr except it is for user errors. 90295Seric ** 91295Seric ** Parameters: 92295Seric ** fmt, a, b, c, d -- printf strings 93295Seric ** 94295Seric ** Returns: 954084Seric ** none 967762Seric ** Through TopFrame if QuickAbort is set. 97295Seric ** 98295Seric ** Side Effects: 991514Seric ** increments Errors. 100295Seric */ 101295Seric 102295Seric /*VARARGS1*/ 103295Seric usrerr(fmt, a, b, c, d, e) 104295Seric char *fmt; 105295Seric { 106295Seric extern char SuprErrs; 1074167Seric extern char Arpa_Usrerr[]; 10816901Seric extern int errno; 109295Seric 110295Seric if (SuprErrs) 1114084Seric return; 112295Seric 11316901Seric fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e); 1149389Seric puterrmsg(MsgBuf); 1158239Seric 1167762Seric if (QuickAbort) 1177762Seric longjmp(TopFrame, 1); 1184063Seric } 1194063Seric /* 1204063Seric ** MESSAGE -- print message (not necessarily an error) 1214063Seric ** 1224063Seric ** Parameters: 1234063Seric ** num -- the default ARPANET error number (in ascii) 1244063Seric ** msg -- the message (printf fmt) -- if it begins 1254063Seric ** with a digit, this number overrides num. 1264063Seric ** a, b, c, d, e -- printf arguments 1274063Seric ** 1284063Seric ** Returns: 1294063Seric ** none 1304063Seric ** 1314063Seric ** Side Effects: 1324063Seric ** none. 1334063Seric */ 1344063Seric 1354084Seric /*VARARGS2*/ 1364063Seric message(num, msg, a, b, c, d, e) 1374063Seric register char *num; 1384063Seric register char *msg; 1394063Seric { 1404711Seric errno = 0; 14116901Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e); 1429108Seric putmsg(MsgBuf, FALSE); 1437613Seric } 1447613Seric /* 1458239Seric ** NMESSAGE -- print message (not necessarily an error) 1468239Seric ** 1478239Seric ** Just like "message" except it never puts the to... tag on. 1488239Seric ** 1498239Seric ** Parameters: 1508239Seric ** num -- the default ARPANET error number (in ascii) 1518239Seric ** msg -- the message (printf fmt) -- if it begins 15224943Seric ** with three digits, this number overrides num. 1538239Seric ** a, b, c, d, e -- printf arguments 1548239Seric ** 1558239Seric ** Returns: 1568239Seric ** none 1578239Seric ** 1588239Seric ** Side Effects: 1598239Seric ** none. 1608239Seric */ 1618239Seric 1628239Seric /*VARARGS2*/ 1638239Seric nmessage(num, msg, a, b, c, d, e) 1648239Seric register char *num; 1658239Seric register char *msg; 1668239Seric { 1678239Seric errno = 0; 16816901Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e); 1699108Seric putmsg(MsgBuf, FALSE); 1708239Seric } 1718239Seric /* 1727613Seric ** PUTMSG -- output error message to transcript and channel 1737613Seric ** 1747613Seric ** Parameters: 1757613Seric ** msg -- message to output (in SMTP format). 1769108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 1779108Seric ** our output channel. 1787613Seric ** 1797613Seric ** Returns: 1807613Seric ** none. 1817613Seric ** 1827613Seric ** Side Effects: 1837613Seric ** Outputs msg to the transcript. 1847613Seric ** If appropriate, outputs it to the channel. 1857613Seric ** Deletes SMTP reply code number as appropriate. 1867613Seric */ 1874711Seric 1889108Seric putmsg(msg, holdmsg) 1897613Seric char *msg; 1909108Seric bool holdmsg; 1917613Seric { 19214900Seric /* output to transcript if serious */ 19314900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 19414900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 1954711Seric 1964711Seric /* output to channel if appropriate */ 1979108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 1984063Seric { 1997275Seric (void) fflush(stdout); 2009277Seric if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 2017613Seric fprintf(OutChannel, "%s\r\n", msg); 2024711Seric else 2037613Seric fprintf(OutChannel, "%s\n", &msg[4]); 2044711Seric (void) fflush(OutChannel); 2054063Seric } 2069389Seric } 2079389Seric /* 2089389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2099389Seric ** 2109389Seric ** Parameters: 2119389Seric ** msg -- the message to output. 2129389Seric ** 2139389Seric ** Returns: 2149389Seric ** none. 2159389Seric ** 2169389Seric ** Side Effects: 2179389Seric ** Sets the fatal error bit in the envelope as appropriate. 2189389Seric */ 2198239Seric 2209389Seric puterrmsg(msg) 2219389Seric char *msg; 2229389Seric { 2239389Seric /* output the message as usual */ 2249389Seric putmsg(msg, HoldErrs); 2259389Seric 2269389Seric /* signal the error */ 2279389Seric Errors++; 2289389Seric if (msg[0] == '5') 2299336Seric CurEnv->e_flags |= EF_FATALERRS; 2304711Seric } 2314711Seric /* 2324711Seric ** FMTMSG -- format a message into buffer. 2334711Seric ** 2344711Seric ** Parameters: 2354711Seric ** eb -- error buffer to get result. 2364711Seric ** to -- the recipient tag for this message. 2374711Seric ** num -- arpanet error number. 23816901Seric ** en -- the error number to display. 2394711Seric ** fmt -- format of string. 2404711Seric ** a, b, c, d, e -- arguments. 2414711Seric ** 2424711Seric ** Returns: 2434711Seric ** none. 2444711Seric ** 2454711Seric ** Side Effects: 2464711Seric ** none. 2474711Seric */ 2484063Seric 24916901Seric /*VARARGS5*/ 2504711Seric static 25116901Seric fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e) 2524711Seric register char *eb; 2534711Seric char *to; 2544711Seric char *num; 25516904Seric int eno; 2564711Seric char *fmt; 2574711Seric { 2584711Seric char del; 2594711Seric 2604711Seric /* output the reply code */ 26124943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2624577Seric { 2634711Seric num = fmt; 2644711Seric fmt += 4; 2654711Seric } 2664711Seric if (num[3] == '-') 2674711Seric del = '-'; 2684711Seric else 2694711Seric del = ' '; 2704711Seric (void) sprintf(eb, "%3.3s%c", num, del); 2714711Seric eb += 4; 2724063Seric 2739372Seric /* output the file name and line number */ 2749372Seric if (FileName != NULL) 2759372Seric { 2769372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 2779372Seric eb += strlen(eb); 2789372Seric } 2799372Seric 2804711Seric /* output the "to" person */ 2814711Seric if (to != NULL && to[0] != '\0') 2824711Seric { 2834711Seric (void) sprintf(eb, "%s... ", to); 2845201Seric while (*eb != '\0') 2855201Seric *eb++ &= 0177; 2864711Seric } 2874711Seric 2884711Seric /* output the message */ 2894711Seric (void) sprintf(eb, fmt, a, b, c, d, e); 2905201Seric while (*eb != '\0') 2915201Seric *eb++ &= 0177; 2924711Seric 2934711Seric /* output the error code, if any */ 29416904Seric if (eno != 0) 2954711Seric { 29615136Seric extern char *errstring(); 29715136Seric 29816904Seric (void) sprintf(eb, ": %s", errstring(eno)); 2994711Seric eb += strlen(eb); 3004577Seric } 301295Seric } 30215136Seric /* 30315136Seric ** ERRSTRING -- return string description of error code 30415136Seric ** 30515136Seric ** Parameters: 30615136Seric ** errno -- the error number to translate 30715136Seric ** 30815136Seric ** Returns: 30915136Seric ** A string description of errno. 31015136Seric ** 31115136Seric ** Side Effects: 31215136Seric ** none. 31315136Seric */ 31415136Seric 31515136Seric char * 31615136Seric errstring(errno) 31715136Seric int errno; 31815136Seric { 31915136Seric extern char *sys_errlist[]; 32015136Seric extern int sys_nerr; 32124943Seric static char buf[100]; 32224943Seric # ifdef SMTP 32324943Seric extern char *SmtpPhase; 32424943Seric # endif SMTP 32515136Seric 32624943Seric # ifdef DAEMON 32724943Seric # ifdef VMUNIX 32824943Seric /* 32924943Seric ** Handle special network error codes. 33024943Seric ** 33124943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 33224943Seric */ 33324943Seric 33424943Seric switch (errno) 33524943Seric { 33624943Seric case ETIMEDOUT: 33724943Seric case ECONNRESET: 33824943Seric (void) strcpy(buf, sys_errlist[errno]); 33924943Seric if (SmtpPhase != NULL) 34024943Seric { 34124943Seric (void) strcat(buf, " during "); 34224943Seric (void) strcat(buf, SmtpPhase); 34324943Seric } 34425050Seric if (CurHostName != NULL) 34524943Seric { 34624943Seric (void) strcat(buf, " with "); 34725050Seric (void) strcat(buf, CurHostName); 34824943Seric } 34924943Seric return (buf); 35024943Seric 35124943Seric case EHOSTDOWN: 35225050Seric if (CurHostName == NULL) 35324943Seric break; 35425050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 35524943Seric return (buf); 35624943Seric 35724943Seric case ECONNREFUSED: 35825050Seric if (CurHostName == NULL) 35924943Seric break; 36025050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 36124943Seric return (buf); 36225526Smiriam 36325526Smiriam case (TRY_AGAIN+MAX_ERRNO): 36425526Smiriam (void) sprintf(buf, "Host Name Lookup Failure"); 36525526Smiriam return (buf); 36624943Seric } 36724943Seric # endif VMUNIX 36824943Seric # endif DAEMON 36924943Seric 37015136Seric if (errno > 0 && errno < sys_nerr) 37115136Seric return (sys_errlist[errno]); 37215136Seric 37315136Seric (void) sprintf(buf, "Error %d", errno); 37415136Seric return (buf); 37515136Seric } 376