1 /* pidfile handling for DBMail, many thanks to Tridge and Samba
2 * for making their software available under the GNU GPL.
3 *
4 * Modified for DBMail by Aaron Stone, July 9, 2004.
5 */
6
7 /* this code is broken - there is a race condition with the unlink (tridge) */
8
9 /*
10 Unix SMB/CIFS implementation.
11 pidfile handling
12 Copyright (C) Andrew Tridgell 1998
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 #include "dbmail.h"
30 #define THIS_MODULE "pidfile"
31
32 /* These are used by pidfile_remove. */
33 static FILE *pidfile_to_close;
34 static char *pidfile_to_remove;
35
36 /* Check if a process exists. */
process_exists(pid_t pid)37 static int process_exists(pid_t pid)
38 {
39 if (pid > 0)
40 return (kill(pid, 0) == 0 || errno != ESRCH);
41 return 0;
42 }
43
44 /* Return the pid in a pidfile, or return 0
45 * if the process or pidfile does not exist. */
pidfile_pid(const char * pidFile)46 static pid_t pidfile_pid(const char *pidFile)
47 {
48 FILE *f;
49 char pidstr[20];
50 unsigned ret;
51
52 memset(pidstr, 0, sizeof(pidstr));
53
54 if (!(f = fopen(pidFile, "r"))) {
55 return 0;
56 }
57
58 if (fread(pidstr, sizeof(char), sizeof(pidstr)-1, f) <= 0) {
59 goto noproc;
60 }
61
62 ret = atoi(pidstr);
63
64 if (!process_exists((pid_t)ret)) {
65 goto noproc;
66 }
67
68 fclose(f);
69 return (pid_t)ret;
70
71 noproc:
72 fclose(f);
73 unlink(pidFile);
74 return 0;
75 }
76
pidfile_remove(void)77 static void pidfile_remove(void)
78 {
79 int res;
80
81 if (pidfile_to_close) {
82 res = fclose(pidfile_to_close);
83 if (res) TRACE(TRACE_ERR, "Error closing pidfile: [%s].",
84 strerror(errno));
85 pidfile_to_close = NULL;
86 }
87
88 if (pidfile_to_remove) {
89 res = unlink(pidfile_to_remove);
90 if (res) TRACE(TRACE_ERR, "Error unlinking pidfile [%s]: [%s].",
91 pidfile_to_remove, strerror(errno));
92 g_free(pidfile_to_remove);
93 pidfile_to_remove = NULL;
94 }
95
96 }
97
98 /* Create a pidfile and leave it open. */
pidfile_create(const char * pidFile,pid_t pid)99 void pidfile_create(const char *pidFile, pid_t pid)
100 {
101 FILE *f;
102 pid_t oldpid;
103
104 oldpid = pidfile_pid(pidFile);
105
106 if (oldpid != 0) {
107 TRACE(TRACE_EMERG, "File [%s] exists and process id [%d] is running.",
108 pidFile, (int)pid);
109 }
110
111 if (!(f = fopen(pidFile, "w"))) {
112 int serr = errno;
113 TRACE(TRACE_EMERG, "open pidfile [%s] failed: [%s]",
114 pidFile, strerror(serr));
115 return;
116 }
117 if (chmod(pidFile, 0644)) {
118 int serr = errno;
119 TRACE(TRACE_EMERG, "chown pidfile [%s] failed: [%s]",
120 pidFile, strerror(serr));
121 fclose(f);
122 return;
123 }
124
125 fprintf(f, "%u\n", pid);
126 fflush(f);
127
128 /* Leave pid file open & locked for the duration,
129 * but close and remove it upon termination. */
130 atexit(pidfile_remove);
131
132 pidfile_to_close = f;
133 pidfile_to_remove = g_strdup(pidFile);
134
135 }
136
137