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