xref: /freebsd/contrib/sendmail/src/sysexits.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*
2  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
3  *	All rights reserved.
4  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5  * Copyright (c) 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * By using this file, you agree to the terms and conditions set
9  * forth in the LICENSE file which can be found at the top level of
10  * the sendmail distribution.
11  *
12  */
13 
14 #ifndef lint
15 static char id[] = "@(#)$Id: sysexits.c,v 8.25 1999/09/23 19:59:24 ca Exp $";
16 #endif /* ! lint */
17 
18 #include <sendmail.h>
19 
20 /*
21 **  SYSEXITS.C -- error messages corresponding to sysexits.h
22 **
23 **	If the first character of the string is a colon, interpolate
24 **	the current errno after the rest of the string.
25 */
26 
27 char *SysExMsg[] =
28 {
29 	/* 64 USAGE */		" 500 5.0.0 Bad usage",
30 	/* 65 DATAERR */	" 501 5.6.0 Data format error",
31 	/* 66 NOINPUT */	":550 5.3.0 Cannot open input",
32 	/* 67 NOUSER */		" 550 5.1.1 User unknown",
33 	/* 68 NOHOST */		" 550 5.1.2 Host unknown",
34 	/* 69 UNAVAILABLE */	" 554 5.0.0 Service unavailable",
35 	/* 70 SOFTWARE */	":554 5.3.0 Internal error",
36 	/* 71 OSERR */		":451 4.0.0 Operating system error",
37 	/* 72 OSFILE */		":554 5.3.5 System file missing",
38 	/* 73 CANTCREAT */	":550 5.0.0 Can't create output",
39 	/* 74 IOERR */		":451 4.0.0 I/O error",
40 	/* 75 TEMPFAIL */	" 450 4.0.0 Deferred",
41 	/* 76 PROTOCOL */	" 554 5.5.0 Remote protocol error",
42 	/* 77 NOPERM */		":550 5.0.0 Insufficient permission",
43 	/* 78 CONFIG */		" 554 5.3.5 Local configuration error",
44 };
45 
46 int N_SysEx = sizeof(SysExMsg) / sizeof(SysExMsg[0]);
47 
48 static char *SysExitMsg[] =
49 {
50 	"command line usage error",
51 	"data format error",
52 	"cannot open input",
53 	"addressee unknown",
54 	"host name unknown",
55 	"service unavailable",
56 	"internal software error",
57 	"system error (e.g., can't fork)",
58 	"critical OS file missing",
59 	"can't create (user) output file",
60 	"input/output error",
61 	"temp failure; user is invited to retry",
62 	"remote error in protocol",
63 	"permission denied",
64 	"configuration error"
65 };
66 
67 /*
68 **  DSNTOEXITSTAT -- convert DSN-style error code to EX_ style.
69 **
70 **	Parameters:
71 **		dsncode -- the text of the DSN-style code.
72 **
73 **	Returns:
74 **		The corresponding exit status.
75 */
76 
77 int
78 dsntoexitstat(dsncode)
79 	char *dsncode;
80 {
81 	int code2, code3;
82 
83 	/* first the easy cases.... */
84 	if (*dsncode == '2')
85 		return EX_OK;
86 	if (*dsncode == '4')
87 		return EX_TEMPFAIL;
88 
89 	/* now decode the other two field parts */
90 	if (*++dsncode == '.')
91 		dsncode++;
92 	code2 = atoi(dsncode);
93 	while (*dsncode != '\0' && *dsncode != '.')
94 		dsncode++;
95 	if (*dsncode != '\0')
96 		dsncode++;
97 	code3 = atoi(dsncode);
98 
99 	/* and do a nested switch to work them out */
100 	switch (code2)
101 	{
102 	  case 0:	/* Other or Undefined status */
103 		return EX_UNAVAILABLE;
104 
105 	  case 1:	/* Address Status */
106 		switch (code3)
107 		{
108 		  case 0:	/* Other Address Status */
109 			return EX_DATAERR;
110 
111 		  case 1:	/* Bad destination mailbox address */
112 		  case 6:	/* Mailbox has moved, No forwarding address */
113 			return EX_NOUSER;
114 
115 		  case 2:	/* Bad destination system address */
116 		  case 8:	/* Bad senders system address */
117 			return EX_NOHOST;
118 
119 		  case 3:	/* Bad destination mailbox address syntax */
120 		  case 7:	/* Bad senders mailbox address syntax */
121 			return EX_USAGE;
122 
123 		  case 4:	/* Destination mailbox address ambiguous */
124 			return EX_UNAVAILABLE;
125 
126 		  case 5:	/* Destination address valid */
127 			return EX_OK;
128 		}
129 		break;
130 
131 	  case 2:	/* Mailbox Status */
132 		switch (code3)
133 		{
134 		  case 0:	/* Other or Undefined mailbox status */
135 		  case 1:	/* Mailbox disabled, not accepting messages */
136 		  case 2:	/* Mailbox full */
137 		  case 4:	/* Mailing list expansion problem */
138 			return EX_UNAVAILABLE;
139 
140 		  case 3:	/* Message length exceeds administrative lim */
141 			return EX_DATAERR;
142 		}
143 		break;
144 
145 	  case 3:	/* System Status */
146 		return EX_OSERR;
147 
148 	  case 4:	/* Network and Routing Status */
149 		switch (code3)
150 		{
151 		  case 0:	/* Other or undefined network or routing stat */
152 			return EX_IOERR;
153 
154 		  case 1:	/* No answer from host */
155 		  case 3:	/* Routing server failure */
156 		  case 5:	/* Network congestion */
157 			return EX_TEMPFAIL;
158 
159 		  case 2:	/* Bad connection */
160 			return EX_IOERR;
161 
162 		  case 4:	/* Unable to route */
163 			return EX_PROTOCOL;
164 
165 		  case 6:	/* Routing loop detected */
166 			return EX_CONFIG;
167 
168 		  case 7:	/* Delivery time expired */
169 			return EX_UNAVAILABLE;
170 		}
171 		break;
172 
173 	  case 5:	/* Protocol Status */
174 		return EX_PROTOCOL;
175 
176 	  case 6:	/* Message Content or Media Status */
177 		return EX_UNAVAILABLE;
178 
179 	  case 7:	/* Security Status */
180 		return EX_DATAERR;
181 	}
182 	return EX_CONFIG;
183 }
184 
185 /*
186 **  EXITSTAT -- convert EX_ value to error text.
187 **
188 **	Parameters:
189 **		excode -- rstatus which might consists of an EX_* value.
190 **
191 **	Returns:
192 **		The corresponding error text or the original string.
193 */
194 
195 char *
196 exitstat(excode)
197 	char *excode;
198 {
199 	char *c;
200 	int i;
201 
202 	if (excode == NULL || *excode == '\0')
203 		return excode;
204 	i = 0;
205 	for (c = excode; *c != '\0'; c++)
206 	{
207 		if (isascii(*c) && isdigit(*c))
208 			i = i * 10 + (*c - '0');
209 		else
210 			return excode;
211 	}
212 	i -= EX__BASE;
213 	if (i >= 0 && i <= N_SysEx)
214 		return SysExitMsg[i];
215 	return excode;
216 }
217