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