X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=a5a774376b37c50eba92a76a02b1389bd6df67f4;hp=56ab0c9a0c86608a8b78909f40794b62ac99bcbf;hb=4fb6bf35f5dd6bfcafc0b90e83d4d9084da38365;hpb=56330d8f7795979211591bb54273c59beeb45327 diff --git a/audiod.c b/audiod.c index 56ab0c9a..a5a77437 100644 --- a/audiod.c +++ b/audiod.c @@ -1,8 +1,4 @@ -/* - * Copyright (C) 2005 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2005 Andre Noll , see file COPYING. */ /** \file audiod.c The paraslash's audio daemon. */ @@ -17,15 +13,14 @@ #include #include +#include "audiod.lsg.h" #include "recv_cmd.lsg.h" -#include "client.lsg.h" #include "para.h" #include "error.h" +#include "lsu.h" #include "crypt.h" -#include "audiod.cmdline.h" #include "list.h" #include "sched.h" -#include "ggo.h" #include "buffer_tree.h" #include "recv.h" #include "filter.h" @@ -37,13 +32,21 @@ #include "string.h" #include "fd.h" #include "write.h" -#include "write_common.h" #include "signal.h" #include "version.h" /** Array of error strings. */ DEFINE_PARA_ERRLIST; +static struct lls_parse_result *lpr; +#define CMD_PTR (lls_cmd(0, audiod_suite)) +#define OPT_RESULT(_name) (lls_opt_result(LSG_AUDIOD_PARA_AUDIOD_OPT_ ## _name, lpr)) +#define OPT_GIVEN(_name) (lls_opt_given(OPT_RESULT(_name))) +#define OPT_STRING_VAL(_name) (lls_string_val(0, OPT_RESULT(_name))) +#define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name))) +#define ENUM_STRING_VAL(_name) (lls_enum_string_val(OPT_UINT32_VAL(_name), \ + lls_opt(LSG_AUDIOD_PARA_AUDIOD_OPT_ ## _name, CMD_PTR))) + __printf_2_3 void (*para_log)(int, const char*, ...) = daemon_log; /** define the array containing all supported audio formats */ const char *audio_formats[] = {AUDIOD_AUDIO_FORMAT_ARRAY NULL}; @@ -60,12 +63,14 @@ struct audio_format_info { unsigned *filter_nums; /** Pointer to the array of filter configurations. */ void **filter_conf; + /** Parsed filter command line, one parse result per filter. */ + struct lls_parse_result **filter_lpr; /** the number of filters that should be activated for this audio format */ unsigned int num_writers; - /** Array of writer numbers to be activated. */ - int *writer_nums; - /** pointer to the array of writer configurations */ - void **writer_conf; + /** Array of writer IDs to be activated. */ + int *wids; + /** Parsed writer command line(s) */ + struct lls_parse_result **writer_lpr; /** do not start receiver/filters/writer before this time */ struct timeval restart_barrier; }; @@ -101,9 +106,7 @@ struct slot_info { * para_audiod uses \p MAX_STREAM_SLOTS different slots, each of which may * be associated with a receiver/filter/writer triple. This array holds all * information on the status of these slots. - * - * \sa struct slot_info - * */ + */ struct slot_info slot[MAX_STREAM_SLOTS]; /** The vss status flags audiod is interested in. */ @@ -159,54 +162,32 @@ struct status_task { char *stat_item_values[NUM_STAT_ITEMS] = {NULL}; /** - * the current mode of operation of which can be changed by the on/off/cycle - * commands. It is either, AUDIOD_OFF, AUDIOD_ON or AUDIOD_STANDBY. + * The current mode of operation (AUDIOD_OFF, AUDIOD_ON or AUDIOD_STANDBY). + * Set by the on/off/cycle commands. */ int audiod_status = AUDIOD_ON; -/** - * the gengetopt args_info struct that holds information on all command line - * arguments - */ -static struct audiod_args_info conf; - static char *socket_name; static struct audio_format_info afi[NUM_AUDIO_FORMATS]; - 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 + * The task that calls the status command of para_server. * - * \sa struct status_task + * \sa \ref struct status_task. */ 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 associated task structure */ + /** The local listening socket. */ + int fd; + /** The associated task structure. */ struct task *task; }; -/** iterate over all supported audio formats */ +/** Iterate over all supported audio formats. */ #define FOR_EACH_AUDIO_FORMAT(af) for (af = 0; af < NUM_AUDIO_FORMATS; af++) /** @@ -321,6 +302,7 @@ char *get_time_string(void) rskip; /* receiver start - sss */ int slot_num = get_play_time_slot_num(); struct slot_info *s = slot_num < 0? NULL : &slot[slot_num]; + bool writer_active = s && s->wns && s->wns[0].btrn; char *msg; if (audiod_status == AUDIOD_OFF) @@ -334,11 +316,11 @@ char *get_time_string(void) } /* * 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. + * start. We use the writer start time from the slot info and fall back + * to the info from current status items if no writer is active yet. */ tmp = &stat_task->server_stream_start; - if (s && s->wns && s->wns[0].btrn) { /* writer active in this slot */ + if (writer_active) { btr_get_node_start(s->wns[0].btrn, &wstime); if (wstime.tv_sec != 0) { /* writer wrote something */ if (s->server_stream_start.tv_sec == 0) { @@ -355,7 +337,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 || wstime.tv_sec == 0) { + if (!writer_active) { struct timeval diff; tv_diff(now, &sss, &diff); seconds = diff.tv_sec + stat_task->offset_seconds; @@ -397,58 +379,37 @@ empty: static void parse_config_or_die(void) { - int ret, i; - char *config_file; - struct audiod_cmdline_parser_params params = { - .override = 0, - .initialize = 0, - .check_required = 1, - .check_ambiguity = 0, - .print_errors = 1 - }; - - if (conf.config_file_given) - config_file = para_strdup(conf.config_file_arg); - else { - char *home = para_homedir(); - config_file = make_message("%s/.paraslash/audiod.conf", home); - free(home); - } - 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) { - audiod_cmdline_parser_config_file(config_file, &conf, ¶ms); - daemon_set_loglevel(conf.loglevel_arg); + int i, ret; + uint32_t n; + + ret = lsu_merge_config_file_options(OPT_STRING_VAL(CONFIG_FILE), + "audiod.conf", &lpr, CMD_PTR, audiod_suite, 0U /* flags */); + if (ret < 0) { + PARA_EMERG_LOG("failed to parse config file: %s\n", + para_strerror(-ret)); + exit(EXIT_FAILURE); } - 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; + daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL)); + n = OPT_GIVEN(USER_ALLOW); + if (n == 0) + return; + uid_whitelist = para_malloc(n * sizeof(uid_t)); + for (i = 0; i < n; i++) { + const char *arg = lls_string_val(i, OPT_RESULT(USER_ALLOW)); + int32_t val; + struct passwd *pw; + ret = para_atoi32(arg, &val); + if (ret >= 0) { + uid_whitelist[i] = val; + continue; + } + pw = getpwnam(arg); + if (!pw) { + PARA_EMERG_LOG("invalid username: %s\n", arg); + exit(EXIT_FAILURE); } + uid_whitelist[i] = pw->pw_uid; } - return; -err: - exit(EXIT_FAILURE); } static void setup_signal_handling(void) @@ -491,13 +452,10 @@ static void close_receiver(int slot_num) static void writer_cleanup(struct writer_node *wn) { - struct writer *w; - if (!wn) return; - w = writers + wn->writer_num; - PARA_INFO_LOG("closing %s\n", writer_names[wn->writer_num]); - w->close(wn); + PARA_INFO_LOG("closing %s\n", writer_name(wn->wid)); + writer_get(wn->wid)->close(wn); btr_remove_node(&wn->btrn); task_reap(&wn->task); } @@ -592,17 +550,20 @@ static void open_filters(struct slot_info *s) parent = s->receiver_node->btrn; for (i = 0; i < nf; i++) { char buf[20]; + const char *name; 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]; + fn->lpr = a->filter_lpr[i]; + name = filter_name(fn->filter_num); fn->btrn = btr_new_node(&(struct btr_node_description) - EMBRACE(.name = f->name, .parent = parent, + EMBRACE(.name = name, .parent = parent, .handler = f->execute, .context = fn)); if (f->open) f->open(fn); - sprintf(buf, "%s (slot %d)", f->name, (int)(s - slot)); + sprintf(buf, "%s (slot %d)", name, (int)(s - slot)); fn->task = task_register(&(struct task_info) { .name = buf, .pre_select = f->pre_select, @@ -611,7 +572,7 @@ static void open_filters(struct slot_info *s) }, &sched); parent = fn->btrn; PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n", - audio_formats[s->format], i, nf, f->name, (int)(s - slot)); + audio_formats[s->format], i, nf, name, (int)(s - slot)); } } @@ -627,11 +588,11 @@ static void open_writers(struct slot_info *s) * sizeof(struct writer_node)); for (i = 0; i < a->num_writers; i++) { wn = s->wns + i; - wn->conf = a->writer_conf[i]; - wn->writer_num = a->writer_nums[i]; + wn->wid = a->wids[i]; + wn->lpr = a->writer_lpr[i]; register_writer_node(wn, parent, &sched); PARA_NOTICE_LOG("%s writer started in slot %d\n", - writer_names[a->writer_nums[i]], (int)(s - slot)); + writer_name(a->wids[i]), (int)(s - slot)); } } @@ -657,6 +618,7 @@ static int open_receiver(int format) EMBRACE(.name = name, .context = rn)); ret = r->open(rn); if (ret < 0) { + PARA_ERROR_LOG("could not open %s receiver\n", name); btr_remove_node(&rn->btrn); free(rn); return ret; @@ -792,38 +754,38 @@ static int update_item(int itemnum, char *buf) { long unsigned sec, usec; - if (stat_task->clock_diff_count && itemnum != SI_CURRENT_TIME) + if (stat_task->clock_diff_count && itemnum != SI_current_time) return 1; free(stat_item_values[itemnum]); stat_item_values[itemnum] = para_strdup(buf); stat_client_write_item(itemnum); switch (itemnum) { - case SI_STATUS_FLAGS: + case SI_status_flags: stat_task->vss_status = 0; if (strchr(buf, 'N')) stat_task->vss_status |= VSS_STATUS_FLAG_NEXT; if (strchr(buf, 'P')) stat_task->vss_status |= VSS_STATUS_FLAG_PLAYING; break; - case SI_OFFSET: + case SI_offset: stat_task->offset_seconds = atoi(buf); break; - case SI_SECONDS_TOTAL: + case SI_seconds_total: stat_task->length_seconds = atoi(buf); break; - case SI_STREAM_START: + case SI_stream_start: if (sscanf(buf, "%lu.%lu", &sec, &usec) == 2) { stat_task->server_stream_start.tv_sec = sec; stat_task->server_stream_start.tv_usec = usec; } break; - case SI_CURRENT_TIME: + case SI_current_time: if (sscanf(buf, "%lu.%lu", &sec, &usec) == 2) { struct timeval tv = {sec, usec}; compute_time_diff(&tv); } break; - case SI_FORMAT: + case SI_format: stat_task->current_audio_format_num = get_audio_format_num(buf); } @@ -852,19 +814,22 @@ static int add_filter(int format, const char *cmdline) struct audio_format_info *a = &afi[format]; int filter_num, nf = a->num_filters; void *cfg; + struct lls_parse_result *flpr; - filter_num = check_filter_arg(cmdline, &cfg); - if (filter_num < 0) - return filter_num; + filter_num = filter_setup(cmdline, &cfg, &flpr); + a->filter_lpr = para_realloc(a->filter_lpr, + (nf + 1) * sizeof(flpr)); a->filter_conf = para_realloc(a->filter_conf, (nf + 1) * sizeof(void *)); a->filter_nums = para_realloc(a->filter_nums, (nf + 1) * sizeof(unsigned)); + a->filter_nums[nf] = filter_num; a->filter_conf[nf] = cfg; + a->filter_lpr[nf] = flpr; a->num_filters++; PARA_INFO_LOG("%s filter %d: %s\n", audio_formats[format], nf, - filter_get(filter_num)->name); + filter_name(filter_num)); return filter_num; } @@ -874,11 +839,11 @@ static int parse_writer_args(void) const char *cmd; struct audio_format_info *a; - for (i = 0; i < conf.writer_given; i++) { - void *wconf; - int j, nw, writer_num, af_mask; + for (i = 0; i < OPT_GIVEN(WRITER); i++) { + int j, nw, af_mask; - ret = parse_stream_command(conf.writer_arg[i], &cmd); + ret = parse_stream_command(lls_string_val(i, + OPT_RESULT(WRITER)), &cmd); if (ret < 0) return ret; af_mask = ret; @@ -886,32 +851,28 @@ static int parse_writer_args(void) a = afi + j; if ((af_mask & (1 << j)) == 0) /* no match */ continue; - wconf = check_writer_arg_or_die(cmd, &writer_num); nw = a->num_writers; - a->writer_nums = para_realloc(a->writer_nums, (nw + 1) * sizeof(int)); - a->writer_conf = para_realloc(a->writer_conf, (nw + 1) * sizeof(void *)); - a->writer_nums[nw] = writer_num; - a->writer_conf[nw] = wconf; + a->wids = para_realloc(a->wids, (nw + 1) * sizeof(int)); + a->writer_lpr = para_realloc(a->writer_lpr, + (nw + 1) * sizeof(struct lls_parse_result *)); + a->wids[nw] = check_writer_arg_or_die(cmd, + a->writer_lpr + nw); PARA_INFO_LOG("%s writer #%d: %s\n", audio_formats[j], - nw, writer_names[writer_num]); + nw, writer_name(a->wids[nw])); a->num_writers++; } } /* Use default writer for audio formats which are not yet set up. */ FOR_EACH_AUDIO_FORMAT(i) { - void *writer_conf; - int writer_num; a = afi + i; if (a->num_writers > 0) continue; /* already set up */ - writer_conf = check_writer_arg_or_die(NULL, &writer_num); - a->writer_nums = para_malloc(sizeof(int)); - a->writer_nums[0] = writer_num; - a->writer_conf = para_malloc(sizeof(void *)); - a->writer_conf[0] = writer_conf; a->num_writers = 1; + a->wids = para_malloc(sizeof(int)); + a->writer_lpr = para_malloc(sizeof(struct lls_parse_result *)); + a->wids[0] = check_writer_arg_or_die(NULL, a->writer_lpr); PARA_INFO_LOG("%s writer: %s (default)\n", audio_formats[i], - writer_names[writer_num]); + writer_name(a->wids[0])); } return 1; } @@ -924,10 +885,11 @@ static int parse_receiver_args(void) FOR_EACH_AUDIO_FORMAT(i) afi[i].receiver_num = -1; - for (i = conf.receiver_given - 1; i >= 0; i--) { + for (i = OPT_GIVEN(RECEIVER) - 1; i >= 0; i--) { int j, af_mask; - ret = parse_stream_command(conf.receiver_arg[i], &arg); + ret = parse_stream_command(lls_string_val(i, + OPT_RESULT(RECEIVER)), &arg); if (ret < 0) goto out; af_mask = ret; @@ -990,20 +952,20 @@ static int init_default_filters(void) } /* add "dec" to audio format name */ tmp = make_message("%sdec", audio_formats[i]); - for (j = 0; filter_get(j); j++) - if (!strcmp(tmp, filter_get(j)->name)) + for (j = 1; filter_get(j); j++) + if (!strcmp(tmp, filter_name(j))) break; free(tmp); ret = -E_UNSUPPORTED_FILTER; if (!filter_get(j)) goto out; - tmp = para_strdup(filter_get(j)->name); + tmp = para_strdup(filter_name(j)); ret = add_filter(i, tmp); free(tmp); if (ret < 0) goto out; PARA_INFO_LOG("%s -> default filter: %s\n", audio_formats[i], - filter_get(j)->name); + filter_name(j)); } out: return ret; @@ -1013,9 +975,10 @@ static int parse_filter_args(void) { int i, j, ret, af_mask, num_matches; - for (i = 0; i < conf.filter_given; i++) { + for (i = 0; i < OPT_GIVEN(FILTER); i++) { const char *arg; - ret = parse_stream_command(conf.filter_arg[i], &arg); + ret = parse_stream_command(lls_string_val(i, + OPT_RESULT(FILTER)), &arg); if (ret < 0) goto out; af_mask = ret; @@ -1030,7 +993,7 @@ static int parse_filter_args(void) } if (num_matches == 0) PARA_WARNING_LOG("ignoring filter spec: %s\n", - conf.filter_arg[i]); + lls_string_val(i, OPT_RESULT(FILTER))); } ret = init_default_filters(); /* use default values for the rest */ out: @@ -1054,10 +1017,10 @@ 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); + if (OPT_GIVEN(SOCKET)) + socket_name = para_strdup(OPT_STRING_VAL(SOCKET)); else { char *hn = para_hostname(); socket_name = make_message("/var/paraslash/audiod_socket.%s", @@ -1065,14 +1028,12 @@ static void init_local_sockets(struct command_task *ct) free(hn); } PARA_NOTICE_LOG("local socket: %s\n", socket_name); - if (conf.force_given) + if (OPT_GIVEN(FORCE)) 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); } @@ -1099,16 +1060,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; @@ -1117,19 +1074,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); - 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; @@ -1157,7 +1110,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", @@ -1250,7 +1203,6 @@ static void audiod_cleanup(void) unlink(socket_name); close_stat_pipe(); close_unused_slots(); - audiod_cmdline_parser_free(&conf); close_stat_clients(); free(uid_whitelist); } @@ -1331,7 +1283,7 @@ static int status_post_select(struct sched *s, void *context) goto out; } close_stat_pipe(); - st->clock_diff_count = conf.clock_diff_count_arg; + st->clock_diff_count = OPT_UINT32_VAL(CLOCK_DIFF_COUNT); goto out; } if (st->ct) { @@ -1385,10 +1337,10 @@ static int status_post_select(struct sched *s, void *context) client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s); set_stat_task_restart_barrier(5); } - free(stat_item_values[SI_BASENAME]); - stat_item_values[SI_BASENAME] = para_strdup( + free(stat_item_values[SI_basename]); + stat_item_values[SI_basename] = para_strdup( "no connection to para_server"); - stat_client_write_item(SI_BASENAME); + stat_client_write_item(SI_basename); st->last_status_read = *now; out: start_stop_decoders(); @@ -1399,7 +1351,7 @@ static void init_status_task(struct status_task *st) { memset(st, 0, sizeof(struct status_task)); st->sa_time_diff_sign = 1; - st->clock_diff_count = conf.clock_diff_count_arg; + st->clock_diff_count = OPT_UINT32_VAL(CLOCK_DIFF_COUNT); st->current_audio_format_num = -1; st->btrn = btr_new_node(&(struct btr_node_description) EMBRACE(.name = "stat")); @@ -1415,36 +1367,20 @@ static void init_status_task(struct status_task *st) static void set_initial_status(void) { audiod_status = AUDIOD_ON; - if (!conf.mode_given) + if (!OPT_GIVEN(MODE)) return; - if (!strcmp(conf.mode_arg, "sb")) { + if (!strcmp(OPT_STRING_VAL(MODE), "sb")) { audiod_status = AUDIOD_STANDBY; return; } - if (!strcmp(conf.mode_arg, "off")) { + if (!strcmp(OPT_STRING_VAL(MODE), "off")) { audiod_status = AUDIOD_OFF; return; } - if (strcmp(conf.mode_arg, "on")) + if (strcmp(OPT_STRING_VAL(MODE), "on")) PARA_WARNING_LOG("invalid mode\n"); } -__noreturn static void print_help_and_die(void) -{ - struct ggo_help h = DEFINE_GGO_HELP(audiod); - bool d = conf.detailed_help_given; - unsigned flags; - - flags = d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS; - ggo_print_help(&h, flags); - - flags = d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS; - print_receiver_helps(flags); - print_filter_helps(flags); - print_writer_helps(flags); - exit(0); -} - /** * Lookup the given UID in the whitelist. * @@ -1460,14 +1396,33 @@ bool uid_is_whitelisted(uid_t uid) { int i; - if (!conf.user_allow_given) + if (!OPT_GIVEN(USER_ALLOW)) return true; - for (i = 0; i < conf.user_allow_given; i++) + for (i = 0; i < OPT_GIVEN(USER_ALLOW); i++) if (uid == uid_whitelist[i]) return true; return false; } +static void handle_help_flags(void) +{ + char *help; + bool d = OPT_GIVEN(DETAILED_HELP); + + if (d) + help = lls_long_help(CMD_PTR); + else if (OPT_GIVEN(HELP)) + help = lls_short_help(CMD_PTR); + else + return; + printf("%s\n", help); + free(help); + print_receiver_helps(d); + print_filter_helps(d); + print_writer_helps(d); + exit(EXIT_SUCCESS); +} + /** * the main function of para_audiod * @@ -1482,40 +1437,33 @@ int main(int argc, char *argv[]) { int ret, i; struct command_task command_task_struct, *cmd_task = &command_task_struct; - struct audiod_cmdline_parser_params params = { - .override = 0, - .initialize = 1, - .check_required = 0, - .check_ambiguity = 0, - .print_errors = 1 - }; + char *errctx; valid_fd_012(); - audiod_cmdline_parser_ext(argc, argv, &conf, ¶ms); - daemon_set_loglevel(conf.loglevel_arg); - version_handle_flag("audiod", conf.version_given); - /* init receivers/filters/writers early to make help work */ - recv_init(); - filter_init(); - 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); + ret = lls(lls_parse(argc, argv, CMD_PTR, &lpr, &errctx)); + if (ret < 0) + goto out; + daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL)); + daemon_drop_privileges_or_die(OPT_STRING_VAL(USER), + OPT_STRING_VAL(GROUP)); + version_handle_flag("audiod", OPT_GIVEN(VERSION)); + handle_help_flags(); parse_config_or_die(); - 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]); + crypt_init(); + daemon_set_priority(OPT_UINT32_VAL(PRIORITY)); + if (daemon_init_colors_or_die(OPT_UINT32_VAL(COLOR), COLOR_AUTO, + COLOR_NO, OPT_GIVEN(LOGFILE))) { + for (i = 0; i < OPT_GIVEN(LOG_COLOR); i++) + daemon_set_log_color_or_die(lls_string_val(i, + OPT_RESULT(LOG_COLOR))); } - init_random_seed_or_die(); daemon_set_flag(DF_LOG_TIME); daemon_set_flag(DF_LOG_HOSTNAME); daemon_set_flag(DF_LOG_LL); - if (conf.log_timing_given) + if (OPT_GIVEN(LOG_TIMING)) daemon_set_flag(DF_LOG_TIMING); - if (conf.logfile_given) { - daemon_set_logfile(conf.logfile_arg); + if (OPT_GIVEN(LOGFILE)) { + daemon_set_logfile(OPT_STRING_VAL(LOGFILE)); daemon_open_log_or_die(); } ret = parse_stream_args(); @@ -1533,7 +1481,7 @@ int main(int argc, char *argv[]) init_status_task(stat_task); init_command_task(cmd_task); - if (conf.daemon_given) + if (OPT_GIVEN(DAEMON)) daemonize(false /* parent exits immediately */); signal_task->task = task_register(&(struct task_info) { @@ -1549,7 +1497,11 @@ int main(int argc, char *argv[]) audiod_cleanup(); sched_shutdown(&sched); signal_shutdown(signal_task); - + crypt_shutdown(); +out: + lls_free_parse_result(lpr, CMD_PTR); + if (errctx) + PARA_ERROR_LOG("%s\n", errctx); if (ret < 0) PARA_EMERG_LOG("%s\n", para_strerror(-ret)); return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;