1 #ifndef __supervise_h
2 #define __supervise_h
3
4 #include "config.h"
5
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <unistd.h>
11
12 #ifndef HAVE_SYSLOG
supervise(char * x)13 static void inline supervise(char *x)
14 {
15 fatal("You probably don't want to supervise when you cannot log");
16 }
17 #else
18 static int supervised_pid = -1;
19 static int supervised_quit = 0;
handle_sign(int signo)20 static void handle_sign(int signo)
21 {
22 if (supervised_pid != -1) {
23 kill(supervised_pid, signo);
24 supervised_quit = 1;
25 }
26 }
supervise(char * x)27 static void inline supervise(char *x)
28 {
29 int fd, status;
30 int super_pid;
31 /* GOOD DAEMON PRACTICES */
32
33 /* do first fork */
34 signal(SIGCHLD, SIG_IGN);
35 switch (fork()) {
36 case -1: cfatal("fork: %s");
37 case 0: break;
38 default: exit(0);
39 };
40
41 /* be a proper daemon */
42 fd = open("/dev/null", O_RDWR);
43 if (fd != 0) { close(0); dup2(fd, 0); }
44 if (fd != 1) { close(1); dup2(fd, 1); }
45 if (fd != 2) { close(2); dup2(fd, 2); }
46 if (fd > 2) { close(fd); }
47
48 super_pid = getpid();
49 #ifdef HAVE_SETSID
50 /* change session ID if possible */
51 (void) setsid();
52 #endif
53 /* signore Sigpipe */
54 signal(SIGPIPE, SIG_IGN);
55
56 /* we want child notification */
57 signal(SIGCHLD, SIG_DFL);
58
59 /* setup other signals */
60 signal(SIGSTOP, handle_sign);
61 signal(SIGCONT, handle_sign);
62 signal(SIGTERM, handle_sign);
63 signal(SIGHUP, handle_sign);
64 signal(SIGINT, handle_sign);
65
66 /* do second fork */
67 restart_from_child_l:
68 switch ((supervised_pid = fork())) {
69 case -1: cfatal("fork: %s");
70 case 0: /* child */ return;
71 };
72
73 /* pid file */
74 if (x && *x == '/') {
75 FILE *fp;
76
77 fp = fopen(x, "w");
78 fprintf(fp, "%d\n", super_pid);
79 fclose(fp);
80 }
81
82 wait_some_more_l:
83 #ifdef HAVE_WAITPID
84 waitpid(supervised_pid, &status, 0);
85 #else
86 #ifdef HAVE_WAIT4
87 wait4(supervised_pid, &status, 0, NULL);
88 #else
89 while (wait(&status) != supervised_pid);
90 #endif
91 #endif
92 if (kill(supervised_pid, 0) == -1) {
93 sleep(1); /* go to sleep for 1 second */
94 if ((volatile)supervised_quit)
95 exit(0);
96 /* wasn't supposed to be dead yet... */
97 goto restart_from_child_l;
98 }
99 supervised_quit = 0;
100 goto wait_some_more_l;
101 }
102 #endif
103
104 #endif
105