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