X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=181d6ab12e6370a4e0df6b661ce20132d6036e78;hp=5909859be6384604513185afebbe35e7152e27be;hb=fc8dfbb416ff07cca08fbf4e13efcaa25e17cc54;hpb=3fd8d0567ae654aed7e97e832568d3e1b98e20a2 diff --git a/audiod.c b/audiod.c index 5909859b..181d6ab1 100644 --- a/audiod.c +++ b/audiod.c @@ -15,7 +15,9 @@ #include #include #include +#include +#include "recv_cmd.lsg.h" #include "para.h" #include "error.h" #include "crypt.h" @@ -39,20 +41,19 @@ #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}; -DEFINE_RECEIVER_ARRAY; - /** Defines how audiod handles one supported audio format. */ struct audio_format_info { - /** pointer to the receiver for this audio format */ - struct receiver *receiver; - /** the receiver configuration */ - void *receiver_conf; + /** the receiver for this audio format */ + int receiver_num; + /** Parsed receiver command line. */ + struct lls_parse_result *receiver_lpr; /** the number of filters that should be activated for this audio format */ unsigned int num_filters; /** Array of filter numbers to be activated. */ @@ -87,6 +88,9 @@ struct slot_info { struct writer_node *wns; }; +#define RECEIVER_CMD(_a) lls_cmd((_a)->receiver_num, recv_cmd_suite) +#define RECEIVER(_a) ((const struct receiver *)lls_user_data(RECEIVER_CMD(_a))) + /** Maximal number of simultaneous instances. */ #define MAX_STREAM_SLOTS 5 @@ -164,7 +168,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]; @@ -475,7 +479,7 @@ static void close_receiver(int slot_num) a = &afi[s->format]; PARA_NOTICE_LOG("closing %s receiver in slot %d\n", audio_formats[s->format], slot_num); - a->receiver->close(s->receiver_node); + RECEIVER(a)->close(s->receiver_node); btr_remove_node(&s->receiver_node->btrn); task_reap(&s->receiver_node->task); free(s->receiver_node); @@ -596,7 +600,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, @@ -636,7 +641,8 @@ static int open_receiver(int format) struct audio_format_info *a = &afi[format]; struct slot_info *s; int ret, slot_num; - struct receiver *r = a->receiver; + const struct receiver *r = RECEIVER(a); + const char *name = lls_command_name(RECEIVER_CMD(a)); struct receiver_node *rn; tv_add(now, &(struct timeval)EMBRACE(2, 0), &a->restart_barrier); @@ -646,9 +652,9 @@ static int open_receiver(int format) slot_num = ret; rn = para_calloc(sizeof(*rn)); rn->receiver = r; - rn->conf = a->receiver_conf; + rn->lpr = a->receiver_lpr; rn->btrn = btr_new_node(&(struct btr_node_description) - EMBRACE(.name = r->name, .context = rn)); + EMBRACE(.name = name, .context = rn)); ret = r->open(rn); if (ret < 0) { btr_remove_node(&rn->btrn); @@ -659,9 +665,9 @@ static int open_receiver(int format) s->format = format; s->receiver_node = rn; PARA_NOTICE_LOG("started %s: %s receiver in slot %d\n", - audio_formats[format], r->name, slot_num); + audio_formats[format], name, slot_num); rn->task = task_register(&(struct task_info) { - .name = r->name, + .name = name, .pre_select = r->pre_select, .post_select = r->post_select, .context = rn, @@ -763,7 +769,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++; @@ -824,7 +830,7 @@ static int update_item(int itemnum, char *buf) return 1; } -static int parse_stream_command(const char *txt, char **cmd) +static int parse_stream_command(const char *txt, const char **cmd) { int ret, len; char *re, *p = strchr(txt, ':'); @@ -841,7 +847,7 @@ static int parse_stream_command(const char *txt, char **cmd) return ret; } -static int add_filter(int format, char *cmdline) +static int add_filter(int format, const char *cmdline) { struct audio_format_info *a = &afi[format]; int filter_num, nf = a->num_filters; @@ -865,7 +871,7 @@ static int add_filter(int format, char *cmdline) static int parse_writer_args(void) { int i, ret; - char *cmd; + const char *cmd; struct audio_format_info *a; for (i = 0; i < conf.writer_given; i++) { @@ -912,12 +918,13 @@ static int parse_writer_args(void) static int parse_receiver_args(void) { - int i, ret, receiver_num; - char *cmd = NULL; + int i, ret; + const char *arg; struct audio_format_info *a; + FOR_EACH_AUDIO_FORMAT(i) + afi[i].receiver_num = -1; for (i = conf.receiver_given - 1; i >= 0; i--) { - char *arg; int j, af_mask; ret = parse_stream_command(conf.receiver_arg[i], &arg); @@ -934,37 +941,27 @@ static int parse_receiver_args(void) * config here. Since we are iterating backwards, the winning * receiver arg is in fact the first one given. */ - if (a->receiver_conf) - a->receiver->free_config(a->receiver_conf); - a->receiver_conf = check_receiver_arg(arg, &receiver_num); - ret = -E_RECV_SYNTAX; - if (!a->receiver_conf) - goto out; - a->receiver = receivers + receiver_num; + lls_free_parse_result(a->receiver_lpr, RECEIVER_CMD(a)); + a->receiver_num = check_receiver_arg(arg, &a->receiver_lpr); } } /* - * Use the first available receiver with no arguments for those audio - * formats for which no receiver was specified. + * Use the default receiver for those audio formats for which no + * receiver was specified. */ - cmd = para_strdup(receivers[0].name); FOR_EACH_AUDIO_FORMAT(i) { - a = &afi[i]; - if (a->receiver_conf) + a = afi + i; + if (a->receiver_num >= 0) continue; - a->receiver_conf = check_receiver_arg(cmd, &receiver_num); - if (!a->receiver_conf) - return -E_RECV_SYNTAX; - a->receiver = &receivers[receiver_num]; + a->receiver_num = check_receiver_arg(NULL, &a->receiver_lpr); } FOR_EACH_AUDIO_FORMAT(i) { a = afi + i; PARA_INFO_LOG("receiving %s streams via %s receiver\n", - audio_formats[i], a->receiver->name); + audio_formats[i], lls_command_name(RECEIVER_CMD(a))); } ret = 1; out: - free(cmd); return ret; } @@ -974,6 +971,7 @@ static int init_default_filters(void) FOR_EACH_AUDIO_FORMAT(i) { struct audio_format_info *a = &afi[i]; + const char *name = lls_command_name(RECEIVER_CMD(a)); char *tmp; int j; @@ -983,8 +981,7 @@ static int init_default_filters(void) * udp and dccp streams are fec-encoded, so add fecdec as the * first filter. */ - if (strcmp(afi[i].receiver->name, "udp") == 0 || - strcmp(afi[i].receiver->name, "dccp") == 0) { + if (strcmp(name, "udp") == 0 || strcmp(name, "dccp") == 0) { tmp = para_strdup("fecdec"); add_filter(i, tmp); free(tmp); @@ -1017,7 +1014,7 @@ static int parse_filter_args(void) int i, j, ret, af_mask, num_matches; for (i = 0; i < conf.filter_given; i++) { - char *arg; + const char *arg; ret = parse_stream_command(conf.filter_arg[i], &arg); if (ret < 0) goto out; @@ -1072,7 +1069,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])); @@ -1123,7 +1120,7 @@ static int command_post_select(struct sched *s, void *context) for (i = 0; i < 2; i++) { if (ct->fd[i] < 0) continue; - ret = handle_connect(ct->fd[i], &s->rfds, uid_whitelist); + ret = handle_connect(ct->fd[i], &s->rfds); if (ret < 0) { PARA_ERROR_LOG("%s\n", para_strerror(-ret)); if (ret == -E_AUDIOD_TERM) { @@ -1377,7 +1374,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 +1445,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 +1503,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);