Merge branch 'refs/heads/t/rm_as_compat'
[paraslash.git] / audiod.c
index 2f9d5da3dbd6cc486dcc468d55bbbda7b0b41b6e..254bcb8d8c4bac2947e52c3310fb7051fe5f1153 100644 (file)
--- a/audiod.c
+++ b/audiod.c
 #include "signal.h"
 #include "version.h"
 
+/** Array of error strings. */
+DEFINE_PARA_ERRLIST;
+
 __printf_2_3 void (*para_log)(int, const char*, ...) = daemon_log;
-/** define the array of error lists needed by para_audiod */
-INIT_AUDIOD_ERRLISTS;
 /** define the array containing all supported audio formats */
 const char *audio_formats[] = {AUDIOD_AUDIO_FORMAT_ARRAY NULL};
 
@@ -164,7 +165,7 @@ int audiod_status = AUDIOD_ON;
  * the gengetopt args_info struct that holds information on all command line
  * arguments
  */
-struct audiod_args_info conf;
+static struct audiod_args_info conf;
 
 static char *socket_name;
 static struct audio_format_info afi[NUM_AUDIO_FORMATS];
@@ -182,22 +183,9 @@ static uid_t *uid_whitelist;
  */
 static struct status_task *stat_task = &status_task_struct;
 
-/*
- * The task for handling audiod commands.
- *
- * We need two listening sockets for backward compability: on Linux systems
- * fd[0] is an abstract socket (more precisely, a socket bound to an address in
- * the abstract namespace), and fd[1] is the usual pathname socket. On other
- * systems, fd[0] is negative, and only the pathname socket is used.
- *
- * For 0.5.x we accept connections on both sockets to make sure that old
- * para_audioc versions can still connect. New versions use only the abstract
- * socket. Hence after v0.6.0 we can go back to a single socket, either an
- * abstract one (Linux) or a pathname socket (all other systems).
- */
 struct command_task {
-       /** The local listening sockets. */
-       int fd[2];
+       /** The local listening socket. */
+       int fd;
        /** the associated task structure */
        struct task *task;
 };
@@ -596,7 +584,8 @@ static void open_filters(struct slot_info *s)
                        EMBRACE(.name = f->name, .parent = parent,
                                .handler = f->execute, .context = fn));
 
