2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <sys/types.h>
41 #define G_LOG_DOMAIN "daemon"
45 /** the Unix user name which MPD runs as */
46 static char *user_name
;
48 /** the Unix user id which MPD runs as */
49 static uid_t user_uid
= (uid_t
)-1;
51 /** the Unix group id which MPD runs as */
52 static gid_t user_gid
= (pid_t
)-1;
54 /** the absolute path of the pidfile */
57 /* whether "group" conf. option was given */
58 static bool had_group
= false;
68 g_error("no pid_file specified in the config file");
70 fp
= fopen(pidfile
, "r");
72 g_error("unable to open pid file \"%s\": %s",
73 pidfile
, g_strerror(errno
));
75 if (fscanf(fp
, "%i", &pid
) != 1) {
76 g_error("unable to read the pid from file \"%s\"",
81 ret
= kill(pid
, SIGTERM
);
83 g_error("unable to kill proccess %i: %s",
84 pid
, g_strerror(errno
));
90 daemonize_close_stdin(void)
93 open("/dev/null", O_RDONLY
);
97 daemonize_set_user(void)
99 if (user_name
== NULL
)
103 if (user_gid
!= (gid_t
)-1 && user_gid
!= getgid()) {
104 if (setgid(user_gid
) == -1) {
105 g_error("cannot setgid to %d: %s",
106 (int)user_gid
, g_strerror(errno
));
111 /* init suplementary groups
112 * (must be done before we change our uid)
114 if (!had_group
&& initgroups(user_name
, user_gid
) == -1) {
115 g_warning("cannot init supplementary groups "
116 "of user \"%s\": %s",
117 user_name
, g_strerror(errno
));
122 if (user_uid
!= (uid_t
)-1 && user_uid
!= getuid() &&
123 setuid(user_uid
) == -1) {
124 g_error("cannot change to uid of user \"%s\": %s",
125 user_name
, g_strerror(errno
));
130 daemonize_detach(void)
132 /* flush all file handles before duplicating the buffers */
139 g_error("daemon() failed: %s", g_strerror(errno
));
141 #elif defined(HAVE_FORK)
143 /* detach from parent process */
147 g_error("fork() failed: %s", g_strerror(errno
));
151 /* exit the parent process */
155 /* release the current working directory */
158 g_error("problems changing to root directory");
160 /* detach from the current session */
165 g_error("no support for daemonizing");
168 g_debug("daemonized!");
172 daemonize(bool detach
)
176 if (pidfile
!= NULL
) {
177 /* do this before daemon'izing so we can fail gracefully if we can't
178 * write to the pid file */
179 g_debug("opening pid file");
180 fp
= fopen(pidfile
, "w+");
182 g_error("could not create pid file \"%s\": %s",
183 pidfile
, g_strerror(errno
));
190 if (pidfile
!= NULL
) {
191 g_debug("writing pid file");
192 fprintf(fp
, "%lu\n", (unsigned long)getpid());
198 daemonize_init(const char *user
, const char *group
, const char *_pidfile
)
201 struct passwd
*pwd
= getpwnam(user
);
203 g_error("no such user \"%s\"", user
);
205 user_uid
= pwd
->pw_uid
;
206 user_gid
= pwd
->pw_gid
;
208 user_name
= g_strdup(user
);
210 /* this is needed by libs such as arts */
211 g_setenv("HOME", pwd
->pw_dir
, true);
215 struct group
*grp
= grp
= getgrnam(group
);
217 g_error("no such group \"%s\"", group
);
218 user_gid
= grp
->gr_gid
;
223 pidfile
= g_strdup(_pidfile
);
227 daemonize_finish(void)