]> diplodocus.org Git - nmh/blob - sbr/done.c
inc/test-eom-align: Use octal, not hex, in printf(1) format string.
[nmh] / sbr / done.c
1 /* done.c -- terminate the program
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include <h/mh.h>
9
10 /* It's undefined behaviour in C99 to convert from a function pointer to
11 * a data-object pointer, e.g. void pointer. gcc's -pedantic warns of
12 * this and can stop compilation. POSIX requires the operation however,
13 * e.g. for dlsym(3), and so we know it's safe on POSIX platforms, e.g.
14 * the pointers are of the same size. Thus use a union to subvert gcc's
15 * check. The function-pointer equivalent of a void pointer is any
16 * function-pointer type as all function pointers are defined to be
17 * convertible from one another; use the simplest available. */
18 typedef union {
19 void *v;
20 void (*f)(void);
21 } generic_pointer;
22
23 static void (*altexit)(int) NORETURN = exit;
24
25 /* set_done changes the path of done() from exit(3), or back to exit(3).
26 * Anything else will work, but a standard-error warning will report the
27 * old non-exit() value has been trampled. */
28 void
29 set_done(void (*new)(int) NORETURN)
30 {
31 generic_pointer gpo, gpn;
32
33 if (altexit != exit && new != exit) {
34 gpo.f = (void (*)(void))altexit;
35 gpn.f = (void (*)(void))new;
36 inform("altexit trampled: %p %p", gpo.v, gpn.v);
37 }
38 altexit = new;
39 }
40
41 void NORETURN
42 done(int status)
43 {
44 (*altexit)(status);
45 }