- moved daemonize in its own file
[sip-router] / daemonize.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 Fhg Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 /*
28  * 
29  * History:
30  * --------
31  *  2004-02-20  removed from ser main.c into its own file (andrei)
32  *  2004-03-04  moved setuid/setgid in do_suid() (andrei)
33  */
34
35 #include <sys/types.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <syslog.h>
39 #include <errno.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43
44 #include "daemonize.h"
45 #include "globals.h"
46 #include "dprint.h"
47
48
49 #define MAX_FD 32 /* maximum number of inherited open file descriptors,
50                     (normally it shouldn't  be bigger  than 3) */
51
52
53
54 /* daemon init, return 0 on success, -1 on error */
55 int daemonize(char*  name)
56 {
57         FILE *pid_stream;
58         pid_t pid;
59         int r, p;
60
61
62         p=-1;
63
64
65         if (chroot_dir&&(chroot(chroot_dir)<0)){
66                 LOG(L_CRIT, "Cannot chroot to %s: %s\n", chroot_dir, strerror(errno));
67                 goto error;
68         }
69         
70         if (chdir(working_dir)<0){
71                 LOG(L_CRIT,"cannot chdir to %s: %s\n", working_dir, strerror(errno));
72                 goto error;
73         }
74
75         /* fork to become!= group leader*/
76         if ((pid=fork())<0){
77                 LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
78                 goto error;
79         }else if (pid!=0){
80                 /* parent process => exit*/
81                 exit(0);
82         }
83         /* become session leader to drop the ctrl. terminal */
84         if (setsid()<0){
85                 LOG(L_WARN, "setsid failed: %s\n",strerror(errno));
86         }else{
87                 own_pgid=1;/* we have our own process group */
88         }
89         /* fork again to drop group  leadership */
90         if ((pid=fork())<0){
91                 LOG(L_CRIT, "Cannot  fork:%s\n", strerror(errno));
92                 goto error;
93         }else if (pid!=0){
94                 /*parent process => exit */
95                 exit(0);
96         }
97
98         /* added by noh: create a pid file for the main process */
99         if (pid_file!=0){
100                 
101                 if ((pid_stream=fopen(pid_file, "r"))!=NULL){
102                         fscanf(pid_stream, "%d", &p);
103                         fclose(pid_stream);
104                         if (p==-1){
105                                 LOG(L_CRIT, "pid file %s exists, but doesn't contain a valid"
106                                         " pid number\n", pid_file);
107                                 goto error;
108                         }
109                         if (kill((pid_t)p, 0)==0 || errno==EPERM){
110                                 LOG(L_CRIT, "running process found in the pid file %s\n",
111                                         pid_file);
112                                 goto error;
113                         }else{
114                                 LOG(L_WARN, "pid file contains old pid, replacing pid\n");
115                         }
116                 }
117                 pid=getpid();
118                 if ((pid_stream=fopen(pid_file, "w"))==NULL){
119                         LOG(L_WARN, "unable to create pid file %s: %s\n", 
120                                 pid_file, strerror(errno));
121                         goto error;
122                 }else{
123                         fprintf(pid_stream, "%i\n", (int)pid);
124                         fclose(pid_stream);
125                 }
126         }
127         
128         /* try to replace stdin, stdout & stderr with /dev/null */
129         if (freopen("/dev/null", "r", stdin)==0){
130                 LOG(L_ERR, "unable to replace stdin with /dev/null: %s\n",
131                                 strerror(errno));
132                 /* continue, leave it open */
133         };
134         if (freopen("/dev/null", "w", stdout)==0){
135                 LOG(L_ERR, "unable to replace stdout with /dev/null: %s\n",
136                                 strerror(errno));
137                 /* continue, leave it open */
138         };
139         /* close stderr only if log_stderr=0 */
140         if ((!log_stderr) &&(freopen("/dev/null", "w", stderr)==0)){
141                 LOG(L_ERR, "unable to replace stderr with /dev/null: %s\n",
142                                 strerror(errno));
143                 /* continue, leave it open */
144         };
145         
146         /* close any open file descriptors */
147         closelog();
148         for (r=3;r<MAX_FD; r++){
149                         close(r);
150         }
151         
152         if (log_stderr==0)
153                 openlog(name, LOG_PID|LOG_CONS, log_facility);
154                 /* LOG_CONS, LOG_PERRROR ? */
155
156         return  0;
157
158 error:
159         return -1;
160 }
161
162
163
164 int do_suid()
165 {
166         if (gid&&(setgid(gid)<0)){
167                 LOG(L_CRIT, "cannot change gid to %d: %s\n", gid, strerror(errno));
168                 goto error;
169         }
170         
171         if(uid&&(setuid(uid)<0)){
172                 LOG(L_CRIT, "cannot change uid to %d: %s\n", uid, strerror(errno));
173                 goto error;
174         }
175         return 0;
176 error:
177         return -1;
178 }
179
180