xref: /original-bsd/usr.sbin/sendmail/src/err.c (revision 4c01ad61)
1 # include "sendmail.h"
2 
3 SCCSID(@(#)err.c	4.6		04/04/85);
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 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 	register char *p;
35 	int olderrno = errno;
36 	extern char Arpa_PSyserr[];
37 	extern char Arpa_TSyserr[];
38 
39 	/* format and output the error message */
40 	if (olderrno == 0)
41 		p = Arpa_PSyserr;
42 	else
43 		p = Arpa_TSyserr;
44 	fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
45 	puterrmsg(MsgBuf);
46 
47 	/* determine exit status if not already set */
48 	if (ExitStat == EX_OK)
49 	{
50 		if (olderrno == 0)
51 			ExitStat = EX_SOFTWARE;
52 		else
53 			ExitStat = EX_OSERR;
54 	}
55 
56 	/* insure that we have a queue id for logging */
57 	(void) queuename(CurEnv, '\0');
58 # ifdef LOG
59 	if (LogLevel > 0)
60 		syslog(LOG_MAIL, "%s: SYSERR: %s", CurEnv->e_id, &MsgBuf[4]);
61 # endif LOG
62 	errno = 0;
63 	if (QuickAbort)
64 		longjmp(TopFrame, 2);
65 }
66 /*
67 **  USRERR -- Signal user error.
68 **
69 **	This is much like syserr except it is for user errors.
70 **
71 **	Parameters:
72 **		fmt, a, b, c, d -- printf strings
73 **
74 **	Returns:
75 **		none
76 **		Through TopFrame if QuickAbort is set.
77 **
78 **	Side Effects:
79 **		increments Errors.
80 */
81 
82 /*VARARGS1*/
83 usrerr(fmt, a, b, c, d, e)
84 	char *fmt;
85 {
86 	extern char SuprErrs;
87 	extern char Arpa_Usrerr[];
88 	extern int errno;
89 
90 	if (SuprErrs)
91 		return;
92 
93 	fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
94 	puterrmsg(MsgBuf);
95 
96 	if (QuickAbort)
97 		longjmp(TopFrame, 1);
98 }
99 /*
100 **  MESSAGE -- print message (not necessarily an error)
101 **
102 **	Parameters:
103 **		num -- the default ARPANET error number (in ascii)
104 **		msg -- the message (printf fmt) -- if it begins
105 **			with a digit, this number overrides num.
106 **		a, b, c, d, e -- printf arguments
107 **
108 **	Returns:
109 **		none
110 **
111 **	Side Effects:
112 **		none.
113 */
114 
115 /*VARARGS2*/
116 message(num, msg, a, b, c, d, e)
117 	register char *num;
118 	register char *msg;
119 {
120 	errno = 0;
121 	fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
122 	putmsg(MsgBuf, FALSE);
123 }
124 /*
125 **  NMESSAGE -- print message (not necessarily an error)
126 **
127 **	Just like "message" except it never puts the to... tag on.
128 **
129 **	Parameters:
130 **		num -- the default ARPANET error number (in ascii)
131 **		msg -- the message (printf fmt) -- if it begins
132 **			with a digit, this number overrides num.
133 **		a, b, c, d, e -- printf arguments
134 **
135 **	Returns:
136 **		none
137 **
138 **	Side Effects:
139 **		none.
140 */
141 
142 /*VARARGS2*/
143 nmessage(num, msg, a, b, c, d, e)
144 	register char *num;
145 	register char *msg;
146 {
147 	errno = 0;
148 	fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
149 	putmsg(MsgBuf, FALSE);
150 }
151 /*
152 **  PUTMSG -- output error message to transcript and channel
153 **
154 **	Parameters:
155 **		msg -- message to output (in SMTP format).
156 **		holdmsg -- if TRUE, don't output a copy of the message to
157 **			our output channel.
158 **
159 **	Returns:
160 **		none.
161 **
162 **	Side Effects:
163 **		Outputs msg to the transcript.
164 **		If appropriate, outputs it to the channel.
165 **		Deletes SMTP reply code number as appropriate.
166 */
167 
168 putmsg(msg, holdmsg)
169 	char *msg;
170 	bool holdmsg;
171 {
172 	/* output to transcript if serious */
173 	if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
174 		fprintf(CurEnv->e_xfp, "%s\n", msg);
175 
176 	/* output to channel if appropriate */
177 	if (!holdmsg && (Verbose || msg[0] != '0'))
178 	{
179 		(void) fflush(stdout);
180 		if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
181 			fprintf(OutChannel, "%s\r\n", msg);
182 		else
183 			fprintf(OutChannel, "%s\n", &msg[4]);
184 		(void) fflush(OutChannel);
185 	}
186 }
187 /*
188 **  PUTERRMSG -- like putmsg, but does special processing for error messages
189 **
190 **	Parameters:
191 **		msg -- the message to output.
192 **
193 **	Returns:
194 **		none.
195 **
196 **	Side Effects:
197 **		Sets the fatal error bit in the envelope as appropriate.
198 */
199 
200 puterrmsg(msg)
201 	char *msg;
202 {
203 	/* output the message as usual */
204 	putmsg(msg, HoldErrs);
205 
206 	/* signal the error */
207 	Errors++;
208 	if (msg[0] == '5')
209 		CurEnv->e_flags |= EF_FATALERRS;
210 }
211 /*
212 **  FMTMSG -- format a message into buffer.
213 **
214 **	Parameters:
215 **		eb -- error buffer to get result.
216 **		to -- the recipient tag for this message.
217 **		num -- arpanet error number.
218 **		en -- the error number to display.
219 **		fmt -- format of string.
220 **		a, b, c, d, e -- arguments.
221 **
222 **	Returns:
223 **		none.
224 **
225 **	Side Effects:
226 **		none.
227 */
228 
229 /*VARARGS5*/
230 static
231 fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
232 	register char *eb;
233 	char *to;
234 	char *num;
235 	int eno;
236 	char *fmt;
237 {
238 	char del;
239 
240 	/* output the reply code */
241 	if (isdigit(*fmt))
242 	{
243 		num = fmt;
244 		fmt += 4;
245 	}
246 	if (num[3] == '-')
247 		del = '-';
248 	else
249 		del = ' ';
250 	(void) sprintf(eb, "%3.3s%c", num, del);
251 	eb += 4;
252 
253 	/* output the file name and line number */
254 	if (FileName != NULL)
255 	{
256 		(void) sprintf(eb, "%s: line %d: ", FileName, LineNumber);
257 		eb += strlen(eb);
258 	}
259 
260 	/* output the "to" person */
261 	if (to != NULL && to[0] != '\0')
262 	{
263 		(void) sprintf(eb, "%s... ", to);
264 		while (*eb != '\0')
265 			*eb++ &= 0177;
266 	}
267 
268 	/* output the message */
269 	(void) sprintf(eb, fmt, a, b, c, d, e);
270 	while (*eb != '\0')
271 		*eb++ &= 0177;
272 
273 	/* output the error code, if any */
274 	if (eno != 0)
275 	{
276 		extern char *errstring();
277 
278 		(void) sprintf(eb, ": %s", errstring(eno));
279 		eb += strlen(eb);
280 	}
281 }
282 /*
283 **  ERRSTRING -- return string description of error code
284 **
285 **	Parameters:
286 **		errno -- the error number to translate
287 **
288 **	Returns:
289 **		A string description of errno.
290 **
291 **	Side Effects:
292 **		none.
293 */
294 
295 char *
296 errstring(errno)
297 	int errno;
298 {
299 	extern char *sys_errlist[];
300 	extern int sys_nerr;
301 	static char buf[50];
302 
303 	if (errno > 0 && errno < sys_nerr)
304 		return (sys_errlist[errno]);
305 
306 	(void) sprintf(buf, "Error %d", errno);
307 	return (buf);
308 }
309