lockdaemon.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:5k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 2000 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. #include "config.h"
  6. #include "liblock.h"
  7. #include <stdio.h>
  8. #include <signal.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #if HAVE_FCNTL_H
  13. #include <fcntl.h>
  14. #endif
  15. #include <sys/types.h>
  16. #include "../numlib/numlib.h"
  17. #if HAVE_SYS_WAIT_H
  18. #include <sys/wait.h>
  19. #endif
  20. #ifndef WEXITSTATUS
  21. #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
  22. #endif
  23. #ifndef WIFEXITED
  24. #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
  25. #endif
  26. #if HAVE_SYS_IOCTL_H
  27. #include <sys/ioctl.h>
  28. #endif
  29. static const char rcsid[]="$Id: lockdaemon.c,v 1.1 2000/04/26 22:31:10 mrsam Exp $";
  30. static int start1(const char *, int);
  31. int ll_daemon_start(const char *lockfile)
  32. {
  33. pid_t p;
  34. int pipefd[2];
  35. char c;
  36. int i;
  37. /*
  38. ** Close any open file descriptors.
  39. */
  40. for (i=3; i < 256; i++)
  41. close(i);
  42. /*
  43. ** We fork, and set up a pipe from the child process.  If we read
  44. ** a single 0 byte from the pipe, it means that the child has
  45. ** succesfully initialized, and will return to main, so we exit(0).
  46. ** If we do not read a single 0 byte from the pipe, it means that
  47. ** there was an initialization error, so we return -1 to main.
  48. */
  49. if (pipe(pipefd) < 0)
  50. {
  51. perror("pipe");
  52. return (-1);
  53. }
  54. if ((p=fork()) == -1)
  55. {
  56. close(pipefd[0]);
  57. close(pipefd[1]);
  58. perror("fork");
  59. return (-1);
  60. }
  61. if (p == 0)
  62. {
  63. close(pipefd[0]);
  64. /*
  65. ** We fork once more, so that the daemon process will not
  66. ** be the child process of anyone.
  67. */
  68. p=fork();
  69. if (p == -1)
  70. {
  71. perror("fork");
  72. exit(0);
  73. }
  74. if (p)
  75. exit(0);
  76. /*
  77. ** Continue initialization in start1()
  78. */
  79. return (start1(lockfile, pipefd[1]));
  80. }
  81. close(pipefd[1]);
  82. if (read(pipefd[0], &c, 1) <= 0)
  83. c=1;
  84. close(pipefd[0]);
  85. if (c == 0)
  86. exit (0); /* Successful start of daemon */
  87. return (-1);
  88. }
  89. static int start1(const char *lockfile, int fd)
  90. {
  91. int lockfd;
  92. #if     HAVE_SETPGRP
  93. #if     SETPGRP_VOID
  94. setpgrp();
  95. #else
  96. setpgrp(0, 0);
  97. #endif
  98. #endif
  99. #ifdef  TIOCNOTTY
  100. {
  101. int fd=open("/dev/tty", O_RDWR);
  102. if (fd >= 0)
  103. {
  104. ioctl(fd, TIOCNOTTY, 0);
  105. close(fd);
  106. }
  107. }
  108. #endif
  109. /* Attempt to obtain a lock */
  110. if ((lockfd=open(lockfile, O_RDWR|O_CREAT, 0600)) < 0)
  111. {
  112. perror(lockfile);
  113. exit(1);
  114. }
  115. #ifdef FD_CLOEXEC
  116. if (fcntl(lockfd, F_SETFD, FD_CLOEXEC) < 0)
  117. {
  118. perror("fcntl");
  119. close(lockfd);
  120. exit(1);
  121. }
  122. #endif
  123. if (ll_lock_ex_test(lockfd))
  124. {
  125. write(fd, "", 1);
  126. close(fd);
  127. exit (0); /* Already running, pretend success */
  128. }
  129. /*
  130. ** Return >0 to main, so it can continue main's setup.
  131. */
  132. return (fd);
  133. }
  134. int ll_daemon_resetio()
  135. {
  136. int i;
  137. close(0);
  138. if (open("/dev/null", O_RDONLY) != 0)
  139. return (-1);
  140. close(1);
  141. i=open("/dev/console", O_WRONLY);
  142. if (i < 0) i=open("/dev/null", O_WRONLY);
  143. if (i != 1) return (-1);
  144. close(2);
  145. i=open("/dev/console", O_WRONLY);
  146. if (i < 0) i=open("/dev/null", O_WRONLY);
  147. if (i != 2) return (-1);
  148. return (0);
  149. }
  150. void ll_daemon_started(const char *pidfile, int fd)
  151. {
  152. char buf[NUMBUFSIZE+1];
  153. char *p=strcat(str_pid_t(getpid(), buf), "n");
  154. size_t l=strlen(p);
  155. FILE *fp;
  156. if ((fp=fopen(pidfile, "w")) < 0 ||
  157. fprintf(fp, "%s", p) < 0 || fflush(fp) < 0 || fclose(fp))
  158. {
  159. perror(pidfile);
  160. exit(1);
  161. }
  162. write(fd, "", 1); /* Signal waiting parent */
  163. close(fd);
  164. }
  165. static void stop1(const char *, const char *);
  166. int ll_daemon_stop(const char *lockfile, const char *pidfile)
  167. {
  168. pid_t p, p2;
  169. int waitstat;
  170. /*
  171. ** We fork, and the child process attempts to stop the daemon,
  172. ** then communicates the success to us, via its exit code.
  173. */
  174. signal(SIGCHLD, SIG_DFL);
  175. if ((p=fork()) == -1)
  176. {
  177. perror("fork");
  178. return (1);
  179. }
  180. if (p == 0) stop1(lockfile, pidfile);
  181. while ((p2=wait(&waitstat)) != p)
  182. ;
  183. if (WIFEXITED(waitstat))
  184. return (WEXITSTATUS(waitstat));
  185. return (0);
  186. }
  187. /*
  188. ** The child process forks too.  The parent process goes in a loop,
  189. ** trying to kill the daemon process.
  190. **
  191. ** The child process attempts to lock the lock file.  When it
  192. ** succeeds, it exits.  When the child process exits, the parent
  193. ** process kills itself.
  194. */
  195. static RETSIGTYPE sigexit(int signum)
  196. {
  197. kill(getpid(), SIGKILL);
  198. #if     RETSIGTYPE != void
  199. return (0);
  200. #endif
  201. }
  202. static void stop1(const char *lockfile, const char *pidfile)
  203. {
  204. int lockfd;
  205. pid_t p;
  206. if ((lockfd=open(lockfile, O_RDWR|O_CREAT, 0600)) < 0)
  207. {
  208. perror(lockfile);
  209. exit(1);
  210. }
  211. if ( ll_lock_ex_test(lockfd) == 0) /* No daemon process running */
  212. {
  213. close(lockfd);
  214. exit (0); /* That was easy! */
  215. }
  216. signal(SIGCHLD, sigexit);
  217. if ((p=fork()) == -1)
  218. {
  219. perror("fork");
  220. exit(1);
  221. }
  222. if (p) /* Parent - first sends a SIGTERM, then a SIGKILL */
  223. {
  224. int signum=SIGTERM;
  225. close(lockfd);
  226. for (;; sleep(10))
  227. {
  228. FILE *fp;
  229. int c;
  230. if ((fp=fopen(pidfile, "r")) < 0)
  231. continue;
  232. p=0;
  233. while ((c=getc(fp)) != EOF && c != 'n')
  234. {
  235. if (isdigit(c))
  236. p=p*10+(c-'0');
  237. }
  238. fclose(fp);
  239. if (p)
  240. kill(p, signum);
  241. signum=SIGKILL;
  242. }
  243. }
  244. if (ll_lock_ex(lockfd))
  245. perror("lock");
  246. close(lockfd);
  247. exit(0);
  248. }
  249. int ll_daemon_restart(const char *lockfile, const char *pidfile)
  250. {
  251. int lockfd;
  252. pid_t p;
  253. FILE *fp;
  254. int c;
  255. if ((lockfd=open(lockfile, O_RDWR|O_CREAT, 0600)) < 0)
  256. {
  257. perror(lockfile);
  258. return (1);
  259. }
  260. if ( ll_lock_ex_test(lockfd) == 0) /* No daemon process running */
  261. {
  262. close(lockfd);
  263. return (0); /* That was easy! */
  264. }
  265. close(lockfd);
  266. if ((fp=fopen(pidfile, "r")) < 0)
  267. return (0);
  268. p=0;
  269. while ((c=getc(fp)) != EOF && c != 'n')
  270. {
  271. if (isdigit(c))
  272. p=p*10+(c-'0');
  273. }
  274. fclose(fp);
  275. if (p)
  276. kill(p, SIGHUP);
  277. return (0);
  278. }