122705Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 333729Sbostic * Copyright (c) 1988 Regents of the University of California. 433729Sbostic * All rights reserved. 533729Sbostic * 642826Sbostic * %sccs.include.redist.c% 733729Sbostic */ 822705Sdist 922705Sdist #ifndef lint 10*58524Seric static char sccsid[] = "@(#)err.c 6.7 (Berkeley) 03/06/93"; 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 4246928Sbostic static void fmtmsg(); 4346928Sbostic 44295Seric /*VARARGS1*/ 4557642Seric #ifdef __STDC__ 4657642Seric syserr(char *fmt, ...) 4757642Seric #else 4857642Seric syserr(fmt, va_alist) 49295Seric char *fmt; 5057642Seric va_dcl 5157642Seric #endif 52295Seric { 5316901Seric register char *p; 5416901Seric int olderrno = errno; 5556852Seric VA_LOCAL_DECL 56295Seric 577525Seric /* format and output the error message */ 5816901Seric if (olderrno == 0) 5958151Seric p = "554"; 607957Seric else 6158151Seric p = "451"; 6256852Seric VA_START(fmt); 6356852Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap); 6456852Seric VA_END; 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]); 8156795Seric # 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*/ 10357642Seric #ifdef __STDC__ 10457642Seric usrerr(char *fmt, ...) 10557642Seric #else 10657642Seric usrerr(fmt, va_alist) 107295Seric char *fmt; 10857642Seric va_dcl 10957642Seric #endif 110295Seric { 11156852Seric VA_LOCAL_DECL 112295Seric extern char SuprErrs; 11316901Seric extern int errno; 114295Seric 115295Seric if (SuprErrs) 1164084Seric return; 117295Seric 11856852Seric VA_START(fmt); 119*58524Seric fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap); 12056852Seric VA_END; 1219389Seric puterrmsg(MsgBuf); 1228239Seric 12351951Seric # ifdef LOG 12458020Seric if (LogLevel > 3 && LogUsrErrs) 12551951Seric syslog(LOG_NOTICE, "%s: %s", 12651951Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 12751951Seric &MsgBuf[4]); 12856795Seric # endif /* LOG */ 12951951Seric 1307762Seric if (QuickAbort) 1317762Seric longjmp(TopFrame, 1); 1324063Seric } 1334063Seric /* 1344063Seric ** MESSAGE -- print message (not necessarily an error) 1354063Seric ** 1364063Seric ** Parameters: 1374063Seric ** num -- the default ARPANET error number (in ascii) 1384063Seric ** msg -- the message (printf fmt) -- if it begins 1394063Seric ** with a digit, this number overrides num. 1404063Seric ** a, b, c, d, e -- printf arguments 1414063Seric ** 1424063Seric ** Returns: 1434063Seric ** none 1444063Seric ** 1454063Seric ** Side Effects: 1464063Seric ** none. 1474063Seric */ 1484063Seric 1494084Seric /*VARARGS2*/ 15057642Seric #ifdef __STDC__ 15158151Seric message(char *msg, ...) 15257642Seric #else 15358151Seric message(msg, va_alist) 15456852Seric char *msg; 15557642Seric va_dcl 15657642Seric #endif 1574063Seric { 15856852Seric VA_LOCAL_DECL 15956852Seric 1604711Seric errno = 0; 16156852Seric VA_START(msg); 16258151Seric fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap); 16356852Seric VA_END; 1649108Seric putmsg(MsgBuf, FALSE); 1657613Seric } 1667613Seric /* 1678239Seric ** NMESSAGE -- print message (not necessarily an error) 1688239Seric ** 1698239Seric ** Just like "message" except it never puts the to... tag on. 1708239Seric ** 1718239Seric ** Parameters: 1728239Seric ** num -- the default ARPANET error number (in ascii) 1738239Seric ** msg -- the message (printf fmt) -- if it begins 17424943Seric ** with three digits, this number overrides num. 1758239Seric ** a, b, c, d, e -- printf arguments 1768239Seric ** 1778239Seric ** Returns: 1788239Seric ** none 1798239Seric ** 1808239Seric ** Side Effects: 1818239Seric ** none. 1828239Seric */ 1838239Seric 1848239Seric /*VARARGS2*/ 18557642Seric #ifdef __STDC__ 18658151Seric nmessage(char *msg, ...) 18757642Seric #else 18858151Seric nmessage(msg, va_alist) 18956852Seric char *msg; 19057642Seric va_dcl 19157642Seric #endif 1928239Seric { 19356852Seric VA_LOCAL_DECL 19456852Seric 1958239Seric errno = 0; 19656852Seric VA_START(msg); 19758151Seric fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap); 19856852Seric VA_END; 1999108Seric putmsg(MsgBuf, FALSE); 2008239Seric } 2018239Seric /* 2027613Seric ** PUTMSG -- output error message to transcript and channel 2037613Seric ** 2047613Seric ** Parameters: 2057613Seric ** msg -- message to output (in SMTP format). 2069108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 2079108Seric ** our output channel. 2087613Seric ** 2097613Seric ** Returns: 2107613Seric ** none. 2117613Seric ** 2127613Seric ** Side Effects: 2137613Seric ** Outputs msg to the transcript. 2147613Seric ** If appropriate, outputs it to the channel. 2157613Seric ** Deletes SMTP reply code number as appropriate. 2167613Seric */ 2174711Seric 2189108Seric putmsg(msg, holdmsg) 2197613Seric char *msg; 2209108Seric bool holdmsg; 2217613Seric { 22214900Seric /* output to transcript if serious */ 22314900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 22414900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 2254711Seric 2264711Seric /* output to channel if appropriate */ 2279108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 2284063Seric { 2297275Seric (void) fflush(stdout); 23052220Seric if (OpMode == MD_SMTP) 2317613Seric fprintf(OutChannel, "%s\r\n", msg); 2324711Seric else 2337613Seric fprintf(OutChannel, "%s\n", &msg[4]); 2344711Seric (void) fflush(OutChannel); 2354063Seric } 2369389Seric } 2379389Seric /* 2389389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2399389Seric ** 2409389Seric ** Parameters: 2419389Seric ** msg -- the message to output. 2429389Seric ** 2439389Seric ** Returns: 2449389Seric ** none. 2459389Seric ** 2469389Seric ** Side Effects: 2479389Seric ** Sets the fatal error bit in the envelope as appropriate. 2489389Seric */ 2498239Seric 2509389Seric puterrmsg(msg) 2519389Seric char *msg; 2529389Seric { 2539389Seric /* output the message as usual */ 2549389Seric putmsg(msg, HoldErrs); 2559389Seric 2569389Seric /* signal the error */ 2579389Seric Errors++; 2589389Seric if (msg[0] == '5') 2599336Seric CurEnv->e_flags |= EF_FATALERRS; 2604711Seric } 2614711Seric /* 2624711Seric ** FMTMSG -- format a message into buffer. 2634711Seric ** 2644711Seric ** Parameters: 2654711Seric ** eb -- error buffer to get result. 2664711Seric ** to -- the recipient tag for this message. 2674711Seric ** num -- arpanet error number. 26816901Seric ** en -- the error number to display. 2694711Seric ** fmt -- format of string. 2704711Seric ** a, b, c, d, e -- arguments. 2714711Seric ** 2724711Seric ** Returns: 2734711Seric ** none. 2744711Seric ** 2754711Seric ** Side Effects: 2764711Seric ** none. 2774711Seric */ 2784063Seric 27946928Sbostic static void 28056852Seric fmtmsg(eb, to, num, eno, fmt, ap) 2814711Seric register char *eb; 2824711Seric char *to; 2834711Seric char *num; 28416904Seric int eno; 2854711Seric char *fmt; 28656852Seric va_list ap; 2874711Seric { 2884711Seric char del; 2894711Seric 2904711Seric /* output the reply code */ 29124943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2924577Seric { 2934711Seric num = fmt; 2944711Seric fmt += 4; 2954711Seric } 2964711Seric if (num[3] == '-') 2974711Seric del = '-'; 2984711Seric else 2994711Seric del = ' '; 3004711Seric (void) sprintf(eb, "%3.3s%c", num, del); 3014711Seric eb += 4; 3024063Seric 3039372Seric /* output the file name and line number */ 3049372Seric if (FileName != NULL) 3059372Seric { 3069372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 3079372Seric eb += strlen(eb); 3089372Seric } 3099372Seric 3104711Seric /* output the "to" person */ 3114711Seric if (to != NULL && to[0] != '\0') 3124711Seric { 3134711Seric (void) sprintf(eb, "%s... ", to); 3145201Seric while (*eb != '\0') 3155201Seric *eb++ &= 0177; 3164711Seric } 3174711Seric 3184711Seric /* output the message */ 31956852Seric (void) vsprintf(eb, fmt, ap); 3205201Seric while (*eb != '\0') 3215201Seric *eb++ &= 0177; 3224711Seric 3234711Seric /* output the error code, if any */ 32416904Seric if (eno != 0) 3254711Seric { 32615136Seric extern char *errstring(); 32715136Seric 32816904Seric (void) sprintf(eb, ": %s", errstring(eno)); 3294711Seric eb += strlen(eb); 3304577Seric } 331295Seric } 33215136Seric /* 33315136Seric ** ERRSTRING -- return string description of error code 33415136Seric ** 33515136Seric ** Parameters: 33615136Seric ** errno -- the error number to translate 33715136Seric ** 33815136Seric ** Returns: 33915136Seric ** A string description of errno. 34015136Seric ** 34115136Seric ** Side Effects: 34215136Seric ** none. 34315136Seric */ 34415136Seric 34515136Seric char * 34615136Seric errstring(errno) 34715136Seric int errno; 34815136Seric { 34915136Seric extern char *sys_errlist[]; 35015136Seric extern int sys_nerr; 35157232Seric static char buf[MAXLINE]; 35224943Seric # ifdef SMTP 35324943Seric extern char *SmtpPhase; 35456795Seric # endif /* SMTP */ 35515136Seric 35624943Seric # ifdef DAEMON 35752107Seric # ifdef ETIMEDOUT 35824943Seric /* 35924943Seric ** Handle special network error codes. 36024943Seric ** 36124943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 36224943Seric */ 36324943Seric 36424943Seric switch (errno) 36524943Seric { 36624943Seric case ETIMEDOUT: 36724943Seric case ECONNRESET: 36824943Seric (void) strcpy(buf, sys_errlist[errno]); 36924943Seric if (SmtpPhase != NULL) 37024943Seric { 37124943Seric (void) strcat(buf, " during "); 37224943Seric (void) strcat(buf, SmtpPhase); 37324943Seric } 37425050Seric if (CurHostName != NULL) 37524943Seric { 37624943Seric (void) strcat(buf, " with "); 37725050Seric (void) strcat(buf, CurHostName); 37824943Seric } 37924943Seric return (buf); 38024943Seric 38124943Seric case EHOSTDOWN: 38225050Seric if (CurHostName == NULL) 38324943Seric break; 38425050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 38524943Seric return (buf); 38624943Seric 38724943Seric case ECONNREFUSED: 38825050Seric if (CurHostName == NULL) 38924943Seric break; 39025050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 39124943Seric return (buf); 39225526Smiriam 39357736Seric # ifdef NAMED_BIND 39458010Seric case HOST_NOT_FOUND + MAX_ERRNO: 39558010Seric return ("Name server: host not found"); 39658010Seric 39758010Seric case TRY_AGAIN + MAX_ERRNO: 39858010Seric return ("Name server: host name lookup failure"); 39958010Seric 40058010Seric case NO_RECOVERY + MAX_ERRNO: 40158010Seric return ("Name server: non-recoverable error"); 40258010Seric 40358010Seric case NO_DATA + MAX_ERRNO: 40458010Seric return ("Name server: no data known for name"); 40557736Seric # endif 40624943Seric } 40752107Seric # endif 40852107Seric # endif 40924943Seric 41015136Seric if (errno > 0 && errno < sys_nerr) 41115136Seric return (sys_errlist[errno]); 41215136Seric 41315136Seric (void) sprintf(buf, "Error %d", errno); 41415136Seric return (buf); 41515136Seric } 416