* correct spelling of options.
[citadel.git] / webcit / ctdlsvc.c
1 /*
2  * $Id: $
3  *
4  * This is just a quick little hack to start a program in the background,
5  * and automatically restart it if it exits with a nonzero exit status.
6  *
7  */
8
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <errno.h>
15 #include <signal.h>
16 #include <fcntl.h>
17 #include <string.h>
18
19 char *pidfilename = NULL;
20 pid_t current_child = 0;
21
22 void graceful_shutdown(int signum) {
23         kill(current_child, signum);
24         if (pidfilename != NULL) {
25                 unlink(pidfilename);
26         }
27         exit(0);
28 }
29         
30
31 int main(int argc, char **argv)
32 {
33         pid_t child = 0;
34         int status = 0;
35         FILE *fp;
36         int nullfd;
37
38         --argc;
39         ++argv;
40
41         pidfilename = argv[0];
42         --argc;
43         ++argv;
44
45         if (access(argv[0], X_OK)) {
46                 fprintf(stderr, "%s: cannot execute\n", argv[0]);
47                 exit(1);
48         }
49
50         /* Close stdin/stdout/stderr and replace them with /dev/null.
51          * We don't just call close() because we don't want these fd's
52          * to be reused for other files.
53          */
54         nullfd = open("/dev/null", O_RDWR);
55         if (nullfd < 0) {
56                 fprintf(stderr, "/dev/null: %s\n", strerror(errno));
57                 exit(2);
58         }
59         dup2(nullfd, 0);
60         dup2(nullfd, 1);
61         dup2(nullfd, 2);
62         close(nullfd);
63
64         signal(SIGHUP, SIG_IGN);
65         signal(SIGINT, SIG_IGN);
66         signal(SIGQUIT, SIG_IGN);
67
68         child = fork();
69         if (child != 0) {
70                 fp = fopen(pidfilename, "w");
71                 if (fp != NULL) {
72                         fprintf(fp, "%d\n", child);
73                         fclose(fp);
74                 }
75                 exit(0);
76         }
77
78         do {
79                 current_child = fork();
80
81                 signal(SIGTERM, graceful_shutdown);
82         
83                 if (current_child < 0) {
84                         perror("fork");
85                         exit(errno);
86                 }
87         
88                 else if (current_child == 0) {
89                         exit(execvp(argv[0], &argv[0]));
90                 }
91         
92                 else {
93                         waitpid(current_child, &status, 0);
94                 }
95
96         } while (status != 0);
97
98         unlink(pidfilename);
99         exit(0);
100 }
101