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 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 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