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