create_local_socket(): Avoid code duplication.
[paraslash.git] / audiod.c
index 6fd101a093b2f7f94abe43cab0331781c8a57a3a..e8a82b5ed254d447b8edc106e0c6f98d2a64d2f7 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -310,17 +310,6 @@ empty:
        return para_strdup(NULL);
 }
 
-static int want_colors(void)
-{
-       if (conf.color_arg == color_arg_no)
-               return 0;
-       if (conf.color_arg == color_arg_yes)
-               return 1;
-       if (conf.logfile_given)
-               return 0;
-       return isatty(STDERR_FILENO);
-}
-
 static void parse_config_or_die(void)
 {
        int ret;
@@ -390,6 +379,7 @@ static void close_receiver(int slot_num)
        task_reap(&s->receiver_node->task);
        free(s->receiver_node);
        s->receiver_node = NULL;
+       stat_task->current_audio_format_num = -1;
        tv_add(now, &(struct timeval)EMBRACE(0, 200 * 1000),
                &a->restart_barrier);
 }
@@ -968,8 +958,7 @@ static int parse_stream_args(void)
 /* does not unlink socket on errors */
 static int audiod_get_socket(void)
 {
-       struct sockaddr_un unix_addr;
-       int ret, fd;
+       int ret;
 
        if (conf.socket_given)
                socket_name = para_strdup(conf.socket_arg);
@@ -982,19 +971,11 @@ static int audiod_get_socket(void)
        PARA_NOTICE_LOG("local socket: %s\n", socket_name);
        if (conf.force_given)
                unlink(socket_name);
-       ret = create_local_socket(socket_name, &unix_addr,
+       ret = create_local_socket(socket_name,
                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH);
        if (ret < 0)
                goto err;
-       fd = ret;
-       if (listen(fd , 5) < 0) {
-               ret = -ERRNO_TO_PARA_ERROR(errno);
-               goto err;
-       }
-       ret = mark_fd_nonblocking(fd);
-       if (ret < 0)
-               goto err;
-       return fd;
+       return ret;
 err:
        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
        exit(EXIT_FAILURE);
@@ -1006,16 +987,22 @@ static void signal_pre_select(struct sched *s, void *context)
        para_fd_set(st->fd, &s->rfds, &s->max_fileno);
 }
 
-static int signal_post_select(struct sched *s, __a_unused void *context)
+static int signal_post_select(struct sched *s, void *context)
 {
-       int signum;
+       struct signal_task *st = context;
+       int ret, signum;
+
+       ret = task_get_notification(st->task);
+       if (ret < 0)
+               return ret;
        signum = para_next_signal(&s->rfds);
        switch (signum) {
        case SIGINT:
        case SIGTERM:
        case SIGHUP:
                PARA_NOTICE_LOG("received signal %d\n", signum);
-               clean_exit(EXIT_FAILURE, "caught deadly signal");
+               task_notify_all(s, E_AUDIOD_SIGNAL);
+               return -E_AUDIOD_SIGNAL;
        }
        return 0;
 }
@@ -1034,10 +1021,17 @@ static int command_post_select(struct sched *s, void *context)
        struct timeval tmp, delay;
        bool force = true;
 
-       ret = handle_connect(ct->fd, &s->rfds);
+       ret = task_get_notification(ct->task);
        if (ret < 0)
+               return ret;
+       ret = handle_connect(ct->fd, &s->rfds);
+       if (ret < 0) {
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-       else if (ret > 0)
+               if (ret == -E_AUDIOD_TERM) {
+                       task_notify_all(s, -ret);
+                       return ret;
+               }
+       } else if (ret > 0)
                goto dump;
 
        /* if last status dump was less than 500ms ago, do nothing */
@@ -1140,19 +1134,13 @@ static void close_unused_slots(void)
                        close_slot(i);
 }
 
-/**
- * Close the connection to para_server and exit.
- *
- * \param status The exit status which is passed to exit(3).
- * \param msg The log message
- *
- * Log \a msg with loglevel \p EMERG, close the connection to para_server and
- * all slots, and call \p exit(status). \a status should be either EXIT_SUCCESS
- * or EXIT_FAILURE.
+/*
+ * Cleanup all resources.
  *
- * \sa exit(3).
+ * This performs various cleanups, removes the audiod socket and closes the
+ * connection to para_server.
  */
-void __noreturn clean_exit(int status, const char *msg)
+static void audiod_cleanup(void)
 {
        if (socket_name)
                unlink(socket_name);
@@ -1160,8 +1148,6 @@ void __noreturn clean_exit(int status, const char *msg)
        close_unused_slots();
        audiod_cmdline_parser_free(&conf);
        close_stat_clients();
-       PARA_EMERG_LOG("%s\n", msg);
-       exit(status);
 }
 
 /*
@@ -1226,7 +1212,11 @@ min_delay:
 static int status_post_select(struct sched *s, void *context)
 {
        struct status_task *st = context;
+       int ret;
 
+       ret = task_get_notification(st->task);
+       if (ret < 0)
+               return ret;
        if (audiod_status == AUDIOD_OFF) {
                if (!st->ct)
                        goto out;
@@ -1241,7 +1231,6 @@ static int status_post_select(struct sched *s, void *context)
        if (st->ct) {
                char *buf;
                size_t sz;
-               int ret;
 
                ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
                if (ret < 0) {
@@ -1350,18 +1339,6 @@ __noreturn static void print_help_and_die(void)
        exit(0);
 }
 
-static void init_colors_or_die(void)
-{
-       int i;
-
-       if (!want_colors())
-               return;
-       daemon_set_default_log_colors();
-       daemon_set_flag(DF_COLOR_LOG);
-       for (i = 0; i < conf.log_color_given; i++)
-               daemon_set_log_color_or_die(conf.log_color_arg[i]);
-}
-
 /**
  * the main function of para_audiod
  *
@@ -1394,9 +1371,10 @@ int main(int argc, char *argv[])
        writer_init();
        if (conf.help_given || conf.detailed_help_given)
                print_help_and_die();
-       drop_privileges_or_die(conf.user_arg, conf.group_arg);
+       daemon_drop_privileges_or_die(conf.user_arg, conf.group_arg);
        parse_config_or_die();
-       init_colors_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);
        init_random_seed_or_die();
        daemon_set_flag(DF_LOG_TIME);
        daemon_set_flag(DF_LOG_HOSTNAME);
@@ -1412,8 +1390,8 @@ int main(int argc, char *argv[])
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
                exit(EXIT_FAILURE);
        }
-       log_welcome("para_audiod");
-       set_server_start_time(NULL);
+       daemon_log_welcome("para_audiod");
+       daemon_set_start_time();
        set_initial_status();
        FOR_EACH_SLOT(i)
                clear_slot(i);
@@ -1435,8 +1413,10 @@ int main(int argc, char *argv[])
        sched.default_timeout.tv_sec = 2;
        sched.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&sched);
+       audiod_cleanup();
        sched_shutdown(&sched);
 
-       PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-       return EXIT_FAILURE;
+       if (ret < 0)
+               PARA_EMERG_LOG("%s\n", para_strerror(-ret));
+       return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
 }