1 /* $OpenBSD: dtors.c,v 1.5 2003/09/02 23:52:16 david Exp $ */
2 /*
3 * Written by Artur Grabowski <art@openbsd.org>, 2002 Public Domain.
4 */
5 #include <sys/types.h>
6 #include <sys/mman.h>
7 #include <sys/wait.h>
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <err.h>
13 #include <unistd.h>
14
15 void zap(void) __attribute__((destructor));
16
17 void *destarea;
18
19 #define MAGIC "destructed"
20
21 void
zap(void)22 zap(void)
23 {
24 memcpy(destarea, MAGIC, sizeof(MAGIC));
25 }
26
27 /*
28 * XXX - horrible abuse of exit(3), minherit(2) and fork(2).
29 */
30 int
main(int argc,char ** argv)31 main(int argc, char **argv)
32 {
33 int status, ch;
34 int fallthru = 0;
35
36 while ((ch = getopt(argc, argv, "f")) != -1) {
37 switch(ch) {
38 case 'f':
39 fallthru = 1;
40 break;
41 default:
42 fprintf(stderr, "Usage: dtors [-f]\n");
43 exit(1);
44 }
45 }
46
47 destarea = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_ANON,
48 -1, 0);
49 if (destarea == MAP_FAILED)
50 err(1, "mmap");
51
52 if (minherit(destarea, getpagesize(), MAP_INHERIT_SHARE) != 0)
53 err(1, "minherit");
54
55 memset(destarea, 0, sizeof(MAGIC));
56
57 switch(fork()) {
58 case -1:
59 err(1, "fork");
60 case 0:
61 /*
62 * Yes, it's exit(), not _exit(). We _want_ to run the
63 * destructors in the child.
64 */
65 if (fallthru)
66 return (0);
67 else
68 exit(0);
69 }
70
71 if (wait(&status) < 0)
72 err(1, "wait"); /* XXX uses exit() */
73
74 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
75 err(1, "child error"); /* XXX uses exit() */
76
77 _exit(memcmp(destarea, MAGIC, sizeof(MAGIC)) != 0);
78 }
79