1 # include "sendmail.h" 2 3 SCCSID(@(#)err.c 3.36 11/28/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 /* 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: %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 putmsg(MsgBuf, HoldErrs); 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 */ 171 if (Xscript != NULL) 172 fprintf(Xscript, "%s\n", OpMode == MD_SMTP ? msg : &msg[4]); 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 /* determine error status */ 186 switch (msg[0]) 187 { 188 case '5': 189 CurEnv->e_flags |= EF_FATALERRS; 190 /* fall through.... */ 191 192 case '4': 193 Errors++; 194 break; 195 } 196 } 197 /* 198 ** FMTMSG -- format a message into buffer. 199 ** 200 ** Parameters: 201 ** eb -- error buffer to get result. 202 ** to -- the recipient tag for this message. 203 ** num -- arpanet error number. 204 ** fmt -- format of string. 205 ** a, b, c, d, e -- arguments. 206 ** 207 ** Returns: 208 ** none. 209 ** 210 ** Side Effects: 211 ** none. 212 */ 213 214 /*VARARGS4*/ 215 static 216 fmtmsg(eb, to, num, fmt, a, b, c, d, e) 217 register char *eb; 218 char *to; 219 char *num; 220 char *fmt; 221 { 222 char del; 223 224 /* output the reply code */ 225 if (isdigit(*fmt)) 226 { 227 num = fmt; 228 fmt += 4; 229 } 230 if (num[3] == '-') 231 del = '-'; 232 else 233 del = ' '; 234 (void) sprintf(eb, "%3.3s%c", num, del); 235 eb += 4; 236 237 /* output the file name and line number */ 238 if (FileName != NULL) 239 { 240 (void) sprintf(eb, "%s: line %d: ", FileName, LineNumber); 241 eb += strlen(eb); 242 } 243 244 /* output the "to" person */ 245 if (to != NULL && to[0] != '\0') 246 { 247 (void) sprintf(eb, "%s... ", to); 248 while (*eb != '\0') 249 *eb++ &= 0177; 250 } 251 252 /* output the message */ 253 (void) sprintf(eb, fmt, a, b, c, d, e); 254 while (*eb != '\0') 255 *eb++ &= 0177; 256 257 /* output the error code, if any */ 258 if (errno != 0) 259 { 260 extern int sys_nerr; 261 extern char *sys_errlist[]; 262 if (errno < sys_nerr && errno > 0) 263 (void) sprintf(eb, ": %s", sys_errlist[errno]); 264 else 265 (void) sprintf(eb, ": error %d", errno); 266 eb += strlen(eb); 267 } 268 } 269