2 ** Copyright 2000-2007 Double Precision, Inc. See COPYING for
3 ** distribution information.
19 #include <sys/types.h>
20 #include "../numlib/numlib.h"
25 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
28 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
31 #include <sys/ioctl.h>
34 #define exit(_a_) _exit(_a_)
36 static const char rcsid
[]="$Id: lockdaemon.c,v 1.14 2007/10/11 01:46:34 mrsam Exp $";
38 static int start1(const char *, int);
40 #define CONSOLE "/dev/null"
42 int ll_daemon_start(const char *lockfile
)
50 ** Close any open file descriptors.
53 for (i
=3; i
< 256; i
++)
57 ** We fork, and set up a pipe from the child process. If we read
58 ** a single 0 byte from the pipe, it means that the child has
59 ** succesfully initialized, and will return to main, so we exit(0).
60 ** If we do not read a single 0 byte from the pipe, it means that
61 ** there was an initialization error, so we return -1 to main.
83 ** We fork once more, so that the daemon process will not
84 ** be the child process of anyone.
97 ** Continue initialization in start1()
99 return (start1(lockfile
, pipefd
[1]));
103 if (read(pipefd
[0], &c
, 1) <= 0)
107 exit (0); /* Successful start of daemon */
112 static int start1(const char *lockfile
, int fd
)
126 int fd
=open("/dev/tty", O_RDWR
);
130 ioctl(fd
, TIOCNOTTY
, 0);
137 /* Attempt to obtain a lock */
139 lockfd
=open(lockfile
, O_RDWR
|O_CREAT
, 0600);
143 /* Perhaps an upgraded daemon runs under new uid? */
146 lockfd
=open(lockfile
, O_RDWR
|O_CREAT
, 0600);
149 #if HAVE_GETDTABLESIZE
150 maxfd
=getdtablesize()-1;
151 #elif defined(OPEN_MAX)
153 #elif HAVE_SYSCONF && defined(_SC_OPEN_MAX)
154 if ((maxfd
=sysconf(_SC_OPEN_MAX
)) < 0)
162 if (lockfd
< 0 || dup2(lockfd
, maxfd
) != maxfd
)
172 if (fcntl(lockfd
, F_SETFD
, FD_CLOEXEC
) < 0)
180 if (ll_lock_ex_test(lockfd
))
182 if (write(fd
, "", 1) != 1)
183 exit(1); /* Shouldn't happen */
186 exit (0); /* Already running, pretend success */
190 ** Return >0 to main, so it can continue main's setup.
196 int ll_daemon_resetio()
201 if (open("/dev/null", O_RDONLY
) != 0)
205 i
=open(CONSOLE
, O_WRONLY
);
206 if (i
< 0) i
=open("/dev/null", O_WRONLY
);
207 if (i
!= 1) return (-1);
210 i
=open(CONSOLE
, O_WRONLY
);
211 if (i
< 0) i
=open("/dev/null", O_WRONLY
);
212 if (i
!= 2) return (-1);
216 void ll_daemon_started(const char *pidfile
, int fd
)
218 char buf
[NUMBUFSIZE
+1];
219 char *p
=strcat(libmail_str_pid_t(getpid(), buf
), "\n");
223 if ((fp
=fopen(pidfile
, "w")) == NULL
||
224 fprintf(fp
, "%s", p
) < 0 || fflush(fp
) < 0 || fclose(fp
))
230 if (write(fd
, "", 1) != 1) /* Signal waiting parent */
231 exit(1); /* Shouldn't happen */
235 static void stop1(const char *, const char *);
237 int ll_daemon_stop(const char *lockfile
, const char *pidfile
)
243 ** We fork, and the child process attempts to stop the daemon,
244 ** then communicates the success to us, via its exit code.
247 signal(SIGCHLD
, SIG_DFL
);
248 if ((p
=fork()) == -1)
253 if (p
== 0) stop1(lockfile
, pidfile
);
255 while ((p2
=wait(&waitstat
)) != p
)
258 if (WIFEXITED(waitstat
))
259 return (WEXITSTATUS(waitstat
));
264 ** The child process forks too. The parent process goes in a loop,
265 ** trying to kill the daemon process.
267 ** The child process attempts to lock the lock file. When it
268 ** succeeds, it exits. When the child process exits, the parent
269 ** process kills itself.
272 static RETSIGTYPE
sigexit(int signum
)
274 kill(getpid(), SIGKILL
);
275 #if RETSIGTYPE != void
280 static void stop1(const char *lockfile
, const char *pidfile
)
285 if ((lockfd
=open(lockfile
, O_RDWR
|O_CREAT
, 0600)) < 0)
291 if ( ll_lock_ex_test(lockfd
) == 0) /* No daemon process running */
294 exit (0); /* That was easy! */
297 signal(SIGCHLD
, sigexit
);
299 if ((p
=fork()) == -1)
305 if (p
) /* Parent - first sends a SIGTERM, then a SIGKILL */
315 if ((fp
=fopen(pidfile
, "r")) == NULL
)
320 while ((c
=getc(fp
)) != EOF
&& c
!= '\n')
333 if (ll_lock_ex(lockfd
))
339 int ll_daemon_restart(const char *lockfile
, const char *pidfile
)
346 if ((lockfd
=open(lockfile
, O_RDWR
|O_CREAT
, 0600)) < 0)
352 if ( ll_lock_ex_test(lockfd
) == 0) /* No daemon process running */
355 return (0); /* That was easy! */
359 if ((fp
=fopen(pidfile
, "r")) == NULL
)
364 while ((c
=getc(fp
)) != EOF
&& c
!= '\n')