1 /*
2 
3  #    #   ####    ####            ####
4  ##  ##  #       #    #          #    #
5  # ## #   ####   #               #
6  #    #       #  #  ###   ###    #
7  #    #  #    #  #    #   ###    #    #
8  #    #   ####    ####    ###     ####
9 
10 	Fatal messages.
11 */
12 
13 /*
14  * $Id$
15  *
16  *  Copyright (c) 1990-2006, Raphael Manfredi
17  *
18  *  You may redistribute only under the terms of the Artistic License,
19  *  as specified in the README file that comes with the distribution.
20  *  You may reuse parts of this distribution only within the terms of
21  *  that same Artistic License; a copy of which may be found at the root
22  *  of the source tree for mailagent 3.0.
23  *
24  * $Log: msg.c,v $
25  * Revision 3.0.1.5  1999/01/13  18:08:06  ram
26  * patch64: added tag-checking heuristic to say()
27  *
28  * Revision 3.0.1.4  1996/12/24  13:59:31  ram
29  * patch45: call my_exit() instead of exit()
30  *
31  * Revision 3.0.1.3  1995/08/31  16:22:00  ram
32  * patch42: new routine say() to print messages onto stderr
33  * patch42: all messages on stderr now also include the filter pid
34  * patch42: fatal() now prefixes its supplied reason with FATAL
35  *
36  * Revision 3.0.1.2  1995/08/07  16:10:55  ram
37  * patch37: commented and re-organized fatal code for emergency saving
38  *
39  * Revision 3.0.1.1  1994/09/22  13:46:01  ram
40  * patch12: made fatal() arguments long rather than int for 64-bit machines
41  *
42  * Revision 3.0  1993/11/29  13:48:17  ram
43  * Baseline for mailagent 3.0 netwide release.
44  *
45  */
46 
47 #include "config.h"
48 #include "portable.h"
49 #include <stdio.h>
50 #include <sys/types.h>
51 #include <ctype.h>
52 #include "sysexits.h"
53 #include "logfile.h"
54 #include "lock.h"
55 #include "io.h"
56 #include "confmagic.h"
57 
58 #define MAX_STRING	1024		/* Maximum length for error string */
59 
60 extern void my_exit();
61 
62 /* VARARGS2 */
say(msg,arg1,arg2,arg3,arg4,arg5)63 public void say(msg, arg1, arg2, arg3, arg4, arg5)
64 char *msg;
65 long arg1, arg2, arg3, arg4, arg5;	/* Use longs, hope (char *) fits in it! */
66 {
67 	/* Write important message to stderr */
68 
69 	fprintf(stderr, "%s[%d]: ", progname, progpid);
70 	fprintf(stderr, msg, arg1, arg2, arg3, arg4, arg5);
71 	fputc('\n', stderr);
72 
73 	/*
74 	 * A little heuristic here...
75 	 *
76 	 * If the message begins with an upper-cased don't prepend
77 	 * the ERROR tag, assuming a tag was already specified.
78 	 */
79 
80 	if (isupper(msg[0]))
81 		add_log(2, msg, arg1, arg2, arg3, arg4, arg5);
82 	else {
83 		char buffer[MAX_STRING];
84 		sprintf(buffer, "ERROR %s", msg);
85 		add_log(2, buffer, arg1, arg2, arg3, arg4, arg5);
86 	}
87 }
88 
89 /* VARARGS2 */
fatal(reason,arg1,arg2,arg3,arg4,arg5)90 public void fatal(reason, arg1, arg2, arg3, arg4, arg5)
91 char *reason;
92 long arg1, arg2, arg3, arg4, arg5;	/* Use longs, hope (char *) fits in it! */
93 {
94 	/* Fatal error -- die with a meaningful error status for sendmail. If the
95 	 * logfile has been opened, the reason will also be logged there.
96 	 */
97 	char buffer[MAX_STRING];
98 	int status;						/* Status from emergency_save() */
99 
100 	/*
101 	 * Attempt a save as early as possible, since we might not recover
102 	 * from a fprintf() if we came here on a SIGSEGV or a SIGBUS.
103 	 */
104 
105 	status = emergency_save();		/* Attempt emergency saving */
106 
107 	fprintf(stderr, "%s[%d]: FATAL ", progname, progpid);
108 	fprintf(stderr, reason, arg1, arg2, arg3, arg4, arg5);
109 	fputc('\n', stderr);
110 
111 	sprintf(buffer, "FATAL %s", reason);
112 	add_log(1, buffer, arg1, arg2, arg3, arg4, arg5);
113 
114 	release_lock();		/* We're about to exit, free grabbed resources */
115 
116 	/*
117 	 * If the emergency saving failed, then the message is not queued
118 	 * anywhere. We're about to leave the message in the MTA queue in
119 	 * that case, but we must warn them since we have no guarantee the
120 	 * MTA will do as we think it will.
121 	 */
122 
123 	if (status == -1)
124 		add_log(5, "WARNING no saving was ever done");
125 
126 	if (!was_queued()) {
127 		/*
128 		 * Exit with a meaningful exit code for the MTA (sendmail usually) so
129 		 * that it leaves the message in its own queue for later delivery when
130 		 * conditions * are better (hopefully), or it will bounce to the sender
131 		 * after some delay.
132 		 */
133 
134 		add_log(6, "NOTICE leaving mail in MTA's queue");
135 		my_exit(EX_TEMPFAIL);
136 	}
137 
138 	/*
139 	 * Message was saved somewhere where mailagent will find it (either in
140 	 * its queue, or listed in the agent.wait file). There's no need for
141 	 * the MTA to worry, hence the following...
142 	 */
143 
144 	my_exit(EX_OK);
145 }
146 
147