xref: /csrg-svn/usr.sbin/sendmail/src/err.c (revision 9277)
1 # include "sendmail.h"
2 
3 SCCSID(@(#)err.c	3.33		11/17/82);
4 
5 /*
6 **  SYSERR -- Print error message.
7 **
8 **	Prints an error message via printf to the diagnostic
9 **	output.  If LOG is defined, it logs it also.
10 **
11 **	Parameters:
12 **		f -- the format string
13 **		a, b, c, d, e -- parameters
14 **
15 **	Returns:
16 **		none
17 **		Through TopFrame if QuickAbort is set.
18 **
19 **	Side Effects:
20 **		increments Errors.
21 **		sets ExitStat.
22 */
23 
24 # ifdef lint
25 int	sys_nerr;
26 char	*sys_errlist[];
27 # endif lint
28 static char	MsgBuf[BUFSIZ*2];	/* text of most recent message */
29 
30 /*VARARGS1*/
31 syserr(fmt, a, b, c, d, e)
32 	char *fmt;
33 {
34 	extern char Arpa_PSyserr[];
35 	extern char Arpa_TSyserr[];
36 	register char *p;
37 
38 	/* format and output the error message */
39 	if (errno == 0)
40 		p = Arpa_PSyserr;
41 	else
42 		p = Arpa_TSyserr;
43 	fmtmsg(MsgBuf, (char *) NULL, p, fmt, a, b, c, d, e);
44 	putmsg(MsgBuf, HoldErrs);
45 
46 	/* determine exit status if not already set */
47 	if (ExitStat == EX_OK)
48 	{
49 		if (errno == 0)
50 			ExitStat = EX_SOFTWARE;
51 		else
52 			ExitStat = EX_OSERR;
53 	}
54 
55 	(void) queuename(CurEnv, '\0');
56 # ifdef LOG
57 	if (LogLevel > 0)
58 		syslog(LOG_ERR, "%s: %s", CurEnv->e_id, &MsgBuf[4]);
59 # endif LOG
60 	errno = 0;
61 	if (QuickAbort)
62 		longjmp(TopFrame, 2);
63 }
64 /*
65 **  USRERR -- Signal user error.
66 **
67 **	This is much like syserr except it is for user errors.
68 **
69 **	Parameters:
70 **		fmt, a, b, c, d -- printf strings
71 **
72 **	Returns:
73 **		none
74 **		Through TopFrame if QuickAbort is set.
75 **
76 **	Side Effects:
77 **		increments Errors.
78 */
79 
80 /*VARARGS1*/
81 usrerr(fmt, a, b, c, d, e)
82 	char *fmt;
83 {
84 	extern char SuprErrs;
85 	extern char Arpa_Usrerr[];
86 
87 	if (SuprErrs)
88 		return;
89 
90 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, fmt, a, b, c, d, e);
91 	putmsg(MsgBuf, HoldErrs);
92 
93 	if (QuickAbort)
94 		longjmp(TopFrame, 1);
95 }
96 /*
97 **  MESSAGE -- print message (not necessarily an error)
98 **
99 **	Parameters:
100 **		num -- the default ARPANET error number (in ascii)
101 **		msg -- the message (printf fmt) -- if it begins
102 **			with a digit, this number overrides num.
103 **		a, b, c, d, e -- printf arguments
104 **
105 **	Returns:
106 **		none
107 **
108 **	Side Effects:
109 **		none.
110 */
111 
112 /*VARARGS2*/
113 message(num, msg, a, b, c, d, e)
114 	register char *num;
115 	register char *msg;
116 {
117 	errno = 0;
118 	fmtmsg(MsgBuf, CurEnv->e_to, num, msg, a, b, c, d, e);
119 	putmsg(MsgBuf, FALSE);
120 }
121 /*
122 **  NMESSAGE -- print message (not necessarily an error)
123 **
124 **	Just like "message" except it never puts the to... tag on.
125 **
126 **	Parameters:
127 **		num -- the default ARPANET error number (in ascii)
128 **		msg -- the message (printf fmt) -- if it begins
129 **			with a digit, this number overrides num.
130 **		a, b, c, d, e -- printf arguments
131 **
132 **	Returns:
133 **		none
134 **
135 **	Side Effects:
136 **		none.
137 */
138 
139 /*VARARGS2*/
140 nmessage(num, msg, a, b, c, d, e)
141 	register char *num;
142 	register char *msg;
143 {
144 	errno = 0;
145 	fmtmsg(MsgBuf, NULL, num, msg, a, b, c, d, e);
146 	putmsg(MsgBuf, FALSE);
147 }
148 /*
149 **  PUTMSG -- output error message to transcript and channel
150 **
151 **	Parameters:
152 **		msg -- message to output (in SMTP format).
153 **		holdmsg -- if TRUE, don't output a copy of the message to
154 **			our output channel.
155 **
156 **	Returns:
157 **		none.
158 **
159 **	Side Effects:
160 **		Outputs msg to the transcript.
161 **		If appropriate, outputs it to the channel.
162 **		Deletes SMTP reply code number as appropriate.
163 */
164 
165 putmsg(msg, holdmsg)
166 	char *msg;
167 	bool holdmsg;
168 {
169 	/* output to transcript */
170 	if (Xscript != OutChannel)
171 		fprintf(Xscript, "%s\n", OpMode == MD_SMTP ? msg : &msg[4]);
172 
173 	/* output to channel if appropriate */
174 	if (!holdmsg && (Verbose || msg[0] != '0'))
175 	{
176 		(void) fflush(stdout);
177 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
178 			fprintf(OutChannel, "%s\r\n", msg);
179 		else
180 			fprintf(OutChannel, "%s\n", &msg[4]);
181 		(void) fflush(OutChannel);
182 	}
183 
184 	/* determine error status */
185 	switch (msg[0])
186 	{
187 	  case '5':
188 		FatalErrors = TRUE;
189 		/* fall through.... */
190 
191 	  case '4':
192 		Errors++;
193 		break;
194 	}
195 }
196 /*
197 **  FMTMSG -- format a message into buffer.
198 **
199 **	Parameters:
200 **		eb -- error buffer to get result.
201 **		to -- the recipient tag for this message.
202 **		num -- arpanet error number.
203 **		fmt -- format of string.
204 **		a, b, c, d, e -- arguments.
205 **
206 **	Returns:
207 **		none.
208 **
209 **	Side Effects:
210 **		none.
211 */
212 
213 /*VARARGS4*/
214 static
215 fmtmsg(eb, to, num, fmt, a, b, c, d, e)
216 	register char *eb;
217 	char *to;
218 	char *num;
219 	char *fmt;
220 {
221 	char del;
222 
223 	/* output the reply code */
224 	if (isdigit(*fmt))
225 	{
226 		num = fmt;
227 		fmt += 4;
228 	}
229 	if (num[3] == '-')
230 		del = '-';
231 	else
232 		del = ' ';
233 	(void) sprintf(eb, "%3.3s%c", num, del);
234 	eb += 4;
235 
236 	/* output the "to" person */
237 	if (to != NULL && to[0] != '\0')
238 	{
239 		(void) sprintf(eb, "%s... ", to);
240 		while (*eb != '\0')
241 			*eb++ &= 0177;
242 	}
243 
244 	/* output the message */
245 	(void) sprintf(eb, fmt, a, b, c, d, e);
246 	while (*eb != '\0')
247 		*eb++ &= 0177;
248 
249 	/* output the error code, if any */
250 	if (errno != 0)
251 	{
252 		extern int sys_nerr;
253 		extern char *sys_errlist[];
254 		if (errno < sys_nerr && errno > 0)
255 			(void) sprintf(eb, ": %s", sys_errlist[errno]);
256 		else
257 			(void) sprintf(eb, ": error %d", errno);
258 		eb += strlen(eb);
259 	}
260 }
261