h/addrsbr.h \
h/aliasbr.h \
h/crawl_folders.h \
+ h/done.h \
h/dropsbr.h \
h/fmt_compile.h \
h/fmt_scan.h \
--- /dev/null
+/* done.h -- allow calls to exit(3) to be redirected
+ *
+ * This code is Copyright (c) 2017, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+void set_done(void (*new)(int) NORETURN);
+void done(int status) NORETURN;
extern char *whatnowproc;
extern char *whomproc;
-extern void (*done) (int) NORETURN;
-
#include <h/prototypes.h>
#include <h/mh.h>
-void (*done) (int) NORETURN = exit;
+/* It's undefined behaviour in C99 to convert from a function pointer to
+ * a data-object pointer, e.g. void pointer. gcc's -pedantic warns of
+ * this and can stop compilation. POSIX requires the operation however,
+ * e.g. for dlsym(3), and so we know it's safe on POSIX platforms, e.g.
+ * the pointers are of the same size. Thus use a union to subvert gcc's
+ * check. The function-pointer equivalent of a void pointer is any
+ * function-pointer type as all function pointers are defined to be
+ * convertible from one another; use the simplest available. */
+typedef union {
+ void *v;
+ void (*f)(void);
+} generic_pointer;
+
+static void (*altexit)(int) NORETURN = exit;
+
+/* set_done changes the path of done() from exit(3), or back to exit(3).
+ * Anything else will work, but a standard-error warning will report the
+ * old non-exit() value has been trampled. */
+void
+set_done(void (*new)(int) NORETURN)
+{
+ generic_pointer gpo, gpn;
+
+ if (altexit != exit && new != exit) {
+ gpo.f = (void (*)(void))altexit;
+ gpn.f = (void (*)(void))new;
+ inform("altexit trampled: %p %p", gpo.v, gpn.v);
+ }
+ altexit = new;
+}
+
+void NORETURN
+done(int status)
+{
+ (*altexit)(status);
+}
#include <sys/types.h>
#include <sys/uio.h>
-
+#include "h/done.h"
/* inform calls advertise() with no what and no tail.
* Thus the simple "[invo_name: ]fmt\n" results. */
#include <h/mh.h>
#include <h/utils.h>
#include "m_maildir.h"
+#include "h/done.h"
char *
#include <h/mh.h>
#include <h/signals.h>
+#include "h/done.h"
#include "m_mktemp.h"
#include <h/addrsbr.h>
#include <h/aliasbr.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#define ALI_SWITCHES \
#include <h/mh.h>
#include <h/utils.h>
+#include "h/done.h"
#include "sbr/m_maildir.h"
#define ANNO_SWITCHES \
#include <h/addrsbr.h>
#include <h/fmt_scan.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/terminal.h"
#include <h/mh.h>
#include <h/utils.h>
#include <h/mhparse.h>
+#include "h/done.h"
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
#include "mhfree.h"
#include <h/mh.h>
#include <h/utils.h>
#include <h/fmt_scan.h>
+#include "h/done.h"
#include "sbr/m_maildir.h"
#include <fcntl.h>
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <fcntl.h>
+#include "h/done.h"
#define DIST_SWITCHES \
X("annotate", 0, ANNOSW) \
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include <h/fmt_scan.h>
#include <h/tws.h>
#include <h/mh.h>
#include <h/utils.h>
+#include "h/done.h"
#include "sbr/m_maildir.h"
/*
#include <h/fmt_scan.h>
#include <h/fmt_compile.h>
#include <h/scansbr.h>
+#include "h/done.h"
#include <h/utils.h>
#define FMTDUMP_SWITCHES \
#include <h/utils.h>
#include <h/scansbr.h>
#include <h/addrsbr.h>
+#include "h/done.h"
#include "sbr/m_maildir.h"
#include "sbr/terminal.h"
#include <h/mh.h>
#include <h/crawl_folders.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <h/mh.h>
#include <fcntl.h>
#include <h/tws.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <h/signals.h>
#include <h/tws.h>
#include <h/mts.h>
+#include "h/done.h"
#include "sbr/lock_file.h"
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
int nmsgs, nbytes;
char *MAILHOST_env_variable;
- done=inc_done;
+ set_done(inc_done);
/* absolutely the first thing we do is save our privileges,
* and drop them if we can.
static void NORETURN
inc_done (int status)
{
- done = exit;
+ set_done(exit);
if (locked)
{
GETGROUPPRIVS();
*/
#include <h/mh.h> /* mh internals */
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include "sbr/makedir.h"
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/mhcachesbr.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
if (nmh_init(argv[0], 2)) { return 1; }
- done=unlink_done;
+ set_done(unlink_done);
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
#include <h/fmt_scan.h>
#include <h/mime.h>
#include <h/mhparse.h>
+#include "h/done.h"
#include <h/utils.h>
#include "h/mhcachesbr.h"
#include "mhmisc.h"
CT *ctp;
convert_list *next;
- done = freects_done;
+ set_done(freects_done);
/* In case there are multiple calls that land here, prevent leak. */
for (ctp = cts; ctp && *ctp; ++ctp) { free_content (*ctp); }
#include <h/fmt_scan.h>
#include <h/mime.h>
#include <h/mhparse.h>
+#include "h/done.h"
#include <h/utils.h>
#include <h/signals.h>
#include "sbr/m_maildir.h"
#include <h/fmt_scan.h>
#include "h/addrsbr.h"
#include "h/mts.h"
+#include "h/done.h"
#include "h/utils.h"
#include <time.h>
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/mhcachesbr.h>
+#include "h/done.h"
#include <h/utils.h>
#include "mhmisc.h"
#include "sbr/m_maildir.h"
if (nmh_init(argv[0], 1)) { return 1; }
- done=freects_done;
+ set_done(freects_done);
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
#include <string.h>
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include <h/oauth.h>
#include "sbr/lock_file.h"
#include <h/addrsbr.h>
#include <h/fmt_scan.h>
#include <h/tws.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_popen.h"
#include <setjmp.h>
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/mhcachesbr.h>
+#include "h/done.h"
#include <h/utils.h>
#include "mhmisc.h"
#include "sbr/m_maildir.h"
if (nmh_init(argv[0], 1)) { return 1; }
- done=freects_done;
+ set_done(freects_done);
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
#include <h/mh.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#define MHPARAM_SWITCHES \
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/mhcachesbr.h>
+#include "h/done.h"
#include <h/utils.h>
#include "mhmisc.h"
#include "sbr/m_maildir.h"
if (nmh_init(argv[0], 1)) { return 1; }
- done=freects_done;
+ set_done(freects_done);
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/fmt_scan.h>
+#include "h/done.h"
#include <h/utils.h>
#include "mhmisc.h"
#include "mhshowsbr.h"
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/mhcachesbr.h>
+#include "h/done.h"
#include <h/utils.h>
#include "mhmisc.h"
#include "sbr/m_maildir.h"
if (nmh_init(argv[0], 1)) { return 1; }
- done=freects_done;
+ set_done(freects_done);
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
#if NMH
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#if HAVE_MKSTEMPS
#include <h/mh.h>
#include <h/mts.h>
#include <h/tws.h>
+#include "h/done.h"
#include <h/utils.h>
#include <pwd.h>
#include <h/mh.h>
#include <h/crawl_folders.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/lock_file.h"
#include "sbr/m_maildir.h"
#include <h/mh.h>
#include <fcntl.h>
#include <h/dropsbr.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
if (nmh_init(argv[0], 1)) { return 1; }
- done=mbxclose_done;
+ set_done(mbxclose_done);
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
#include <h/mh.h>
#include <h/tws.h>
#include <h/picksbr.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
if (nmh_init(argv[0], 1)) { return 1; }
- done=putzero_done;
+ set_done(putzero_done);
arguments = getarguments (invo_name, argc, argv, 1);
argp = arguments;
#include <h/aliasbr.h>
#include <h/dropsbr.h>
#include <h/mime.h>
+#include "h/done.h"
#include <h/utils.h>
#include <h/tws.h>
#include <h/mts.h>
#include <h/mh.h>
#include <fcntl.h>
#include <h/signals.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_mktemp.h"
#include <setjmp.h>
#include <h/rcvmail.h>
#include <h/tws.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_mktemp.h"
if (nmh_init(argv[0], 2)) { return 1; }
- done=unlink_done;
+ set_done(unlink_done);
/*
* Configure this now, since any unknown switches to rcvdist get
#include <h/rcvmail.h>
#include <h/tws.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#define RCVPACK_SWITCHES \
#include <fcntl.h>
#include <h/signals.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
if (nmh_init(argv[0], 2)) { return 1; }
- done=unlink_done;
+ set_done(unlink_done);
mts_init ();
arguments = getarguments (invo_name, argc, argv, 1);
#include <h/scansbr.h>
#include <h/tws.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_mktemp.h"
#include <fcntl.h>
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
#include <h/mh.h>
#include <h/mime.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <h/mh.h>
#include <h/addrsbr.h>
#include <h/fmt_scan.h>
+#include "h/done.h"
#include <h/utils.h>
#include <sys/file.h> /* L_SET */
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <h/scansbr.h>
#include <h/tws.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include "sbr/terminal.h"
#include <h/mh.h>
#include <fcntl.h>
+#include "h/done.h"
#include <h/utils.h>
#ifdef OAUTH_SUPPORT
# include <h/oauth.h>
#ifdef OAUTH_SUPPORT
#include <h/oauth.h>
#endif
+#include "h/done.h"
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
#include "sbr/message_id.h"
break;
}
- done=armed_done;
+ set_done(armed_done);
switch (setjmp (env)) {
case OK:
/*
break;
}
- done=exit;
+ set_done(exit);
if (distfile)
(void) m_unlink (distfile);
#include <h/mh.h>
#include <h/mime.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <setjmp.h>
#include <h/tws.h>
#include <h/mts.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/lock_file.h"
#include "sbr/m_mktemp.h"
#include <h/mh.h>
#include <h/tws.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_maildir.h"
#include <h/tws.h>
#include <h/mime.h>
#include <h/mhparse.h>
+#include "h/done.h"
#include <h/utils.h>
#include "sbr/m_mktemp.h"
#include "sbr/base64.h"
*/
#include <h/mh.h>
+#include "h/done.h"
/*
#ifdef OAUTH_SUPPORT
# include <h/oauth.h>
#endif
+#include "h/done.h"
#include "sbr/m_maildir.h"
#include "sbr/m_mktemp.h"
#include "sbr/mime_type.h"
*/
#include <h/mh.h>
+#include "h/done.h"
#include <h/utils.h>
#include <h/signals.h>
#include "sbr/m_maildir.h"