X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=fedeff7af880a009d938e73087edb7ca6c83f267;hp=1f226265b0c9c79593f255bba4805cfdb8a53e9a;hb=cf47da359caca907d8f0fd8fe9f5f4ddb398b67d;hpb=a181da64ba896c709d61e775606a0b8ebfdd1dde diff --git a/audiod.c b/audiod.c index 1f226265..fedeff7a 100644 --- a/audiod.c +++ b/audiod.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "para.h" #include "error.h" @@ -163,7 +164,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]; @@ -172,6 +173,8 @@ static struct signal_task *signal_task; static struct status_task status_task_struct; +static uid_t *uid_whitelist; + /** * the task that calls the status command of para_server * @@ -306,7 +309,7 @@ static int get_play_time_slot_num(void) */ char *get_time_string(void) { - int ret, seconds = 0, length; + int ret, seconds = 0, length = stat_task->length_seconds; struct timeval *tmp, sum, sss, /* server stream start */ rstime, /* receiver start time */ wstime, /* writer start time */ @@ -318,19 +321,18 @@ char *get_time_string(void) if (audiod_status == AUDIOD_OFF) goto empty; - if (!(stat_task->vss_status & VSS_STATUS_FLAG_PLAYING)) { - if (stat_task->length_seconds) /* paused */ + if (stat_task->server_stream_start.tv_sec == 0) { + if (stat_task->vss_status & VSS_STATUS_FLAG_PLAYING) + goto out; /* server is about to change file */ + if (length > 0) /* paused */ return NULL; goto empty; /* stopped */ } - if (audiod_status == AUDIOD_ON && !s) - goto empty; /* * Valid status items and playing, set length and tmp to the stream * start. We use the slot info and fall back to the info from current * status items if no slot info is available. */ - length = stat_task->length_seconds; tmp = &stat_task->server_stream_start; if (s && s->wns && s->wns[0].btrn) { /* writer active in this slot */ btr_get_node_start(s->wns[0].btrn, &wstime); @@ -349,7 +351,7 @@ char *get_time_string(void) tv_diff(tmp, &stat_task->sa_time_diff, &sss); else tv_add(tmp, &stat_task->sa_time_diff, &sss); - if (!s || !s->wns || !s->wns[0].btrn) { + if (!s || !s->wns || !s->wns[0].btrn || wstime.tv_sec == 0) { struct timeval diff; tv_diff(now, &sss, &diff); seconds = diff.tv_sec + stat_task->offset_seconds; @@ -361,7 +363,8 @@ char *get_time_string(void) if (s->receiver_node->btrn) { btr_get_node_start(s->receiver_node->btrn, &rstime); ret = tv_diff(&rstime, &sss, &rskip); - if (ret > 0) { /* audiod was started in the middle of the stream */ + if (ret > 0 && rskip.tv_sec > 2) { + /* audiod was started in the middle of the stream */ tv_add(&wtime, &rskip, &sum); seconds += sum.tv_sec; } else @@ -390,7 +393,7 @@ empty: static void parse_config_or_die(void) { - int ret; + int ret, i; char *config_file; struct audiod_cmdline_parser_params params = { .override = 0, @@ -410,6 +413,7 @@ static void parse_config_or_die(void) ret = file_exists(config_file); if (conf.config_file_given && !ret) { PARA_EMERG_LOG("can not read config file %s\n", config_file); + free(config_file); goto err; } if (ret) { @@ -417,9 +421,29 @@ static void parse_config_or_die(void) daemon_set_loglevel(conf.loglevel_arg); } free(config_file); + if (conf.user_allow_given > 0) { + uid_whitelist = para_malloc(conf.user_allow_given + * sizeof(uid_t)); + for (i = 0; i < conf.user_allow_given; i++) { + int32_t val; + struct passwd *pw; + ret = para_atoi32(conf.user_allow_arg[i], &val); + if (ret >= 0) { + uid_whitelist[i] = val; + continue; + } + errno = 0; /* see getpwnam(3) */ + pw = getpwnam(conf.user_allow_arg[i]); + if (!pw) { + PARA_EMERG_LOG("invalid username: %s\n", + conf.user_allow_arg[i]); + goto err; + } + uid_whitelist[i] = pw->pw_uid; + } + } return; err: - free(config_file); exit(EXIT_FAILURE); } @@ -501,11 +525,11 @@ static void close_filters(struct slot_info *s) return; for (i = a->num_filters - 1; i >= 0; i--) { struct filter_node *fn = s->fns + i; - struct filter *f; + const struct filter *f; if (!fn) continue; - f = filters + fn->filter_num; + f = filter_get(fn->filter_num); if (f->close) f->close(fn); btr_remove_node(&fn->btrn); @@ -564,7 +588,7 @@ static void open_filters(struct slot_info *s) parent = s->receiver_node->btrn; for (i = 0; i < nf; i++) { char buf[20]; - struct filter *f = filters + a->filter_nums[i]; + const struct filter *f = filter_get(a->filter_nums[i]); fn = s->fns + i; fn->filter_num = a->filter_nums[i]; fn->conf = a->filter_conf[i]; @@ -834,7 +858,7 @@ static int add_filter(int format, char *cmdline) a->filter_conf[nf] = cfg; a->num_filters++; PARA_INFO_LOG("%s filter %d: %s\n", audio_formats[format], nf, - filters[filter_num].name); + filter_get(filter_num)->name); return filter_num; } @@ -969,20 +993,20 @@ static int init_default_filters(void) } /* add "dec" to audio format name */ tmp = make_message("%sdec", audio_formats[i]); - for (j = 0; filters[j].name; j++) - if (!strcmp(tmp, filters[j].name)) + for (j = 0; filter_get(j); j++) + if (!strcmp(tmp, filter_get(j)->name)) break; free(tmp); ret = -E_UNSUPPORTED_FILTER; - if (!filters[j].name) + if (!filter_get(j)) goto out; - tmp = para_strdup(filters[j].name); + tmp = para_strdup(filter_get(j)->name); ret = add_filter(i, tmp); free(tmp); if (ret < 0) goto out; PARA_INFO_LOG("%s -> default filter: %s\n", audio_formats[i], - filters[j].name); + filter_get(j)->name); } out: return ret; @@ -1048,7 +1072,7 @@ static void init_local_sockets(struct command_task *ct) 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_IWOTH); + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (ct->fd[0] >= 0 || ct->fd[1] >= 0) return; PARA_EMERG_LOG("%s\n", para_strerror(-ct->fd[1])); @@ -1206,10 +1230,15 @@ static void close_slot(int slot_num) static void close_unused_slots(void) { int i; + bool dump = false; FOR_EACH_SLOT(i) - if (must_close_slot(i)) + if (must_close_slot(i)) { close_slot(i); + dump = true; + } + if (dump) + audiod_status_dump(true); } /* @@ -1226,6 +1255,7 @@ static void audiod_cleanup(void) close_unused_slots(); audiod_cmdline_parser_free(&conf); close_stat_clients(); + free(uid_whitelist); } /* @@ -1253,6 +1283,7 @@ static void start_stop_decoders(void) open_writers(sl); activate_grab_clients(&sched); btr_log_tree(sl->receiver_node->btrn, LL_NOTICE); + audiod_status_dump(true); } static void status_pre_select(struct sched *s, void *context) @@ -1417,6 +1448,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 * @@ -1449,10 +1503,14 @@ int main(int argc, char *argv[]) writer_init(); if (conf.help_given || conf.detailed_help_given) print_help_and_die(); + 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); @@ -1468,7 +1526,7 @@ int main(int argc, char *argv[]) PARA_EMERG_LOG("%s\n", para_strerror(-ret)); exit(EXIT_FAILURE); } - daemon_log_welcome("para_audiod"); + daemon_log_welcome("audiod"); daemon_set_start_time(); set_initial_status(); FOR_EACH_SLOT(i)