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*57736Seric static char sccsid[] = "@(#)err.c 6.3 (Berkeley) 01/28/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 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; 6456852Seric VA_START(fmt); 6556852Seric fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap); 6656852Seric VA_END; 679389Seric puterrmsg(MsgBuf); 684063Seric 69295Seric /* determine exit status if not already set */ 70295Seric if (ExitStat == EX_OK) 71295Seric { 7216901Seric if (olderrno == 0) 73295Seric ExitStat = EX_SOFTWARE; 74295Seric else 751598Seric ExitStat = EX_OSERR; 76295Seric } 77295Seric 78295Seric # ifdef LOG 797674Seric if (LogLevel > 0) 8025277Seric syslog(LOG_CRIT, "%s: SYSERR: %s", 8125277Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 8225277Seric &MsgBuf[4]); 8356795Seric # endif /* LOG */ 84295Seric errno = 0; 857762Seric if (QuickAbort) 867762Seric longjmp(TopFrame, 2); 87295Seric } 88295Seric /* 89295Seric ** USRERR -- Signal user error. 90295Seric ** 91295Seric ** This is much like syserr except it is for user errors. 92295Seric ** 93295Seric ** Parameters: 94295Seric ** fmt, a, b, c, d -- printf strings 95295Seric ** 96295Seric ** Returns: 974084Seric ** none 987762Seric ** Through TopFrame if QuickAbort is set. 99295Seric ** 100295Seric ** Side Effects: 1011514Seric ** increments Errors. 102295Seric */ 103295Seric 104295Seric /*VARARGS1*/ 10557642Seric #ifdef __STDC__ 10657642Seric usrerr(char *fmt, ...) 10757642Seric #else 10857642Seric usrerr(fmt, va_alist) 109295Seric char *fmt; 11057642Seric va_dcl 11157642Seric #endif 112295Seric { 11356852Seric VA_LOCAL_DECL 114295Seric extern char SuprErrs; 1154167Seric extern char Arpa_Usrerr[]; 11616901Seric extern int errno; 117295Seric 118295Seric if (SuprErrs) 1194084Seric return; 120295Seric 12156852Seric VA_START(fmt); 12256852Seric fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, ap); 12356852Seric VA_END; 1249389Seric puterrmsg(MsgBuf); 1258239Seric 12651951Seric # ifdef LOG 12751951Seric if (LogLevel > 1 && LogUsrErrs) 12851951Seric syslog(LOG_NOTICE, "%s: %s", 12951951Seric CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, 13051951Seric &MsgBuf[4]); 13156795Seric # endif /* LOG */ 13251951Seric 1337762Seric if (QuickAbort) 1347762Seric longjmp(TopFrame, 1); 1354063Seric } 1364063Seric /* 1374063Seric ** MESSAGE -- print message (not necessarily an error) 1384063Seric ** 1394063Seric ** Parameters: 1404063Seric ** num -- the default ARPANET error number (in ascii) 1414063Seric ** msg -- the message (printf fmt) -- if it begins 1424063Seric ** with a digit, this number overrides num. 1434063Seric ** a, b, c, d, e -- printf arguments 1444063Seric ** 1454063Seric ** Returns: 1464063Seric ** none 1474063Seric ** 1484063Seric ** Side Effects: 1494063Seric ** none. 1504063Seric */ 1514063Seric 1524084Seric /*VARARGS2*/ 15357642Seric #ifdef __STDC__ 15457642Seric message(char *num, char *msg, ...) 15557642Seric #else 15657642Seric message(num, msg, va_alist) 15756852Seric char *num; 15856852Seric char *msg; 15957642Seric va_dcl 16057642Seric #endif 1614063Seric { 16256852Seric VA_LOCAL_DECL 16356852Seric 1644711Seric errno = 0; 16556852Seric VA_START(msg); 16656852Seric fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, ap); 16756852Seric VA_END; 1689108Seric putmsg(MsgBuf, FALSE); 1697613Seric } 1707613Seric /* 1718239Seric ** NMESSAGE -- print message (not necessarily an error) 1728239Seric ** 1738239Seric ** Just like "message" except it never puts the to... tag on. 1748239Seric ** 1758239Seric ** Parameters: 1768239Seric ** num -- the default ARPANET error number (in ascii) 1778239Seric ** msg -- the message (printf fmt) -- if it begins 17824943Seric ** with three digits, this number overrides num. 1798239Seric ** a, b, c, d, e -- printf arguments 1808239Seric ** 1818239Seric ** Returns: 1828239Seric ** none 1838239Seric ** 1848239Seric ** Side Effects: 1858239Seric ** none. 1868239Seric */ 1878239Seric 1888239Seric /*VARARGS2*/ 18957642Seric #ifdef __STDC__ 19057642Seric nmessage(char *num, char *msg, ...) 19157642Seric #else 19257642Seric nmessage(num, msg, va_alist) 19356852Seric char *num; 19456852Seric char *msg; 19557642Seric va_dcl 19657642Seric #endif 1978239Seric { 19856852Seric VA_LOCAL_DECL 19956852Seric 2008239Seric errno = 0; 20156852Seric VA_START(msg); 20256852Seric fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, ap); 20356852Seric VA_END; 2049108Seric putmsg(MsgBuf, FALSE); 2058239Seric } 2068239Seric /* 2077613Seric ** PUTMSG -- output error message to transcript and channel 2087613Seric ** 2097613Seric ** Parameters: 2107613Seric ** msg -- message to output (in SMTP format). 2119108Seric ** holdmsg -- if TRUE, don't output a copy of the message to 2129108Seric ** our output channel. 2137613Seric ** 2147613Seric ** Returns: 2157613Seric ** none. 2167613Seric ** 2177613Seric ** Side Effects: 2187613Seric ** Outputs msg to the transcript. 2197613Seric ** If appropriate, outputs it to the channel. 2207613Seric ** Deletes SMTP reply code number as appropriate. 2217613Seric */ 2224711Seric 2239108Seric putmsg(msg, holdmsg) 2247613Seric char *msg; 2259108Seric bool holdmsg; 2267613Seric { 22714900Seric /* output to transcript if serious */ 22814900Seric if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5')) 22914900Seric fprintf(CurEnv->e_xfp, "%s\n", msg); 2304711Seric 2314711Seric /* output to channel if appropriate */ 2329108Seric if (!holdmsg && (Verbose || msg[0] != '0')) 2334063Seric { 2347275Seric (void) fflush(stdout); 23552220Seric if (OpMode == MD_SMTP) 2367613Seric fprintf(OutChannel, "%s\r\n", msg); 2374711Seric else 2387613Seric fprintf(OutChannel, "%s\n", &msg[4]); 2394711Seric (void) fflush(OutChannel); 2404063Seric } 2419389Seric } 2429389Seric /* 2439389Seric ** PUTERRMSG -- like putmsg, but does special processing for error messages 2449389Seric ** 2459389Seric ** Parameters: 2469389Seric ** msg -- the message to output. 2479389Seric ** 2489389Seric ** Returns: 2499389Seric ** none. 2509389Seric ** 2519389Seric ** Side Effects: 2529389Seric ** Sets the fatal error bit in the envelope as appropriate. 2539389Seric */ 2548239Seric 2559389Seric puterrmsg(msg) 2569389Seric char *msg; 2579389Seric { 2589389Seric /* output the message as usual */ 2599389Seric putmsg(msg, HoldErrs); 2609389Seric 2619389Seric /* signal the error */ 2629389Seric Errors++; 2639389Seric if (msg[0] == '5') 2649336Seric CurEnv->e_flags |= EF_FATALERRS; 2654711Seric } 2664711Seric /* 2674711Seric ** FMTMSG -- format a message into buffer. 2684711Seric ** 2694711Seric ** Parameters: 2704711Seric ** eb -- error buffer to get result. 2714711Seric ** to -- the recipient tag for this message. 2724711Seric ** num -- arpanet error number. 27316901Seric ** en -- the error number to display. 2744711Seric ** fmt -- format of string. 2754711Seric ** a, b, c, d, e -- arguments. 2764711Seric ** 2774711Seric ** Returns: 2784711Seric ** none. 2794711Seric ** 2804711Seric ** Side Effects: 2814711Seric ** none. 2824711Seric */ 2834063Seric 28446928Sbostic static void 28556852Seric fmtmsg(eb, to, num, eno, fmt, ap) 2864711Seric register char *eb; 2874711Seric char *to; 2884711Seric char *num; 28916904Seric int eno; 2904711Seric char *fmt; 29156852Seric va_list ap; 2924711Seric { 2934711Seric char del; 2944711Seric 2954711Seric /* output the reply code */ 29624943Seric if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2])) 2974577Seric { 2984711Seric num = fmt; 2994711Seric fmt += 4; 3004711Seric } 3014711Seric if (num[3] == '-') 3024711Seric del = '-'; 3034711Seric else 3044711Seric del = ' '; 3054711Seric (void) sprintf(eb, "%3.3s%c", num, del); 3064711Seric eb += 4; 3074063Seric 3089372Seric /* output the file name and line number */ 3099372Seric if (FileName != NULL) 3109372Seric { 3119372Seric (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 3129372Seric eb += strlen(eb); 3139372Seric } 3149372Seric 3154711Seric /* output the "to" person */ 3164711Seric if (to != NULL && to[0] != '\0') 3174711Seric { 3184711Seric (void) sprintf(eb, "%s... ", to); 3195201Seric while (*eb != '\0') 3205201Seric *eb++ &= 0177; 3214711Seric } 3224711Seric 3234711Seric /* output the message */ 32456852Seric (void) vsprintf(eb, fmt, ap); 3255201Seric while (*eb != '\0') 3265201Seric *eb++ &= 0177; 3274711Seric 3284711Seric /* output the error code, if any */ 32916904Seric if (eno != 0) 3304711Seric { 33115136Seric extern char *errstring(); 33215136Seric 33316904Seric (void) sprintf(eb, ": %s", errstring(eno)); 3344711Seric eb += strlen(eb); 3354577Seric } 336295Seric } 33715136Seric /* 33815136Seric ** ERRSTRING -- return string description of error code 33915136Seric ** 34015136Seric ** Parameters: 34115136Seric ** errno -- the error number to translate 34215136Seric ** 34315136Seric ** Returns: 34415136Seric ** A string description of errno. 34515136Seric ** 34615136Seric ** Side Effects: 34715136Seric ** none. 34815136Seric */ 34915136Seric 35015136Seric char * 35115136Seric errstring(errno) 35215136Seric int errno; 35315136Seric { 35415136Seric extern char *sys_errlist[]; 35515136Seric extern int sys_nerr; 35657232Seric static char buf[MAXLINE]; 35724943Seric # ifdef SMTP 35824943Seric extern char *SmtpPhase; 35956795Seric # endif /* SMTP */ 36015136Seric 36124943Seric # ifdef DAEMON 36252107Seric # ifdef ETIMEDOUT 36324943Seric /* 36424943Seric ** Handle special network error codes. 36524943Seric ** 36624943Seric ** These are 4.2/4.3bsd specific; they should be in daemon.c. 36724943Seric */ 36824943Seric 36924943Seric switch (errno) 37024943Seric { 37124943Seric case ETIMEDOUT: 37224943Seric case ECONNRESET: 37324943Seric (void) strcpy(buf, sys_errlist[errno]); 37424943Seric if (SmtpPhase != NULL) 37524943Seric { 37624943Seric (void) strcat(buf, " during "); 37724943Seric (void) strcat(buf, SmtpPhase); 37824943Seric } 37925050Seric if (CurHostName != NULL) 38024943Seric { 38124943Seric (void) strcat(buf, " with "); 38225050Seric (void) strcat(buf, CurHostName); 38324943Seric } 38424943Seric return (buf); 38524943Seric 38624943Seric case EHOSTDOWN: 38725050Seric if (CurHostName == NULL) 38824943Seric break; 38925050Seric (void) sprintf(buf, "Host %s is down", CurHostName); 39024943Seric return (buf); 39124943Seric 39224943Seric case ECONNREFUSED: 39325050Seric if (CurHostName == NULL) 39424943Seric break; 39525050Seric (void) sprintf(buf, "Connection refused by %s", CurHostName); 39624943Seric return (buf); 39725526Smiriam 398*57736Seric # ifdef NAMED_BIND 39925526Smiriam case (TRY_AGAIN+MAX_ERRNO): 40025526Smiriam (void) sprintf(buf, "Host Name Lookup Failure"); 40125526Smiriam return (buf); 402*57736Seric # endif 40324943Seric } 40452107Seric # endif 40552107Seric # endif 40624943Seric 40715136Seric if (errno > 0 && errno < sys_nerr) 40815136Seric return (sys_errlist[errno]); 40915136Seric 41015136Seric (void) sprintf(buf, "Error %d", errno); 41115136Seric return (buf); 41215136Seric } 413