1 /*
2 ** Copyright 2000-2007 Double Precision, Inc.  See COPYING for
3 ** distribution information.
4 */
5 
6 #include	"config.h"
7 #include	"liblock.h"
8 #include	<stdio.h>
9 #include	<signal.h>
10 #include	<limits.h>
11 #include	<stdlib.h>
12 #include	<string.h>
13 #include	<unistd.h>
14 #include	<ctype.h>
15 #include	<errno.h>
16 #if	HAVE_FCNTL_H
17 #include	<fcntl.h>
18 #endif
19 #include	<sys/types.h>
20 #include	"../numlib/numlib.h"
21 #if HAVE_SYS_WAIT_H
22 #include <sys/wait.h>
23 #endif
24 #ifndef WEXITSTATUS
25 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
26 #endif
27 #ifndef WIFEXITED
28 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
29 #endif
30 #if	HAVE_SYS_IOCTL_H
31 #include	<sys/ioctl.h>
32 #endif
33 
34 #define exit(_a_) _exit(_a_)
35 
36 
37 static int start1(const char *, int);
38 
39 #define CONSOLE "/dev/null"
40 
ll_daemon_start(const char * lockfile)41 int ll_daemon_start(const char *lockfile)
42 {
43 pid_t	p;
44 int	pipefd[2];
45 char	c;
46 int	i;
47 
48 	/*
49 	** Close any open file descriptors.
50 	*/
51 
52 	for (i=3; i < 256; i++)
53 		close(i);
54 
55 	/*
56 	** We fork, and set up a pipe from the child process.  If we read
57 	** a single 0 byte from the pipe, it means that the child has
58 	** successfully initialized, and will return to main, so we exit(0).
59 	** If we do not read a single 0 byte from the pipe, it means that
60 	** there was an initialization error, so we return -1 to main.
61 	*/
62 
63 	if (pipe(pipefd) < 0)
64 	{
65 		perror("pipe");
66 		return (-1);
67 	}
68 
69 	if ((p=fork()) == -1)
70 	{
71 		close(pipefd[0]);
72 		close(pipefd[1]);
73 		perror("fork");
74 		return (-1);
75 	}
76 
77 	if (p == 0)
78 	{
79 		close(pipefd[0]);
80 
81 		/*
82 		** We fork once more, so that the daemon process will not
83 		** be the child process of anyone.
84 		*/
85 
86 		p=fork();
87 		if (p == -1)
88 		{
89 			perror("fork");
90 			exit(0);
91 		}
92 		if (p)
93 			exit(0);
94 
95 		/*
96 		** Continue initialization in start1()
97 		*/
98 		return (start1(lockfile, pipefd[1]));
99 	}
100 
101 	close(pipefd[1]);
102 	if (read(pipefd[0], &c, 1) <= 0)
103 		c=1;
104 	close(pipefd[0]);
105 	if (c == 0)
106 		exit (0);	/* Successful start of daemon */
107 	errno=EAGAIN;
108 	return (-1);
109 }
110 
start1(const char * lockfile,int fd)111 static int start1(const char *lockfile, int fd)
112 {
113 int	lockfd, maxfd;
114 
115 #if     HAVE_SETPGRP
116 #if     SETPGRP_VOID
117 	setpgrp();
118 #else
119 	setpgrp(0, 0);
120 #endif
121 #endif
122 #ifdef  TIOCNOTTY
123 
124 	{
125 	int fd=open("/dev/tty", O_RDWR);
126 
127 		if (fd >= 0)
128 		{
129 			ioctl(fd, TIOCNOTTY, 0);
130 			close(fd);
131 		}
132 	}
133 #endif
134 
135 
136 	/* Attempt to obtain a lock */
137 
138 	lockfd=open(lockfile, O_RDWR|O_CREAT, 0600);
139 
140 	if (lockfd < 0)
141 	{
142 		/* Perhaps an upgraded daemon runs under new uid? */
143 
144 		unlink(lockfile);
145 		lockfd=open(lockfile, O_RDWR|O_CREAT, 0600);
146 	}
147 
148 #if HAVE_GETDTABLESIZE
149 	maxfd=getdtablesize()-1;
150 #elif defined(OPEN_MAX)
151 	maxfd=OPEN_MAX-1;
152 #elif HAVE_SYSCONF && defined(_SC_OPEN_MAX)
153 	if ((maxfd=sysconf(_SC_OPEN_MAX)) < 0)
154 		maxfd=63;
155 	else if (maxfd > 0)
156 		maxfd--;
157 #else
158 	maxfd=63;
159 #endif
160 
161 	if (lockfd < 0 || dup2(lockfd, maxfd) != maxfd)
162 	{
163 		perror(lockfile);
164 		exit(1);
165 	}
166 
167 	close(lockfd);
168 	lockfd=maxfd;
169 
170 #ifdef	FD_CLOEXEC
171 	if (fcntl(lockfd, F_SETFD, FD_CLOEXEC) < 0)
172 	{
173 		perror("fcntl");
174 		close(lockfd);
175 		exit(1);
176 	}
177 #endif
178 
179 	if (ll_lock_ex_test(lockfd))
180 	{
181 		if (write(fd, "", 1) != 1)
182 			exit(1); /* Shouldn't happen */
183 
184 		close(fd);
185 		exit (0);	/* Already running, pretend success */
186 	}
187 
188 	/*
189 	** Return >0 to main, so it can continue main's setup.
190 	*/
191 
192 	return (fd);
193 }
194 
ll_daemon_resetio()195 int ll_daemon_resetio()
196 {
197 int	i;
198 
199 	close(0);
200 	if (open("/dev/null", O_RDONLY) != 0)
201 		return (-1);
202 
203 	close(1);
204 	i=open(CONSOLE, O_WRONLY);
205 	if (i < 0)	i=open("/dev/null", O_WRONLY);
206 	if (i != 1)	return (-1);
207 
208 	close(2);
209 	i=open(CONSOLE, O_WRONLY);
210 	if (i < 0)	i=open("/dev/null", O_WRONLY);
211 	if (i != 2)	return (-1);
212 	return (0);
213 }
214 
ll_daemon_started(const char * pidfile,int fd)215 void ll_daemon_started(const char *pidfile, int fd)
216 {
217 char	buf[NUMBUFSIZE+1];
218 char	*p=strcat(libmail_str_pid_t(getpid(), buf), "\n");
219 FILE	*fp;
220 
221 	unlink(pidfile);
222 	if ((fp=fopen(pidfile, "w")) == NULL ||
223 		fprintf(fp, "%s", p) < 0 || fflush(fp) < 0 || fclose(fp))
224 	{
225 		perror(pidfile);
226 		exit(1);
227 	}
228 
229 	if (write(fd, "", 1) != 1)	/* Signal waiting parent */
230 		exit(1); /* Shouldn't happen */
231 	close(fd);
232 }
233 
234 static void stop1(const char *, const char *);
235 
ll_daemon_stop(const char * lockfile,const char * pidfile)236 int ll_daemon_stop(const char *lockfile, const char *pidfile)
237 {
238 pid_t	p, p2;
239 int	waitstat;
240 
241 	/*
242 	** We fork, and the child process attempts to stop the daemon,
243 	** then communicates the success to us, via its exit code.
244 	*/
245 
246 	signal(SIGCHLD, SIG_DFL);
247 	if ((p=fork()) == -1)
248 	{
249 		perror("fork");
250 		return (1);
251 	}
252 	if (p == 0)	stop1(lockfile, pidfile);
253 
254 	while ((p2=wait(&waitstat)) != p)
255 		;
256 
257 	if (WIFEXITED(waitstat))
258 		return (WEXITSTATUS(waitstat));
259 	return (0);
260 }
261 
262 /*
263 **	The child process forks too.  The parent process goes in a loop,
264 **	trying to kill the daemon process.
265 **
266 **	The child process attempts to lock the lock file.  When it
267 **	succeeds, it exits.  When the child process exits, the parent
268 **	process kills itself.
269 */
270 
sigexit(int signum)271 static RETSIGTYPE sigexit(int signum)
272 {
273 	kill(getpid(), SIGKILL);
274 #if     RETSIGTYPE != void
275 	return (0);
276 #endif
277 }
278 
stop1(const char * lockfile,const char * pidfile)279 static void stop1(const char *lockfile, const char *pidfile)
280 {
281 int	lockfd;
282 pid_t	p;
283 
284 	if ((lockfd=open(lockfile, O_RDWR|O_CREAT, 0600)) < 0)
285 	{
286 		perror(lockfile);
287 		exit(1);
288 	}
289 
290 	if ( ll_lock_ex_test(lockfd) == 0)	/* No daemon process running */
291 	{
292 		close(lockfd);
293 		exit (0);	/* That was easy! */
294 	}
295 
296 	signal(SIGCHLD, sigexit);
297 
298 	if ((p=fork()) == -1)
299 	{
300 		perror("fork");
301 		exit(1);
302 	}
303 
304 	if (p)	/* Parent - first sends a SIGTERM, then a SIGKILL */
305 	{
306 	int	signum=SIGTERM;
307 
308 		close(lockfd);
309 		for (;; sleep(10))
310 		{
311 		FILE	*fp;
312 		int	c;
313 
314 			if ((fp=fopen(pidfile, "r")) == NULL)
315 				continue;
316 
317 			p=0;
318 
319 			while ((c=getc(fp)) != EOF && c != '\n')
320 			{
321 				if (isdigit(c))
322 					p=p*10+(c-'0');
323 			}
324 
325 			fclose(fp);
326 			if (p)
327 				kill(p, signum);
328 			signum=SIGKILL;
329 		}
330 	}
331 
332 	if (ll_lock_ex(lockfd))
333 		perror("lock");
334 	close(lockfd);
335 	exit(0);
336 }
337 
ll_daemon_restart(const char * lockfile,const char * pidfile)338 int ll_daemon_restart(const char *lockfile, const char *pidfile)
339 {
340 int	lockfd;
341 pid_t	p;
342 FILE	*fp;
343 int	c;
344 
345 	if ((lockfd=open(lockfile, O_RDWR|O_CREAT, 0600)) < 0)
346 	{
347 		perror(lockfile);
348 		return (1);
349 	}
350 
351 	if ( ll_lock_ex_test(lockfd) == 0)	/* No daemon process running */
352 	{
353 		close(lockfd);
354 		return (0);	/* That was easy! */
355 	}
356 	close(lockfd);
357 
358 	if ((fp=fopen(pidfile, "r")) == NULL)
359 		return (0);
360 
361 	p=0;
362 
363 	while ((c=getc(fp)) != EOF && c != '\n')
364 	{
365 		if (isdigit(c))
366 			p=p*10+(c-'0');
367 	}
368 
369 	fclose(fp);
370 	if (p)
371 		kill(p, SIGHUP);
372 	return (0);
373 }
374 
375