1 /* $NetBSD: sys_exits.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* sys_exits 3 6 /* SUMMARY 7 /* sendmail-compatible exit status handling 8 /* SYNOPSIS 9 /* #include <sys_exits.h> 10 /* 11 /* typedef struct { 12 /* .in +4 13 /* int status; /* exit status */ 14 /* const char *dsn; /* RFC 3463 */ 15 /* const char *text; /* free text */ 16 /* .in -4 17 /* } SYS_EXITS_DETAIL; 18 /* 19 /* int SYS_EXITS_CODE(code) 20 /* int code; 21 /* 22 /* const char *sys_exits_strerror(code) 23 /* int code; 24 /* 25 /* const SYS_EXITS_DETAIL *sys_exits_detail(code) 26 /* int code; 27 /* 28 /* int sys_exits_softerror(code) 29 /* int code; 30 /* DESCRIPTION 31 /* This module interprets sendmail-compatible process exit status 32 /* codes. 33 /* 34 /* SYS_EXITS_CODE() returns non-zero when the specified code 35 /* is a sendmail-compatible process exit status code. 36 /* 37 /* sys_exits_strerror() returns a descriptive text for the 38 /* specified sendmail-compatible status code, or a generic 39 /* text for an unknown status code. 40 /* 41 /* sys_exits_detail() returns a table entry with assorted 42 /* information about the specified sendmail-compatible status 43 /* code, or a generic entry for an unknown status code. 44 /* The generic entry may be overwritten with each sys_exits_detail() 45 /* call. 46 /* 47 /* sys_exits_softerror() returns non-zero when the specified 48 /* sendmail-compatible status code corresponds to a recoverable error. 49 /* An unknown status code is always unrecoverable. 50 /* DIAGNOSTICS 51 /* Fatal: out of memory. 52 /* LICENSE 53 /* .ad 54 /* .fi 55 /* The Secure Mailer license must be distributed with this software. 56 /* AUTHOR(S) 57 /* Wietse Venema 58 /* IBM T.J. Watson Research 59 /* P.O. Box 704 60 /* Yorktown Heights, NY 10598, USA 61 /*--*/ 62 63 /* System library. */ 64 65 #include <sys_defs.h> 66 67 /* Utility library. */ 68 69 #include <msg.h> 70 #include <vstring.h> 71 72 /* Global library. */ 73 74 #include <sys_exits.h> 75 76 /* Application-specific. */ 77 78 static const SYS_EXITS_DETAIL sys_exits_table[] = { 79 EX_USAGE, "5.3.0", "command line usage error", 80 EX_DATAERR, "5.6.0", "data format error", 81 EX_NOINPUT, "5.3.0", "cannot open input", 82 EX_NOUSER, "5.1.1", "user unknown", 83 EX_NOHOST, "5.1.2", "host name unknown", 84 EX_UNAVAILABLE, "5.3.0", "service unavailable", 85 EX_SOFTWARE, "5.3.0", "internal software error", 86 EX_OSERR, "4.3.0", "system resource problem", 87 EX_OSFILE, "5.3.0", "critical OS file missing", 88 EX_CANTCREAT, "5.2.0", "can't create user output file", 89 EX_IOERR, "5.3.0", "input/output error", 90 EX_TEMPFAIL, "4.3.0", "temporary failure", 91 EX_PROTOCOL, "5.5.0", "remote error in protocol", 92 EX_NOPERM, "5.7.0", "permission denied", 93 EX_CONFIG, "5.3.5", "local configuration error", 94 }; 95 96 static VSTRING *sys_exits_def_text = 0; 97 98 static SYS_EXITS_DETAIL sys_exits_default[] = { 99 0, "5.3.0", 0, 100 }; 101 102 /* sys_exits_fake - fake an entry for an unknown code */ 103 104 static SYS_EXITS_DETAIL *sys_exits_fake(int code) 105 { 106 if (sys_exits_def_text == 0) 107 sys_exits_def_text = vstring_alloc(30); 108 109 vstring_sprintf(sys_exits_def_text, "unknown mail system error %d", code); 110 sys_exits_default->text = vstring_str(sys_exits_def_text); 111 return (sys_exits_default); 112 } 113 114 /* sys_exits_strerror - map exit status to error string */ 115 116 const char *sys_exits_strerror(int code) 117 { 118 if (!SYS_EXITS_CODE(code)) { 119 return (sys_exits_fake(code)->text); 120 } else { 121 return (sys_exits_table[code - EX__BASE].text); 122 } 123 } 124 125 /* sys_exits_detail - map exit status info table entry */ 126 127 const SYS_EXITS_DETAIL *sys_exits_detail(int code) 128 { 129 if (!SYS_EXITS_CODE(code)) { 130 return (sys_exits_fake(code)); 131 } else { 132 return (sys_exits_table + code - EX__BASE); 133 } 134 } 135 136 /* sys_exits_softerror - determine if error is transient */ 137 138 int sys_exits_softerror(int code) 139 { 140 if (!SYS_EXITS_CODE(code)) { 141 return (sys_exits_default->dsn[0] == '4'); 142 } else { 143 return (sys_exits_table[code - EX__BASE].dsn[0] == '4'); 144 } 145 } 146