V5 config level; Dj optional on confDOMAIN_NAME
[unix-history] / usr / src / usr.sbin / sendmail / src / err.c
CommitLineData
b2a81223 1/*
dc45ba8c 2 * Copyright (c) 1983 Eric P. Allman
eb0bafab
KB
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
bee79b64 5 *
417f7a11 6 * %sccs.include.redist.c%
bee79b64 7 */
b2a81223
DF
8
9#ifndef lint
9acae8cd 10static char sccsid[] = "@(#)err.c 8.8 (Berkeley) %G%";
bee79b64 11#endif /* not lint */
b2a81223 12
96faada8 13# include "sendmail.h"
2e3062fe 14# include <errno.h>
9fd1518e 15# include <netdb.h>
b3cbe40f
EA
16
17/*
d916f0ca 18** SYSERR -- Print error message.
b3cbe40f
EA
19**
20** Prints an error message via printf to the diagnostic
21** output. If LOG is defined, it logs it also.
22**
e0539260
EA
23** If the first character of the syserr message is `!' it will
24** log this as an ALERT message and exit immediately. This can
25** leave queue files in an indeterminate state, so it should not
26** be used lightly.
27**
b3cbe40f
EA
28** Parameters:
29** f -- the format string
30** a, b, c, d, e -- parameters
31**
32** Returns:
29871fef 33** none
633a2e02 34** Through TopFrame if QuickAbort is set.
b3cbe40f
EA
35**
36** Side Effects:
d916f0ca
EA
37** increments Errors.
38** sets ExitStat.
b3cbe40f
EA
39*/
40
044ab67a 41char MsgBuf[BUFSIZ*2]; /* text of most recent message */
29871fef 42
35f1f39e
EA
43static void fmtmsg();
44
45#if defined(NAMED_BIND) && !defined(NO_DATA)
46# define NO_DATA NO_ADDRESS
47#endif
0df908a9 48
36335805 49void
b3cbe40f 50/*VARARGS1*/
6e99f903 51#ifdef __STDC__
c51d6c4c 52syserr(const char *fmt, ...)
6e99f903
EA
53#else
54syserr(fmt, va_alist)
c51d6c4c 55 const char *fmt;
6e99f903
EA
56 va_dcl
57#endif
b3cbe40f 58{
177b9da3
EA
59 register char *p;
60 int olderrno = errno;
e0539260 61 bool panic;
5229f34d 62 VA_LOCAL_DECL
b3cbe40f 63
e0539260
EA
64 panic = *fmt == '!';
65 if (panic)
66 fmt++;
67
d5dba2cd 68 /* format and output the error message */
177b9da3 69 if (olderrno == 0)
b6edea3d 70 p = "554";
314d2f52 71 else
b6edea3d 72 p = "451";
5229f34d
EA
73 VA_START(fmt);
74 fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
75 VA_END;
80482eb5 76 puterrmsg(MsgBuf);
f4e91ea7 77
b3cbe40f
EA
78 /* determine exit status if not already set */
79 if (ExitStat == EX_OK)
80 {
177b9da3 81 if (olderrno == 0)
b3cbe40f
EA
82 ExitStat = EX_SOFTWARE;
83 else
21ec078e 84 ExitStat = EX_OSERR;
b3cbe40f
EA
85 }
86
87# ifdef LOG
9678c96d 88 if (LogLevel > 0)
e0539260 89 syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR: %s",
3312f93c
EA
90 CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
91 &MsgBuf[4]);
f3d8f6d6 92# endif /* LOG */
e0539260 93 if (panic)
b4f81c5d
EA
94 {
95#ifdef XLA
96 xla_all_end();
97#endif
e0539260 98 exit(EX_OSERR);
b4f81c5d 99 }
b3cbe40f 100 errno = 0;
633a2e02
EA
101 if (QuickAbort)
102 longjmp(TopFrame, 2);
b3cbe40f
EA
103}
104\f/*
105** USRERR -- Signal user error.
106**
107** This is much like syserr except it is for user errors.
108**
109** Parameters:
110** fmt, a, b, c, d -- printf strings
111**
112** Returns:
29871fef 113** none
633a2e02 114** Through TopFrame if QuickAbort is set.
b3cbe40f
EA
115**
116** Side Effects:
d916f0ca 117** increments Errors.
b3cbe40f
EA
118*/
119
120/*VARARGS1*/
94bc039a 121void
36335805 122#ifdef __STDC__
c51d6c4c 123usrerr(const char *fmt, ...)
6e99f903
EA
124#else
125usrerr(fmt, va_alist)
c51d6c4c 126 const char *fmt;
6e99f903
EA
127 va_dcl
128#endif
b3cbe40f 129{
5229f34d 130 VA_LOCAL_DECL
b3cbe40f 131 extern char SuprErrs;
177b9da3 132 extern int errno;
b3cbe40f
EA
133
134 if (SuprErrs)
29871fef 135 return;
f4e91ea7 136
5229f34d 137 VA_START(fmt);
75593899 138 fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
5229f34d 139 VA_END;
80482eb5 140 puterrmsg(MsgBuf);
21f25858 141
f61c3c40 142# ifdef LOG
68f7099c 143 if (LogLevel > 3 && LogUsrErrs)
f61c3c40
EA
144 syslog(LOG_NOTICE, "%s: %s",
145 CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
146 &MsgBuf[4]);
f3d8f6d6 147# endif /* LOG */
f61c3c40 148
633a2e02
EA
149 if (QuickAbort)
150 longjmp(TopFrame, 1);
f4e91ea7
EA
151}
152\f/*
153** MESSAGE -- print message (not necessarily an error)
154**
155** Parameters:
62869b50
EA
156** msg -- the message (printf fmt) -- it can begin with
157** an SMTP reply code. If not, 050 is assumed.
f4e91ea7
EA
158** a, b, c, d, e -- printf arguments
159**
160** Returns:
161** none
162**
163** Side Effects:
164** none.
165*/
166
29871fef 167/*VARARGS2*/
94bc039a 168void
319b1ec0 169#ifdef __STDC__
c51d6c4c 170message(const char *msg, ...)
6e99f903 171#else
b6edea3d 172message(msg, va_alist)
c51d6c4c 173 const char *msg;
6e99f903
EA
174 va_dcl
175#endif
f4e91ea7 176{
5229f34d
EA
177 VA_LOCAL_DECL
178
49086753 179 errno = 0;
5229f34d 180 VA_START(msg);
b6edea3d 181 fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
5229f34d 182 VA_END;
8e5c6745 183 putoutmsg(MsgBuf, FALSE);
015bb651
EA
184}
185\f/*
21f25858
EA
186** NMESSAGE -- print message (not necessarily an error)
187**
188** Just like "message" except it never puts the to... tag on.
189**
190** Parameters:
191** num -- the default ARPANET error number (in ascii)
192** msg -- the message (printf fmt) -- if it begins
2e3062fe 193** with three digits, this number overrides num.
21f25858
EA
194** a, b, c, d, e -- printf arguments
195**
196** Returns:
197** none
198**
199** Side Effects:
200** none.
201*/
202
203/*VARARGS2*/
94bc039a 204void
319b1ec0 205#ifdef __STDC__
c51d6c4c 206nmessage(const char *msg, ...)
6e99f903 207#else
b6edea3d 208nmessage(msg, va_alist)
c51d6c4c 209 const char *msg;
6e99f903
EA
210 va_dcl
211#endif
21f25858 212{
5229f34d
EA
213 VA_LOCAL_DECL
214
21f25858 215 errno = 0;
5229f34d 216 VA_START(msg);
b6edea3d 217 fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
5229f34d 218 VA_END;
8e5c6745 219 putoutmsg(MsgBuf, FALSE);
21f25858
EA
220}
221\f/*
8e5c6745 222** PUTOUTMSG -- output error message to transcript and channel
015bb651
EA
223**
224** Parameters:
225** msg -- message to output (in SMTP format).
6a766659
EA
226** holdmsg -- if TRUE, don't output a copy of the message to
227** our output channel.
015bb651
EA
228**
229** Returns:
230** none.
231**
232** Side Effects:
233** Outputs msg to the transcript.
234** If appropriate, outputs it to the channel.
235** Deletes SMTP reply code number as appropriate.
236*/
49086753 237
8e5c6745 238putoutmsg(msg, holdmsg)
015bb651 239 char *msg;
6a766659 240 bool holdmsg;
015bb651 241{
9acae8cd
EA
242 /* display for debugging */
243 if (tTd(54, 8))
244 printf("--- %s%s\n", msg, holdmsg ? " (held)" : "");
245
d7dbe85b 246 /* output to transcript if serious */
5e2168d0 247 if (CurEnv->e_xfp != NULL && strchr("456", msg[0]) != NULL)
d7dbe85b 248 fprintf(CurEnv->e_xfp, "%s\n", msg);
49086753
EA
249
250 /* output to channel if appropriate */
d907841d
EA
251 if (holdmsg || (!Verbose && msg[0] == '0'))
252 return;
253
5e2168d0
EA
254 /* map warnings to something SMTP can handle */
255 if (msg[0] == '6')
256 msg[0] = '5';
257
d907841d
EA
258 (void) fflush(stdout);
259 if (OpMode == MD_SMTP)
260 fprintf(OutChannel, "%s\r\n", msg);
261 else
262 fprintf(OutChannel, "%s\n", &msg[4]);
8e5c6745
EA
263 if (TrafficLogFile != NULL)
264 fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(),
265 OpMode == MD_SMTP ? msg : &msg[4]);
d907841d
EA
266 if (msg[3] == ' ')
267 (void) fflush(OutChannel);
268 if (!ferror(OutChannel))
269 return;
270
271 /* error on output -- if reporting lost channel, just ignore it */
272 if (feof(InChannel) || ferror(InChannel))
273 return;
274
275 /* can't call syserr, 'cause we are using MsgBuf */
276 HoldErrs = TRUE;
a9145676 277#ifdef LOG
d907841d
EA
278 if (LogLevel > 0)
279 syslog(LOG_CRIT,
8e5c6745 280 "%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\"",
d907841d 281 CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
548e1aec
EA
282 CurHostName == NULL ? "NO-HOST" : CurHostName,
283 msg);
a9145676 284#endif
80482eb5
EA
285}
286\f/*
8e5c6745 287** PUTERRMSG -- like putoutmsg, but does special processing for error messages
80482eb5
EA
288**
289** Parameters:
290** msg -- the message to output.
291**
292** Returns:
293** none.
294**
295** Side Effects:
296** Sets the fatal error bit in the envelope as appropriate.
297*/
21f25858 298
80482eb5
EA
299puterrmsg(msg)
300 char *msg;
301{
5e2168d0
EA
302 char msgcode = msg[0];
303
80482eb5 304 /* output the message as usual */
8e5c6745 305 putoutmsg(msg, HoldErrs);
21f25858 306
80482eb5 307 /* signal the error */
5e2168d0
EA
308 if (msgcode == '6')
309 {
310 /* notify the postmaster */
311 CurEnv->e_flags |= EF_PM_NOTIFY;
312 }
313 else
314 {
315 Errors++;
316 if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
317 CurEnv->e_flags |= EF_FATALERRS;
318 }
49086753
EA
319}
320\f/*
321** FMTMSG -- format a message into buffer.
322**
323** Parameters:
324** eb -- error buffer to get result.
325** to -- the recipient tag for this message.
326** num -- arpanet error number.
177b9da3 327** en -- the error number to display.
49086753
EA
328** fmt -- format of string.
329** a, b, c, d, e -- arguments.
330**
331** Returns:
332** none.
333**
334** Side Effects:
335** none.
336*/
337
0df908a9 338static void
5229f34d 339fmtmsg(eb, to, num, eno, fmt, ap)
49086753
EA
340 register char *eb;
341 char *to;
342 char *num;
e1e01376 343 int eno;
49086753 344 char *fmt;
5229f34d 345 va_list ap;
49086753
EA
346{
347 char del;
c281eee3 348 char *meb;
49086753
EA
349
350 /* output the reply code */
2e3062fe 351 if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
f4e91ea7 352 {
49086753
EA
353 num = fmt;
354 fmt += 4;
f4e91ea7 355 }
49086753
EA
356 if (num[3] == '-')
357 del = '-';
358 else
359 del = ' ';
360 (void) sprintf(eb, "%3.3s%c", num, del);
361 eb += 4;
f4e91ea7 362
7338e3d4
EA
363 /* output the file name and line number */
364 if (FileName != NULL)
365 {
366 (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
367 eb += strlen(eb);
368 }
369
49086753
EA
370 /* output the "to" person */
371 if (to != NULL && to[0] != '\0')
34d37b7d 372 {
49086753 373 (void) sprintf(eb, "%s... ", to);
6593367a
EA
374 while (*eb != '\0')
375 *eb++ &= 0177;
49086753
EA
376 }
377
c281eee3
EA
378 meb = eb;
379
49086753 380 /* output the message */
5229f34d 381 (void) vsprintf(eb, fmt, ap);
6593367a
EA
382 while (*eb != '\0')
383 *eb++ &= 0177;
34d37b7d 384
49086753 385 /* output the error code, if any */
e1e01376 386 if (eno != 0)
49086753 387 {
e1e01376 388 (void) sprintf(eb, ": %s", errstring(eno));
49086753 389 eb += strlen(eb);
34d37b7d 390 }
c281eee3 391
7ffb494c 392 if (CurEnv->e_message == NULL && strchr("45", num[0]) != NULL)
c281eee3 393 CurEnv->e_message = newstr(meb);
b3cbe40f 394}
e41c463e
EA
395\f/*
396** ERRSTRING -- return string description of error code
397**
398** Parameters:
399** errno -- the error number to translate
400**
401** Returns:
402** A string description of errno.
403**
404** Side Effects:
405** none.
406*/
407
713c523f 408const char *
e41c463e
EA
409errstring(errno)
410 int errno;
411{
f43b04ce 412 static char buf[MAXLINE];
d4f6a25e
EA
413# ifndef ERRLIST_PREDEFINED
414 extern char *sys_errlist[];
415 extern int sys_nerr;
416# endif
2e3062fe
EA
417# ifdef SMTP
418 extern char *SmtpPhase;
f3d8f6d6 419# endif /* SMTP */
2e3062fe
EA
420
421# ifdef DAEMON
140717b5 422# ifdef ETIMEDOUT
2e3062fe
EA
423 /*
424 ** Handle special network error codes.
425 **
426 ** These are 4.2/4.3bsd specific; they should be in daemon.c.
427 */
428
429 switch (errno)
430 {
431 case ETIMEDOUT:
432 case ECONNRESET:
433 (void) strcpy(buf, sys_errlist[errno]);
434 if (SmtpPhase != NULL)
435 {
436 (void) strcat(buf, " during ");
437 (void) strcat(buf, SmtpPhase);
438 }
57c97d4a 439 if (CurHostName != NULL)
2e3062fe
EA
440 {
441 (void) strcat(buf, " with ");
57c97d4a 442 (void) strcat(buf, CurHostName);
2e3062fe
EA
443 }
444 return (buf);
445
446 case EHOSTDOWN:
57c97d4a 447 if (CurHostName == NULL)
2e3062fe 448 break;
57c97d4a 449 (void) sprintf(buf, "Host %s is down", CurHostName);
2e3062fe
EA
450 return (buf);
451
452 case ECONNREFUSED:
57c97d4a 453 if (CurHostName == NULL)
2e3062fe 454 break;
57c97d4a 455 (void) sprintf(buf, "Connection refused by %s", CurHostName);
2e3062fe 456 return (buf);
9fd1518e 457
92f2b65e
EA
458 case EOPENTIMEOUT:
459 return "Timeout on file open";
460
6feb509e 461# ifdef NAMED_BIND
92f2b65e 462 case HOST_NOT_FOUND + E_DNSBASE:
49a282c6
EA
463 return ("Name server: host not found");
464
92f2b65e 465 case TRY_AGAIN + E_DNSBASE:
49a282c6
EA
466 return ("Name server: host name lookup failure");
467
92f2b65e 468 case NO_RECOVERY + E_DNSBASE:
49a282c6
EA
469 return ("Name server: non-recoverable error");
470
92f2b65e 471 case NO_DATA + E_DNSBASE:
49a282c6 472 return ("Name server: no data known for name");
6feb509e 473# endif
2e3062fe 474 }
140717b5
EA
475# endif
476# endif
e41c463e
EA
477
478 if (errno > 0 && errno < sys_nerr)
479 return (sys_errlist[errno]);
480
481 (void) sprintf(buf, "Error %d", errno);
482 return (buf);
483}