1 /* $NetBSD: dsn.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* dsn 6 /* SUMMARY 7 /* RFC-compliant delivery status information 8 /* SYNOPSIS 9 /* #include <dsn.h> 10 /* 11 /* typedef struct { 12 /* .in +4 13 /* const char *status; /* RFC 3463 status */ 14 /* const char *action; /* null or RFC 3464 action */ 15 /* const char *reason; /* human-readable text */ 16 /* const char *dtype; /* null or diagnostic type */ 17 /* const char *dtext; /* null or diagnostic code */ 18 /* const char *mtype; /* null or MTA type */ 19 /* const char *mname; /* null or remote MTA */ 20 /* .in -4 21 /* } DSN; 22 /* 23 /* DSN *dsn_create(status, action, reason, dtype, dtext, mtype, mname) 24 /* const char *status; 25 /* const char *action; 26 /* const char *reason; 27 /* const char *dtype; 28 /* const char *dtext; 29 /* const char *mtype; 30 /* const char *mname; 31 /* 32 /* DSN *DSN_COPY(dsn) 33 /* DSN *dsn; 34 /* 35 /* void dsn_free(dsn) 36 /* DSN *dsn; 37 /* 38 /* DSN *DSN_ASSIGN(dsn, status, action, reason, dtype, dtext, 39 /* mtype, mname) 40 /* DSN *dsn; 41 /* const char *status; 42 /* const char *action; 43 /* const char *reason; 44 /* const char *dtype; 45 /* const char *dtext; 46 /* const char *mtype; 47 /* const char *mname; 48 /* 49 /* DSN *DSN_SIMPLE(dsn, status, action, reason) 50 /* DSN *dsn; 51 /* const char *status; 52 /* const char *action; 53 /* const char *reason; 54 /* DESCRIPTION 55 /* This module maintains delivery error information. For a 56 /* description of structure field members see "Arguments" 57 /* below. Function-like names spelled in upper case are macros. 58 /* These may evaluate some arguments more than once. 59 /* 60 /* dsn_create() creates a DSN structure and copies its arguments. 61 /* The DSN structure should be destroyed with dsn_free(). 62 /* 63 /* DSN_COPY() creates a deep copy of its argument. 64 /* 65 /* dsn_free() destroys a DSN structure and makes its storage 66 /* available for reuse. 67 /* 68 /* DSN_ASSIGN() updates a DSN structure and DOES NOT copy 69 /* arguments or free memory. The result DSN structure must 70 /* NOT be passed to dsn_free(). DSN_ASSIGN() is typically used 71 /* for stack-based short-lived storage. 72 /* 73 /* DSN_SIMPLE() takes the minimally required subset of all the 74 /* attributes and sets the rest to empty strings. 75 /* This is a wrapper around the DSN_ASSIGN() macro. 76 /* 77 /* Arguments: 78 /* .IP reason 79 /* Human-readable text, used for logging purposes, and for 80 /* updating the message-specific \fBbounce\fR or \fIdefer\fR 81 /* logfile. 82 /* .IP status 83 /* Enhanced status code as specified in RFC 3463. 84 /* .IP action 85 /* DSN_NO_ACTION, empty string, or action as defined in RFC 3464. 86 /* If no action is specified, a default action is chosen. 87 /* .IP dtype 88 /* DSN_NO_DTYPE, empty string, or diagnostic code type as 89 /* specified in RFC 3464. 90 /* .IP dtext 91 /* DSN_NO_DTEXT, empty string, or diagnostic code as specified 92 /* in RFC 3464. 93 /* .IP mtype 94 /* DSN_NO_MTYPE, empty string, DSN_MTYPE_DNS or DSN_MTYPE_UNIX. 95 /* .IP mname 96 /* DSN_NO_MNAME, empty string, or remote MTA as specified in 97 /* RFC 3464. 98 /* DIAGNOSTICS 99 /* Panic: null or empty status or reason. 100 /* Fatal: out of memory. 101 /* LICENSE 102 /* .ad 103 /* .fi 104 /* The Secure Mailer license must be distributed with this software. 105 /* AUTHOR(S) 106 /* Wietse Venema 107 /* IBM T.J. Watson Research 108 /* P.O. Box 704 109 /* Yorktown Heights, NY 10598, USA 110 /*--*/ 111 112 /* System library. */ 113 114 #include <sys_defs.h> 115 116 /* Utility library. */ 117 118 #include <msg.h> 119 #include <mymalloc.h> 120 121 /* Global library. */ 122 123 #include <dsn.h> 124 125 /* dsn_create - create DSN structure */ 126 127 DSN *dsn_create(const char *status, const char *action, const char *reason, 128 const char *dtype, const char *dtext, 129 const char *mtype, const char *mname) 130 { 131 const char *myname = "dsn_create"; 132 DSN *dsn; 133 134 dsn = (DSN *) mymalloc(sizeof(*dsn)); 135 136 /* 137 * Status and reason must not be empty. Other members may be empty 138 * strings. 139 * 140 * Early implementations represented unavailable information with null 141 * pointers. This resulted in code that was difficult to maintain. We now 142 * use empty strings instead. For safety sake we keep the null pointer 143 * test for input, but we always convert to empty string on output. 144 */ 145 #define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0) 146 147 if (NULL_OR_EMPTY(status)) 148 msg_panic("%s: null dsn status", myname); 149 else 150 dsn->status = mystrdup(status); 151 152 if (NULL_OR_EMPTY(action)) 153 dsn->action = mystrdup(""); 154 else 155 dsn->action = mystrdup(action); 156 157 if (NULL_OR_EMPTY(reason)) 158 msg_panic("%s: null dsn reason", myname); 159 else 160 dsn->reason = mystrdup(reason); 161 162 if (NULL_OR_EMPTY(dtype) || NULL_OR_EMPTY(dtext)) { 163 dsn->dtype = mystrdup(""); 164 dsn->dtext = mystrdup(""); 165 } else { 166 dsn->dtype = mystrdup(dtype); 167 dsn->dtext = mystrdup(dtext); 168 } 169 if (NULL_OR_EMPTY(mtype) || NULL_OR_EMPTY(mname)) { 170 dsn->mtype = mystrdup(""); 171 dsn->mname = mystrdup(""); 172 } else { 173 dsn->mtype = mystrdup(mtype); 174 dsn->mname = mystrdup(mname); 175 } 176 return (dsn); 177 } 178 179 /* dsn_free - destroy DSN structure */ 180 181 void dsn_free(DSN *dsn) 182 { 183 myfree((void *) dsn->status); 184 myfree((void *) dsn->action); 185 myfree((void *) dsn->reason); 186 myfree((void *) dsn->dtype); 187 myfree((void *) dsn->dtext); 188 myfree((void *) dsn->mtype); 189 myfree((void *) dsn->mname); 190 myfree((void *) dsn); 191 } 192