summaryrefslogtreecommitdiffstats
path: root/src/global/dsn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/global/dsn.c')
-rw-r--r--src/global/dsn.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/global/dsn.c b/src/global/dsn.c
new file mode 100644
index 0000000..32da936
--- /dev/null
+++ b/src/global/dsn.c
@@ -0,0 +1,189 @@
+/*++
+/* NAME
+/* dsn
+/* SUMMARY
+/* RFC-compliant delivery status information
+/* SYNOPSIS
+/* #include <dsn.h>
+/*
+/* 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 <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+
+/* Global library. */
+
+#include <dsn.h>
+
+/* 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);
+}