/*++ /* NAME /* dsn /* SUMMARY /* RFC-compliant delivery status information /* SYNOPSIS /* #include /* /* typedef struct { /* .in +4 /* const char *status; /* RFC 3463 status */ /* const char *action; /* null or RFC 3464 action */ /* const char *reason; /* human-readable text */ /* const char *dtype; /* null or diagnostic type */ /* const char *dtext; /* null or diagnostic code */ /* const char *mtype; /* null or MTA type */ /* const char *mname; /* null or remote MTA */ /* .in -4 /* } DSN; /* /* DSN *dsn_create(status, action, reason, dtype, dtext, mtype, mname) /* const char *status; /* const char *action; /* const char *reason; /* const char *dtype; /* const char *dtext; /* const char *mtype; /* const char *mname; /* /* DSN *DSN_COPY(dsn) /* DSN *dsn; /* /* void dsn_free(dsn) /* DSN *dsn; /* /* DSN *DSN_ASSIGN(dsn, status, action, reason, dtype, dtext, /* mtype, mname) /* DSN *dsn; /* const char *status; /* const char *action; /* const char *reason; /* const char *dtype; /* const char *dtext; /* const char *mtype; /* const char *mname; /* /* DSN *DSN_SIMPLE(dsn, status, action, reason) /* DSN *dsn; /* const char *status; /* const char *action; /* const char *reason; /* DESCRIPTION /* This module maintains delivery error information. For a /* description of structure field members see "Arguments" /* below. Function-like names spelled in upper case are macros. /* These may evaluate some arguments more than once. /* /* dsn_create() creates a DSN structure and copies its arguments. /* The DSN structure should be destroyed with dsn_free(). /* /* DSN_COPY() creates a deep copy of its argument. /* /* dsn_free() destroys a DSN structure and makes its storage /* available for reuse. /* /* DSN_ASSIGN() updates a DSN structure and DOES NOT copy /* arguments or free memory. The result DSN structure must /* NOT be passed to dsn_free(). DSN_ASSIGN() is typically used /* for stack-based short-lived storage. /* /* DSN_SIMPLE() takes the minimally required subset of all the /* attributes and sets the rest to empty strings. /* This is a wrapper around the DSN_ASSIGN() macro. /* /* Arguments: /* .IP reason /* Human-readable text, used for logging purposes, and for /* updating the message-specific \fBbounce\fR or \fIdefer\fR /* logfile. /* .IP status /* Enhanced status code as specified in RFC 3463. /* .IP action /* DSN_NO_ACTION, empty string, or action as defined in RFC 3464. /* If no action is specified, a default action is chosen. /* .IP dtype /* DSN_NO_DTYPE, empty string, or diagnostic code type as /* specified in RFC 3464. /* .IP dtext /* DSN_NO_DTEXT, empty string, or diagnostic code as specified /* in RFC 3464. /* .IP mtype /* DSN_NO_MTYPE, empty string, DSN_MTYPE_DNS or DSN_MTYPE_UNIX. /* .IP mname /* DSN_NO_MNAME, empty string, or remote MTA as specified in /* RFC 3464. /* DIAGNOSTICS /* Panic: null or empty status or reason. /* Fatal: out of memory. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include /* Utility library. */ #include #include /* Global library. */ #include /* dsn_create - create DSN structure */ DSN *dsn_create(const char *status, const char *action, const char *reason, const char *dtype, const char *dtext, const char *mtype, const char *mname) { const char *myname = "dsn_create"; DSN *dsn; dsn = (DSN *) mymalloc(sizeof(*dsn)); /* * Status and reason must not be empty. Other members may be empty * strings. * * Early implementations represented unavailable information with null * pointers. This resulted in code that was difficult to maintain. We now * use empty strings instead. For safety sake we keep the null pointer * test for input, but we always convert to empty string on output. */ #define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0) if (NULL_OR_EMPTY(status)) msg_panic("%s: null dsn status", myname); else dsn->status = mystrdup(status); if (NULL_OR_EMPTY(action)) dsn->action = mystrdup(""); else dsn->action = mystrdup(action); if (NULL_OR_EMPTY(reason)) msg_panic("%s: null dsn reason", myname); else dsn->reason = mystrdup(reason); if (NULL_OR_EMPTY(dtype) || NULL_OR_EMPTY(dtext)) { dsn->dtype = mystrdup(""); dsn->dtext = mystrdup(""); } else { dsn->dtype = mystrdup(dtype); dsn->dtext = mystrdup(dtext); } if (NULL_OR_EMPTY(mtype) || NULL_OR_EMPTY(mname)) { dsn->mtype = mystrdup(""); dsn->mname = mystrdup(""); } else { dsn->mtype = mystrdup(mtype); dsn->mname = mystrdup(mname); } return (dsn); } /* dsn_free - destroy DSN structure */ void dsn_free(DSN *dsn) { myfree((void *) dsn->status); myfree((void *) dsn->action); myfree((void *) dsn->reason); myfree((void *) dsn->dtype); myfree((void *) dsn->dtext); myfree((void *) dsn->mtype); myfree((void *) dsn->mname); myfree((void *) dsn); }