-               f->open(fn);
+               if (f->open)
+                       f->open(fn);
                sprintf(buf, "%s (slot %d)", f->name, (int)(s - slot));
                fn->task = task_register(&(struct task_info) {
                        .name = buf,
@@ -763,7 +752,7 @@ static void compute_time_diff(const struct timeval *status_time)
        if (count > 5) {
                int s = tv_diff(&diff, &stat_task->sa_time_diff, &tmp);
                if (tv_diff(&max_deviation, &tmp, NULL) < 0)
-                       PARA_WARNING_LOG("time diff jump: %lims\n",
+                       PARA_WARNING_LOG("time diff jump: %lums\n",
                                s * tv2ms(&tmp));
        }
        count++;
@@ -1057,7 +1046,7 @@ static int parse_stream_args(void)
 }
 
 /* does not unlink socket on errors */
-static void init_local_sockets(struct command_task *ct)
+static void init_local_socket(struct command_task *ct)
 {
        if (conf.socket_given)
                socket_name = para_strdup(conf.socket_arg);
@@ -1070,12 +1059,10 @@ static void init_local_sockets(struct command_task *ct)
        PARA_NOTICE_LOG("local socket: %s\n", socket_name);
        if (conf.force_given)
                unlink(socket_name);
-       ct->fd[0] = create_local_socket(socket_name, 0);
-       ct->fd[1] = create_local_socket(socket_name,
-               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
-       if (ct->fd[0] >= 0 || ct->fd[1] >= 0)
+       ct->fd = create_local_socket(socket_name);
+       if (ct->fd >= 0)
                return;
-       PARA_EMERG_LOG("%s\n", para_strerror(-ct->fd[1]));
+       PARA_EMERG_LOG("%s\n", para_strerror(-ct->fd));
        exit(EXIT_FAILURE);
 }
 
@@ -1102,16 +1089,12 @@ static int signal_post_select(struct sched *s, void *context)
 static void command_pre_select(struct sched *s, void *context)
 {
        struct command_task *ct = context;
-       int i;
-
-       for (i = 0; i < 2; i++)
-               if (ct->fd[i] >= 0)
-                       para_fd_set(ct->fd[i], &s->rfds, &s->max_fileno);
+       para_fd_set(ct->fd, &s->rfds, &s->max_fileno);
 }
 
 static int command_post_select(struct sched *s, void *context)
 {
-       int ret, i;
+       int ret;
        struct command_task *ct = context;
        static struct timeval last_status_dump;
        struct timeval tmp, delay;
@@ -1120,19 +1103,15 @@ static int command_post_select(struct sched *s, void *context)
        ret = task_get_notification(ct->task);
        if (ret < 0)
                return ret;
-       for (i = 0; i < 2; i++) {
-               if (ct->fd[i] < 0)
-                       continue;
-               ret = handle_connect(ct->fd[i], &s->rfds, uid_whitelist);
-               if (ret < 0) {
-                       PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-                       if (ret == -E_AUDIOD_TERM) {
-                               task_notify_all(s, -ret);
-                               return ret;
-                       }
-               } else if (ret > 0)
-                       force = true;
-       }
+       ret = handle_connect(ct->fd, &s->rfds);
+       if (ret < 0) {
+               PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+               if (ret == -E_AUDIOD_TERM) {
+                       task_notify_all(s, -ret);
+                       return ret;
+               }
+       } else if (ret > 0)
+               force = true;
        if (force == true)
                goto dump;
 
@@ -1160,7 +1139,7 @@ dump:
 
 static void init_command_task(struct command_task *ct)
 {
-       init_local_sockets(ct); /* doesn't return on errors */
+       init_local_socket(ct); /* doesn't return on errors */
 
        ct->task = task_register(&(struct task_info) {
                .name = "command",
@@ -1377,7 +1356,7 @@ static int status_post_select(struct sched *s, void *context)
        if (st->clock_diff_count) { /* get status only one time */
                char *argv[] = {"audiod", "--", "stat", "-p", "-n=1", NULL};
                int argc = 5;
-               PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count);
+               PARA_INFO_LOG("clock diff count: %u\n", st->clock_diff_count);
                st->clock_diff_count--;
                client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s);
                set_stat_task_restart_barrier(2);
@@ -1448,6 +1427,29 @@ __noreturn static void print_help_and_die(void)
        exit(0);
 }
 
+/**
+ * Lookup the given UID in the whitelist.
+ *
+ * The whitelist is the array of arguments to the --user-allow opion. If the
+ * option was not given, the array is empty, in which case the check succeeds.
+ *
+ * \param uid User ID to look up.
+ *
+ * \return True if --user-allow was not given, or if uid matches an element of
+ * the whitelist.
+ */
+bool uid_is_whitelisted(uid_t uid)
+{
+       int i;
+
+       if (!conf.user_allow_given)
+               return true;
+       for (i = 0; i < conf.user_allow_given; i++)
+               if (uid == uid_whitelist[i])
+                       return true;
+       return false;
+}
+
 /**
  * the main function of para_audiod
  *
@@ -1483,8 +1485,11 @@ int main(int argc, char *argv[])
        daemon_set_priority(conf.priority_arg);
        daemon_drop_privileges_or_die(conf.user_arg, conf.group_arg);
        parse_config_or_die();
-       daemon_init_colors_or_die(conf.color_arg, color_arg_auto, color_arg_no,
-               conf.logfile_given, conf.log_color_arg, conf.log_color_given);
+       if (daemon_init_colors_or_die(conf.color_arg, color_arg_auto, color_arg_no,
+               conf.logfile_given)) {
+                       for (i = 0; i < conf.log_color_given; i++)
+                               daemon_set_log_color_or_die(conf.log_color_arg[i]);
+       }
        init_random_seed_or_die();
        daemon_set_flag(DF_LOG_TIME);
        daemon_set_flag(DF_LOG_HOSTNAME);