home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / sendmail / src / err.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-20  |  8.6 KB  |  396 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *    This product includes software developed by the University of
  17.  *    California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34.  
  35. #ifndef lint
  36. static char sccsid[] = "@(#)err.c    5.11 (Berkeley) 3/2/91";
  37. #endif /* not lint */
  38.  
  39. # include "sendmail.h"
  40. # include <errno.h>
  41. # include <netdb.h>
  42.  
  43. /*
  44. **  SYSERR -- Print error message.
  45. **
  46. **    Prints an error message via printf to the diagnostic
  47. **    output.  If LOG is defined, it logs it also.
  48. **
  49. **    Parameters:
  50. **        f -- the format string
  51. **        a, b, c, d, e -- parameters
  52. **
  53. **    Returns:
  54. **        none
  55. **        Through TopFrame if QuickAbort is set.
  56. **
  57. **    Side Effects:
  58. **        increments Errors.
  59. **        sets ExitStat.
  60. */
  61.  
  62. # ifdef lint
  63. int    sys_nerr;
  64. char    *sys_errlist[];
  65. # endif lint
  66. char    MsgBuf[BUFSIZ*2];    /* text of most recent message */
  67.  
  68. static void fmtmsg();
  69.  
  70. /*VARARGS1*/
  71. syserr(fmt, a, b, c, d, e)
  72.     char *fmt;
  73. {
  74.     register char *p;
  75.     int olderrno = errno;
  76.     extern char Arpa_PSyserr[];
  77.     extern char Arpa_TSyserr[];
  78.  
  79.     /* format and output the error message */
  80.     if (olderrno == 0)
  81.         p = Arpa_PSyserr;
  82.     else
  83.         p = Arpa_TSyserr;
  84.     fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
  85.     puterrmsg(MsgBuf);
  86.  
  87.     /* determine exit status if not already set */
  88.     if (ExitStat == EX_OK)
  89.     {
  90.         if (olderrno == 0)
  91.             ExitStat = EX_SOFTWARE;
  92.         else
  93.             ExitStat = EX_OSERR;
  94.     }
  95.  
  96. # ifdef LOG
  97.     if (LogLevel > 0)
  98.         syslog(LOG_CRIT, "%s: SYSERR: %s",
  99.             CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
  100.             &MsgBuf[4]);
  101. # endif LOG
  102.     errno = 0;
  103.     if (QuickAbort)
  104.         longjmp(TopFrame, 2);
  105. }
  106. /*
  107. **  USRERR -- Signal user error.
  108. **
  109. **    This is much like syserr except it is for user errors.
  110. **
  111. **    Parameters:
  112. **        fmt, a, b, c, d -- printf strings
  113. **
  114. **    Returns:
  115. **        none
  116. **        Through TopFrame if QuickAbort is set.
  117. **
  118. **    Side Effects:
  119. **        increments Errors.
  120. */
  121.  
  122. /*VARARGS1*/
  123. usrerr(fmt, a, b, c, d, e)
  124.     char *fmt;
  125. {
  126.     extern char SuprErrs;
  127.     extern char Arpa_Usrerr[];
  128.     extern int errno;
  129.  
  130.     if (SuprErrs)
  131.         return;
  132.  
  133.     fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
  134.     puterrmsg(MsgBuf);
  135.  
  136.     if (QuickAbort)
  137.         longjmp(TopFrame, 1);
  138. }
  139. /*
  140. **  MESSAGE -- print message (not necessarily an error)
  141. **
  142. **    Parameters:
  143. **        num -- the default ARPANET error number (in ascii)
  144. **        msg -- the message (printf fmt) -- if it begins
  145. **            with a digit, this number overrides num.
  146. **        a, b, c, d, e -- printf arguments
  147. **
  148. **    Returns:
  149. **        none
  150. **
  151. **    Side Effects:
  152. **        none.
  153. */
  154.  
  155. /*VARARGS2*/
  156. message(num, msg, a, b, c, d, e)
  157.     register char *num;
  158.     register char *msg;
  159. {
  160.     errno = 0;
  161.     fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
  162.     putmsg(MsgBuf, FALSE);
  163. }
  164. /*
  165. **  NMESSAGE -- print message (not necessarily an error)
  166. **
  167. **    Just like "message" except it never puts the to... tag on.
  168. **
  169. **    Parameters:
  170. **        num -- the default ARPANET error number (in ascii)
  171. **        msg -- the message (printf fmt) -- if it begins
  172. **            with three digits, this number overrides num.
  173. **        a, b, c, d, e -- printf arguments
  174. **
  175. **    Returns:
  176. **        none
  177. **
  178. **    Side Effects:
  179. **        none.
  180. */
  181.  
  182. /*VARARGS2*/
  183. nmessage(num, msg, a, b, c, d, e)
  184.     register char *num;
  185.     register char *msg;
  186. {
  187.     errno = 0;
  188.     fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
  189.     putmsg(MsgBuf, FALSE);
  190. }
  191. /*
  192. **  PUTMSG -- output error message to transcript and channel
  193. **
  194. **    Parameters:
  195. **        msg -- message to output (in SMTP format).
  196. **        holdmsg -- if TRUE, don't output a copy of the message to
  197. **            our output channel.
  198. **
  199. **    Returns:
  200. **        none.
  201. **
  202. **    Side Effects:
  203. **        Outputs msg to the transcript.
  204. **        If appropriate, outputs it to the channel.
  205. **        Deletes SMTP reply code number as appropriate.
  206. */
  207.  
  208. putmsg(msg, holdmsg)
  209.     char *msg;
  210.     bool holdmsg;
  211. {
  212.     /* output to transcript if serious */
  213.     if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
  214.         fprintf(CurEnv->e_xfp, "%s\n", msg);
  215.  
  216.     /* output to channel if appropriate */
  217.     if (!holdmsg && (Verbose || msg[0] != '0'))
  218.     {
  219.         (void) fflush(stdout);
  220.         if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
  221.             fprintf(OutChannel, "%s\r\n", msg);
  222.         else
  223.             fprintf(OutChannel, "%s\n", &msg[4]);
  224.         (void) fflush(OutChannel);
  225.     }
  226. }
  227. /*
  228. **  PUTERRMSG -- like putmsg, but does special processing for error messages
  229. **
  230. **    Parameters:
  231. **        msg -- the message to output.
  232. **
  233. **    Returns:
  234. **        none.
  235. **
  236. **    Side Effects:
  237. **        Sets the fatal error bit in the envelope as appropriate.
  238. */
  239.  
  240. puterrmsg(msg)
  241.     char *msg;
  242. {
  243.     /* output the message as usual */
  244.     putmsg(msg, HoldErrs);
  245.  
  246.     /* signal the error */
  247.     Errors++;
  248.     if (msg[0] == '5')
  249.         CurEnv->e_flags |= EF_FATALERRS;
  250. }
  251. /*
  252. **  FMTMSG -- format a message into buffer.
  253. **
  254. **    Parameters:
  255. **        eb -- error buffer to get result.
  256. **        to -- the recipient tag for this message.
  257. **        num -- arpanet error number.
  258. **        en -- the error number to display.
  259. **        fmt -- format of string.
  260. **        a, b, c, d, e -- arguments.
  261. **
  262. **    Returns:
  263. **        none.
  264. **
  265. **    Side Effects:
  266. **        none.
  267. */
  268.  
  269. /*VARARGS5*/
  270. static void
  271. fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
  272.     register char *eb;
  273.     char *to;
  274.     char *num;
  275.     int eno;
  276.     char *fmt;
  277. {
  278.     char del;
  279.  
  280.     /* output the reply code */
  281.     if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
  282.     {
  283.         num = fmt;
  284.         fmt += 4;
  285.     }
  286.     if (num[3] == '-')
  287.         del = '-';
  288.     else
  289.         del = ' ';
  290.     (void) sprintf(eb, "%3.3s%c", num, del);
  291.     eb += 4;
  292.  
  293.     /* output the file name and line number */
  294.     if (FileName != NULL)
  295.     {
  296.         (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
  297.         eb += strlen(eb);
  298.     }
  299.  
  300.     /* output the "to" person */
  301.     if (to != NULL && to[0] != '\0')
  302.     {
  303.         (void) sprintf(eb, "%s... ", to);
  304.         while (*eb != '\0')
  305.             *eb++ &= 0177;
  306.     }
  307.  
  308.     /* output the message */
  309.     (void) sprintf(eb, fmt, a, b, c, d, e);
  310.     while (*eb != '\0')
  311.         *eb++ &= 0177;
  312.  
  313.     /* output the error code, if any */
  314.     if (eno != 0)
  315.     {
  316.         extern char *errstring();
  317.  
  318.         (void) sprintf(eb, ": %s", errstring(eno));
  319.         eb += strlen(eb);
  320.     }
  321. }
  322. /*
  323. **  ERRSTRING -- return string description of error code
  324. **
  325. **    Parameters:
  326. **        errno -- the error number to translate
  327. **
  328. **    Returns:
  329. **        A string description of errno.
  330. **
  331. **    Side Effects:
  332. **        none.
  333. */
  334.  
  335. char *
  336. errstring(errno)
  337.     int errno;
  338. {
  339.     extern char *sys_errlist[];
  340.     extern int sys_nerr;
  341.     static char buf[100];
  342. # ifdef SMTP
  343.     extern char *SmtpPhase;
  344. # endif SMTP
  345.  
  346. # ifdef DAEMON
  347. # ifdef VMUNIX
  348.     /*
  349.     **  Handle special network error codes.
  350.     **
  351.     **    These are 4.2/4.3bsd specific; they should be in daemon.c.
  352.     */
  353.  
  354.     switch (errno)
  355.     {
  356.       case ETIMEDOUT:
  357.       case ECONNRESET:
  358.         (void) strcpy(buf, sys_errlist[errno]);
  359.         if (SmtpPhase != NULL)
  360.         {
  361.             (void) strcat(buf, " during ");
  362.             (void) strcat(buf, SmtpPhase);
  363.         }
  364.         if (CurHostName != NULL)
  365.         {
  366.             (void) strcat(buf, " with ");
  367.             (void) strcat(buf, CurHostName);
  368.         }
  369.         return (buf);
  370.  
  371.       case EHOSTDOWN:
  372.         if (CurHostName == NULL)
  373.             break;
  374.         (void) sprintf(buf, "Host %s is down", CurHostName);
  375.         return (buf);
  376.  
  377.       case ECONNREFUSED:
  378.         if (CurHostName == NULL)
  379.             break;
  380.         (void) sprintf(buf, "Connection refused by %s", CurHostName);
  381.         return (buf);
  382.  
  383.       case (TRY_AGAIN+MAX_ERRNO):
  384.         (void) sprintf(buf, "Host Name Lookup Failure");
  385.         return (buf);
  386.     }
  387. # endif VMUNIX
  388. # endif DAEMON
  389.  
  390.     if (errno > 0 && errno < sys_nerr)
  391.         return (sys_errlist[errno]);
  392.  
  393.     (void) sprintf(buf, "Error %d", errno);
  394.     return (buf);
  395. }
  396.