aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/mpdconf.example7
-rw-r--r--src/conf.c1
-rw-r--r--src/conf.h1
-rw-r--r--src/daemon.c48
-rw-r--r--src/daemon.h2
-rw-r--r--src/main.c1
6 files changed, 42 insertions, 18 deletions
diff --git a/doc/mpdconf.example b/doc/mpdconf.example
index 7574ffc87..1dce635b2 100644
--- a/doc/mpdconf.example
+++ b/doc/mpdconf.example
@@ -61,6 +61,13 @@
#
#user "nobody"
#
+# This setting specifies the group that MPD will run as. If not specified
+# primary group of user specified with "user" setting will be used (if set).
+# This is useful if MPD needs to be a member of group such as "audio" to
+# have permission to use sound card.
+#
+#group "nogroup"
+#
# This setting sets the address for the daemon to listen on. Careful attention
# should be paid if this is assigned to anything other then the default, any.
# This setting can deny access to control of the daemon.
diff --git a/src/conf.c b/src/conf.c
index 777cbe6ed..a423b5d2d 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -61,6 +61,7 @@ static struct config_entry config_entries[] = {
{ .name = CONF_PID_FILE, false, false },
{ .name = CONF_STATE_FILE, false, false },
{ .name = CONF_USER, false, false },
+ { .name = CONF_GROUP, false, false },
{ .name = CONF_BIND_TO_ADDRESS, true, false },
{ .name = CONF_PORT, false, false },
{ .name = CONF_LOG_LEVEL, false, false },
diff --git a/src/conf.h b/src/conf.h
index 669542167..fda3a12b9 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -34,6 +34,7 @@
#define CONF_PID_FILE "pid_file"
#define CONF_STATE_FILE "state_file"
#define CONF_USER "user"
+#define CONF_GROUP "group"
#define CONF_BIND_TO_ADDRESS "bind_to_address"
#define CONF_PORT "port"
#define CONF_LOG_LEVEL "log_level"
diff --git a/src/daemon.c b/src/daemon.c
index 33b2953a9..e7fcd0986 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -45,14 +45,17 @@
static char *user_name;
/** the Unix user id which MPD runs as */
-static uid_t user_uid;
+static uid_t user_uid = (uid_t)-1;
/** the Unix group id which MPD runs as */
-static gid_t user_gid;
+static gid_t user_gid = (pid_t)-1;
/** the absolute path of the pidfile */
static char *pidfile;
+/* whether "group" conf. option was given */
+static bool had_group = false;
+
#endif
void
@@ -107,16 +110,19 @@ daemonize_set_user(void)
if (user_name == NULL)
return;
- /* get uid */
- if (setgid(user_gid) == -1) {
- g_error("cannot setgid for user \"%s\": %s",
- user_name, g_strerror(errno));
+ /* set gid */
+ if (user_gid != (gid_t)-1 && user_gid != getgid()) {
+ if (setgid(user_gid) == -1) {
+ g_error("cannot setgid to %d: %s",
+ (int)user_gid, g_strerror(errno));
+ }
}
+
#ifdef _BSD_SOURCE
/* init suplementary groups
* (must be done before we change our uid)
*/
- if (initgroups(user_name, user_gid) == -1) {
+ if (!had_group && initgroups(user_name, user_gid) == -1) {
g_warning("cannot init supplementary groups "
"of user \"%s\": %s",
user_name, g_strerror(errno));
@@ -124,7 +130,8 @@ daemonize_set_user(void)
#endif
/* set uid */
- if (setuid(user_uid) == -1) {
+ if (user_uid != (uid_t)-1 && user_uid != getuid() &&
+ setuid(user_uid) == -1) {
g_error("cannot change to uid of user \"%s\": %s",
user_name, g_strerror(errno));
}
@@ -196,25 +203,32 @@ daemonize(bool detach)
}
void
-daemonize_init(const char *user, const char *_pidfile)
+daemonize_init(const char *user, const char *group, const char *_pidfile)
{
#ifndef WIN32
- if (user != NULL && strcmp(user, g_get_user_name()) != 0) {
- struct passwd *pwd;
-
- user_name = g_strdup(user);
-
- pwd = getpwnam(user_name);
- if (pwd == NULL)
- g_error("no such user \"%s\"", user_name);
+ if (user) {
+ struct passwd *pwd = getpwnam(user);
+ if (!pwd)
+ g_error("no such user \"%s\"", user);
user_uid = pwd->pw_uid;
user_gid = pwd->pw_gid;
+ user_name = g_strdup(user);
+
/* this is needed by libs such as arts */
g_setenv("HOME", pwd->pw_dir, true);
}
+ if (group) {
+ struct group *grp = grp = getgrnam(group);
+ if (!grp)
+ g_error("no such group \"%s\"", group);
+ user_gid = grp->gr_gid;
+ had_group = true;
+ }
+
+
pidfile = g_strdup(_pidfile);
#else
(void)user;
diff --git a/src/daemon.h b/src/daemon.h
index 5b3f9a7dc..46a4c4f71 100644
--- a/src/daemon.h
+++ b/src/daemon.h
@@ -23,7 +23,7 @@
#include <stdbool.h>
void
-daemonize_init(const char *user, const char *pidfile);
+daemonize_init(const char *user, const char *group, const char *pidfile);
void
daemonize_finish(void);
diff --git a/src/main.c b/src/main.c
index 3d0aaabc9..54b31c1f8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -94,6 +94,7 @@ static void
glue_daemonize_init(const struct options *options)
{
daemonize_init(config_get_string(CONF_USER, NULL),
+ config_get_string(CONF_GROUP, NULL),
config_get_path(CONF_PID_FILE));
if (options->kill)