From: Ralph Corderoy Date: Thu, 21 Sep 2017 15:59:15 +0000 (+0100) Subject: Detect function-pointer `done' being set twice in a row. X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/2b83f27e1980a6c5de752bd55c0ff76f53ec15f6?hp=1da3cc1c0b20a17997b4a1dd255016d6c801abf5 Detect function-pointer `done' being set twice in a row. Make `done' a function that uses a file-static function pointer, and add set_done() to alter it. That wants either the old or new value to be exit(3). If it's not, it still alters the stored pointer, to maintain the existing behaviour, but emits a warning on stderr. mhbuild(1) triggers that warning, making this hunch worthwhile. --- diff --git a/Makefile.am b/Makefile.am index 68a7d902..b75896a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -335,6 +335,7 @@ noinst_HEADERS = \ h/addrsbr.h \ h/aliasbr.h \ h/crawl_folders.h \ + h/done.h \ h/dropsbr.h \ h/fmt_compile.h \ h/fmt_scan.h \ diff --git a/h/done.h b/h/done.h new file mode 100644 index 00000000..b0c3cc3c --- /dev/null +++ b/h/done.h @@ -0,0 +1,9 @@ +/* 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; diff --git a/h/mh.h b/h/mh.h index 069d9cbe..a97a2e43 100644 --- a/h/mh.h +++ b/h/mh.h @@ -512,6 +512,4 @@ extern char *version_str; extern char *whatnowproc; extern char *whomproc; -extern void (*done) (int) NORETURN; - #include diff --git a/sbr/done.c b/sbr/done.c index c703aba5..cd76fac5 100644 --- a/sbr/done.c +++ b/sbr/done.c @@ -7,4 +7,39 @@ #include -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); +} diff --git a/sbr/error.c b/sbr/error.c index 5a5808c2..82850510 100644 --- a/sbr/error.c +++ b/sbr/error.c @@ -9,7 +9,7 @@ #include #include - +#include "h/done.h" /* inform calls advertise() with no what and no tail. * Thus the simple "[invo_name: ]fmt\n" results. */ diff --git a/sbr/m_draft.c b/sbr/m_draft.c index 683af25c..a09bf060 100644 --- a/sbr/m_draft.c +++ b/sbr/m_draft.c @@ -8,6 +8,7 @@ #include #include #include "m_maildir.h" +#include "h/done.h" char * diff --git a/sbr/push.c b/sbr/push.c index 6708db47..4576c8e9 100644 --- a/sbr/push.c +++ b/sbr/push.c @@ -7,6 +7,7 @@ #include #include +#include "h/done.h" #include "m_mktemp.h" diff --git a/uip/ali.c b/uip/ali.c index 43e9f5a7..a1b642cb 100644 --- a/uip/ali.c +++ b/uip/ali.c @@ -9,6 +9,7 @@ #include #include #include +#include "h/done.h" #include #define ALI_SWITCHES \ diff --git a/uip/anno.c b/uip/anno.c index 521f7b96..77ecc10b 100644 --- a/uip/anno.c +++ b/uip/anno.c @@ -43,6 +43,7 @@ #include #include +#include "h/done.h" #include "sbr/m_maildir.h" #define ANNO_SWITCHES \ diff --git a/uip/ap.c b/uip/ap.c index 8265723e..0e3e8b55 100644 --- a/uip/ap.c +++ b/uip/ap.c @@ -9,6 +9,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/terminal.h" diff --git a/uip/burst.c b/uip/burst.c index 5623e2c1..5e5d86b9 100644 --- a/uip/burst.c +++ b/uip/burst.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" #include "mhfree.h" diff --git a/uip/comp.c b/uip/comp.c index 744ea19b..2805d56b 100644 --- a/uip/comp.c +++ b/uip/comp.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include "sbr/m_maildir.h" #include diff --git a/uip/dist.c b/uip/dist.c index b0728bdd..7eea4fcc 100644 --- a/uip/dist.c +++ b/uip/dist.c @@ -9,6 +9,7 @@ #include #include "sbr/m_maildir.h" #include +#include "h/done.h" #define DIST_SWITCHES \ X("annotate", 0, ANNOSW) \ diff --git a/uip/dp.c b/uip/dp.c index 9ed5199c..dc799910 100644 --- a/uip/dp.c +++ b/uip/dp.c @@ -6,6 +6,7 @@ */ #include +#include "h/done.h" #include #include #include diff --git a/uip/flist.c b/uip/flist.c index f40f010d..057192c3 100644 --- a/uip/flist.c +++ b/uip/flist.c @@ -15,6 +15,7 @@ #include #include +#include "h/done.h" #include "sbr/m_maildir.h" /* diff --git a/uip/fmtdump.c b/uip/fmtdump.c index 90e87e15..be6b7631 100644 --- a/uip/fmtdump.c +++ b/uip/fmtdump.c @@ -9,6 +9,7 @@ #include #include #include +#include "h/done.h" #include #define FMTDUMP_SWITCHES \ diff --git a/uip/fmttest.c b/uip/fmttest.c index 6b49fc66..9a569ae4 100644 --- a/uip/fmttest.c +++ b/uip/fmttest.c @@ -11,6 +11,7 @@ #include #include #include +#include "h/done.h" #include "sbr/m_maildir.h" #include "sbr/terminal.h" diff --git a/uip/folder.c b/uip/folder.c index 625d68ad..001c3429 100644 --- a/uip/folder.c +++ b/uip/folder.c @@ -9,6 +9,7 @@ #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/forw.c b/uip/forw.c index 51caa0bc..288e85a0 100644 --- a/uip/forw.c +++ b/uip/forw.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/inc.c b/uip/inc.c index 2bd1b71f..e824ea37 100644 --- a/uip/inc.c +++ b/uip/inc.c @@ -40,6 +40,7 @@ #include #include #include +#include "h/done.h" #include "sbr/lock_file.h" #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" @@ -196,7 +197,7 @@ main (int argc, char **argv) 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. @@ -907,7 +908,7 @@ skip: static void NORETURN inc_done (int status) { - done = exit; + set_done(exit); if (locked) { GETGROUPPRIVS(); diff --git a/uip/install-mh.c b/uip/install-mh.c index 549e4525..2470c3ef 100644 --- a/uip/install-mh.c +++ b/uip/install-mh.c @@ -6,6 +6,7 @@ */ #include /* mh internals */ +#include "h/done.h" #include #include "sbr/m_maildir.h" #include "sbr/makedir.h" diff --git a/uip/mark.c b/uip/mark.c index 0b17b862..1c92cafd 100644 --- a/uip/mark.c +++ b/uip/mark.c @@ -8,6 +8,7 @@ */ #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/mhbuild.c b/uip/mhbuild.c index 3b17f356..bb455198 100644 --- a/uip/mhbuild.c +++ b/uip/mhbuild.c @@ -13,6 +13,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" @@ -108,7 +109,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 2)) { return 1; } - done=unlink_done; + set_done(unlink_done); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c index ffec2d6d..ba96ac44 100644 --- a/uip/mhbuildsbr.c +++ b/uip/mhbuildsbr.c @@ -21,6 +21,7 @@ #include #include #include +#include "h/done.h" #include #include "h/mhcachesbr.h" #include "mhmisc.h" @@ -445,7 +446,7 @@ finish_field: 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); } diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index 2bbb0453..486c7cc4 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -9,6 +9,7 @@ #include #include #include +#include "h/done.h" #include #include #include "sbr/m_maildir.h" diff --git a/uip/mhical.c b/uip/mhical.c index d62fce95..b29be153 100644 --- a/uip/mhical.c +++ b/uip/mhical.c @@ -11,6 +11,7 @@ #include #include "h/addrsbr.h" #include "h/mts.h" +#include "h/done.h" #include "h/utils.h" #include diff --git a/uip/mhl.c b/uip/mhl.c index ea7a244c..e3608208 100644 --- a/uip/mhl.c +++ b/uip/mhl.c @@ -6,6 +6,7 @@ */ #include +#include "h/done.h" #include diff --git a/uip/mhlist.c b/uip/mhlist.c index 93e2ea0e..aa304e68 100644 --- a/uip/mhlist.c +++ b/uip/mhlist.c @@ -14,6 +14,7 @@ #include #include #include +#include "h/done.h" #include #include "mhmisc.h" #include "sbr/m_maildir.h" @@ -79,7 +80,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 1)) { return 1; } - done=freects_done; + set_done(freects_done); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; diff --git a/uip/mhlogin.c b/uip/mhlogin.c index aee2c1eb..e02ef465 100644 --- a/uip/mhlogin.c +++ b/uip/mhlogin.c @@ -10,6 +10,7 @@ #include #include +#include "h/done.h" #include #include #include "sbr/lock_file.h" diff --git a/uip/mhlsbr.c b/uip/mhlsbr.c index d21c71c2..5c050e3e 100644 --- a/uip/mhlsbr.c +++ b/uip/mhlsbr.c @@ -10,6 +10,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_popen.h" #include diff --git a/uip/mhn.c b/uip/mhn.c index 71034885..94f25ace 100644 --- a/uip/mhn.c +++ b/uip/mhn.c @@ -15,6 +15,7 @@ #include #include #include +#include "h/done.h" #include #include "mhmisc.h" #include "sbr/m_maildir.h" @@ -118,7 +119,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 1)) { return 1; } - done=freects_done; + set_done(freects_done); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; diff --git a/uip/mhparam.c b/uip/mhparam.c index bfecb9fb..e8047be6 100644 --- a/uip/mhparam.c +++ b/uip/mhparam.c @@ -10,6 +10,7 @@ #include #include +#include "h/done.h" #include #define MHPARAM_SWITCHES \ diff --git a/uip/mhpath.c b/uip/mhpath.c index abf6b01f..1e6ab515 100644 --- a/uip/mhpath.c +++ b/uip/mhpath.c @@ -6,6 +6,7 @@ */ #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/mhshow.c b/uip/mhshow.c index fea40835..d3b8504e 100644 --- a/uip/mhshow.c +++ b/uip/mhshow.c @@ -15,6 +15,7 @@ #include #include #include +#include "h/done.h" #include #include "mhmisc.h" #include "sbr/m_maildir.h" @@ -93,7 +94,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 1)) { return 1; } - done=freects_done; + set_done(freects_done); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; diff --git a/uip/mhshowsbr.c b/uip/mhshowsbr.c index f0b5ef4e..aee86ecb 100644 --- a/uip/mhshowsbr.c +++ b/uip/mhshowsbr.c @@ -14,6 +14,7 @@ #include #include #include +#include "h/done.h" #include #include "mhmisc.h" #include "mhshowsbr.h" diff --git a/uip/mhstore.c b/uip/mhstore.c index ed6ad77f..7fa819aa 100644 --- a/uip/mhstore.c +++ b/uip/mhstore.c @@ -14,6 +14,7 @@ #include #include #include +#include "h/done.h" #include #include "mhmisc.h" #include "sbr/m_maildir.h" @@ -78,7 +79,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 1)) { return 1; } - done=freects_done; + set_done(freects_done); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; diff --git a/uip/mkstemp.c b/uip/mkstemp.c index f28ccf24..7028d43a 100644 --- a/uip/mkstemp.c +++ b/uip/mkstemp.c @@ -118,6 +118,7 @@ build_template(const char *directory, const char *prefix, const char *suffix) { #if NMH #include +#include "h/done.h" #include #if HAVE_MKSTEMPS diff --git a/uip/msgchk.c b/uip/msgchk.c index 73ed7284..e4aad8a1 100644 --- a/uip/msgchk.c +++ b/uip/msgchk.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include #include diff --git a/uip/new.c b/uip/new.c index ae5f3765..d608883d 100644 --- a/uip/new.c +++ b/uip/new.c @@ -13,6 +13,7 @@ #include #include +#include "h/done.h" #include #include "sbr/lock_file.h" #include "sbr/m_maildir.h" diff --git a/uip/packf.c b/uip/packf.c index 94a18eff..4d25c38e 100644 --- a/uip/packf.c +++ b/uip/packf.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" @@ -46,7 +47,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 1)) { return 1; } - done=mbxclose_done; + set_done(mbxclose_done); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; diff --git a/uip/pick.c b/uip/pick.c index 1084a478..d252f3cc 100644 --- a/uip/pick.c +++ b/uip/pick.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" @@ -72,7 +73,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 1)) { return 1; } - done=putzero_done; + set_done(putzero_done); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; diff --git a/uip/post.c b/uip/post.c index 56ae555c..c6a09175 100644 --- a/uip/post.c +++ b/uip/post.c @@ -12,6 +12,7 @@ #include #include #include +#include "h/done.h" #include #include #include diff --git a/uip/prompter.c b/uip/prompter.c index fc7b2c63..3a51dbe3 100644 --- a/uip/prompter.c +++ b/uip/prompter.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_mktemp.h" #include diff --git a/uip/rcvdist.c b/uip/rcvdist.c index f30a573c..bf301cc2 100644 --- a/uip/rcvdist.c +++ b/uip/rcvdist.c @@ -10,6 +10,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_mktemp.h" @@ -49,7 +50,7 @@ main (int argc, char **argv) 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 diff --git a/uip/rcvpack.c b/uip/rcvpack.c index 7fc7602f..ec1342e4 100644 --- a/uip/rcvpack.c +++ b/uip/rcvpack.c @@ -10,6 +10,7 @@ #include #include #include +#include "h/done.h" #include #define RCVPACK_SWITCHES \ diff --git a/uip/rcvstore.c b/uip/rcvstore.c index 6f82f812..02388188 100644 --- a/uip/rcvstore.c +++ b/uip/rcvstore.c @@ -9,6 +9,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" @@ -58,7 +59,7 @@ main (int argc, char **argv) if (nmh_init(argv[0], 2)) { return 1; } - done=unlink_done; + set_done(unlink_done); mts_init (); arguments = getarguments (invo_name, argc, argv, 1); diff --git a/uip/rcvtty.c b/uip/rcvtty.c index 2c66fa6f..f1368f71 100644 --- a/uip/rcvtty.c +++ b/uip/rcvtty.c @@ -17,6 +17,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_mktemp.h" #include diff --git a/uip/refile.c b/uip/refile.c index bed5cba6..be1294fe 100644 --- a/uip/refile.c +++ b/uip/refile.c @@ -7,6 +7,7 @@ */ #include +#include "h/done.h" #include #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" diff --git a/uip/repl.c b/uip/repl.c index 5f2886a2..f213eb30 100644 --- a/uip/repl.c +++ b/uip/repl.c @@ -7,6 +7,7 @@ #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/replsbr.c b/uip/replsbr.c index f99b6d0c..05997fdc 100644 --- a/uip/replsbr.c +++ b/uip/replsbr.c @@ -8,6 +8,7 @@ #include #include #include +#include "h/done.h" #include #include /* L_SET */ diff --git a/uip/rmf.c b/uip/rmf.c index a99b53cf..406d9a61 100644 --- a/uip/rmf.c +++ b/uip/rmf.c @@ -6,6 +6,7 @@ */ #include +#include "h/done.h" #include #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" diff --git a/uip/rmm.c b/uip/rmm.c index fa5fe5b9..104d5d2e 100644 --- a/uip/rmm.c +++ b/uip/rmm.c @@ -6,6 +6,7 @@ */ #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/scan.c b/uip/scan.c index b0c64f1c..c9cf4ce3 100644 --- a/uip/scan.c +++ b/uip/scan.c @@ -10,6 +10,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" #include "sbr/terminal.h" diff --git a/uip/send.c b/uip/send.c index 817feb70..f974337d 100644 --- a/uip/send.c +++ b/uip/send.c @@ -7,6 +7,7 @@ #include #include +#include "h/done.h" #include #ifdef OAUTH_SUPPORT # include diff --git a/uip/sendsbr.c b/uip/sendsbr.c index 371321c1..d7e76033 100644 --- a/uip/sendsbr.c +++ b/uip/sendsbr.c @@ -24,6 +24,7 @@ #ifdef OAUTH_SUPPORT #include #endif +#include "h/done.h" #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" #include "sbr/message_id.h" @@ -109,7 +110,7 @@ sendsbr (char **vec, int vecp, char *program, char *draft, struct stat *st, break; } - done=armed_done; + set_done(armed_done); switch (setjmp (env)) { case OK: /* @@ -175,7 +176,7 @@ sendsbr (char **vec, int vecp, char *program, char *draft, struct stat *st, break; } - done=exit; + set_done(exit); if (distfile) (void) m_unlink (distfile); diff --git a/uip/show.c b/uip/show.c index 86e8e5b5..def62759 100644 --- a/uip/show.c +++ b/uip/show.c @@ -7,6 +7,7 @@ #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/slocal.c b/uip/slocal.c index a4344fd0..df02d0d1 100644 --- a/uip/slocal.c +++ b/uip/slocal.c @@ -26,6 +26,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/lock_file.h" #include "sbr/m_mktemp.h" diff --git a/uip/sortm.c b/uip/sortm.c index 9f95c6d2..0b951bfe 100644 --- a/uip/sortm.c +++ b/uip/sortm.c @@ -7,6 +7,7 @@ #include #include +#include "h/done.h" #include #include "sbr/m_maildir.h" diff --git a/uip/viamail.c b/uip/viamail.c index db93066f..f706dfd1 100644 --- a/uip/viamail.c +++ b/uip/viamail.c @@ -12,6 +12,7 @@ #include #include #include +#include "h/done.h" #include #include "sbr/m_mktemp.h" #include "sbr/base64.h" diff --git a/uip/whatnowproc.c b/uip/whatnowproc.c index ca2236e8..2fa0ed85 100644 --- a/uip/whatnowproc.c +++ b/uip/whatnowproc.c @@ -6,6 +6,7 @@ */ #include +#include "h/done.h" /* diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c index 51836508..c5d2a8f8 100644 --- a/uip/whatnowsbr.c +++ b/uip/whatnowsbr.c @@ -44,6 +44,7 @@ #ifdef OAUTH_SUPPORT # include #endif +#include "h/done.h" #include "sbr/m_maildir.h" #include "sbr/m_mktemp.h" #include "sbr/mime_type.h" diff --git a/uip/whom.c b/uip/whom.c index 39a64703..76f434e4 100644 --- a/uip/whom.c +++ b/uip/whom.c @@ -6,6 +6,7 @@ */ #include +#include "h/done.h" #include #include #include "sbr/m_maildir.h"