tdb2: copy tdb1's changed expansion logic.
[ccan] / ccan / daemon_with_notify / daemon_with_notify.c
1 /*-
2  * Copyright (c) 1990, 1993
3  *    The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 2010
5  *    Stewart Smith
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <signal.h>
38 #include <unistd.h>
39 #include <sys/select.h>
40
41 #include <ccan/daemon_with_notify/daemon_with_notify.h>
42
43 void sigusr1_handler(int sig);
44
45 pid_t parent_pid;
46
47 void sigusr1_handler(int sig)
48 {
49   if (sig == SIGUSR1)
50     _exit(EXIT_SUCCESS);
51 }
52
53 int daemon_is_ready(void)
54 {
55   kill(parent_pid, SIGUSR1);
56   return 0;
57 }
58
59 int daemonize(int nochdir, int noclose, int wait_sigusr1)
60 {
61     int fd;
62     pid_t child= -1;
63
64     parent_pid= getpid();
65     signal(SIGUSR1, sigusr1_handler);
66
67     child= fork();
68
69     switch (child)
70     {
71     case -1:
72         return (-1);
73     case 0:
74         break;
75     default:
76       if (wait_sigusr1)
77       {
78         /* parent */
79         int exit_code= -1;
80         int status;
81         while (waitpid(child, &status, 0) != child);
82         if (WIFEXITED(status))
83         {
84           exit_code= WEXITSTATUS(status);
85         }
86         if (WIFSIGNALED(status))
87         {
88           exit_code= -1;
89         }
90         _exit(exit_code);
91       }
92       else
93       {
94         _exit(EXIT_SUCCESS);
95       }
96     }
97
98     /* child */
99     if (setsid() == -1)
100         return (-1);
101
102     if (nochdir == 0) {
103         if(chdir("/") != 0) {
104             perror("chdir");
105             return (-1);
106         }
107     }
108
109     if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
110         if(dup2(fd, STDIN_FILENO) < 0) {
111             perror("dup2 stdin");
112             return (-1);
113         }
114         if(dup2(fd, STDOUT_FILENO) < 0) {
115             perror("dup2 stdout");
116             return (-1);
117         }
118         if(dup2(fd, STDERR_FILENO) < 0) {
119             perror("dup2 stderr");
120             return (-1);
121         }
122
123         if (fd > STDERR_FILENO) {
124             if(close(fd) < 0) {
125                 perror("close");
126                 return (-1);
127             }
128         }
129     }
130     return (0);
131 }