xref: /openbsd/regress/lib/csu/dtors/dtors.c (revision 1821443c)
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