Home | History | Annotate | Line # | Download | only in global
      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