X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod.c;h=2351a8ed82d1a13aa6de9e24f9e25aa23e3aa010;hp=ca8cd13b01358e13fe06ecc1c751a98800402b7b;hb=9b45b4b85558f012621fc97af31cd2ad6ad08383;hpb=870fcd0379ab096184f42481541d668694da7c83 diff --git a/audiod.c b/audiod.c index ca8cd13b..2351a8ed 100644 --- a/audiod.c +++ b/audiod.c @@ -17,15 +17,13 @@ #include #include +#include "audiod.lsg.h" #include "recv_cmd.lsg.h" -#include "client.lsg.h" #include "para.h" #include "error.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" @@ -43,6 +41,15 @@ /** 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}; @@ -165,19 +172,10 @@ char *stat_item_values[NUM_STAT_ITEMS] = {NULL}; */ 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; /** @@ -398,58 +396,82 @@ 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); + int ret; + char *cf, *errctx = NULL; + void *map; + size_t sz; + + if (OPT_GIVEN(CONFIG_FILE)) + cf = para_strdup(OPT_STRING_VAL(CONFIG_FILE)); else { char *home = para_homedir(); - config_file = make_message("%s/.paraslash/audiod.conf", home); + cf = 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); + ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL); + if (ret < 0) { + if (ret != -E_EMPTY && ret != -ERRNO_TO_PARA_ERROR(ENOENT)) + goto free_cf; + if (ret == -ERRNO_TO_PARA_ERROR(ENOENT) && OPT_GIVEN(CONFIG_FILE)) + goto free_cf; + } else { + int cf_argc; + char **cf_argv; + struct lls_parse_result *cf_lpr, *merged_lpr; + ret = lls(lls_convert_config(map, sz, NULL, &cf_argv, &errctx)); + para_munmap(map, sz); + if (ret < 0) + goto free_cf; + cf_argc = ret; + ret = lls(lls_parse(cf_argc, cf_argv, CMD_PTR, &cf_lpr, &errctx)); + lls_free_argv(cf_argv); + if (ret < 0) + goto free_cf; + ret = lls(lls_merge(lpr, cf_lpr, CMD_PTR, &merged_lpr, + &errctx)); + lls_free_parse_result(cf_lpr, CMD_PTR); + if (ret < 0) + goto free_cf; + lls_free_parse_result(lpr, CMD_PTR); + lpr = merged_lpr; } - 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++) { + daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL)); + if (OPT_GIVEN(USER_ALLOW)) { + uint32_t n = OPT_GIVEN(USER_ALLOW); + int i; + + 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(conf.user_allow_arg[i], &val); + ret = para_atoi32(arg, &val); if (ret >= 0) { uid_whitelist[i] = val; continue; } errno = 0; /* see getpwnam(3) */ - pw = getpwnam(conf.user_allow_arg[i]); + pw = getpwnam(arg); if (!pw) { - PARA_EMERG_LOG("invalid username: %s\n", - conf.user_allow_arg[i]); - goto err; + PARA_EMERG_LOG("invalid username: %s\n", arg); + free(uid_whitelist); + goto free_cf; } uid_whitelist[i] = pw->pw_uid; } } - return; -err: - exit(EXIT_FAILURE); + ret = 0; +free_cf: + free(cf); + if (ret < 0) { + if (errctx) + PARA_ERROR_LOG("%s\n", errctx); + free(errctx); + lls_free_parse_result(lpr, CMD_PTR); + PARA_EMERG_LOG("%s\n", para_strerror(-ret)); + exit(EXIT_FAILURE); + } } static void setup_signal_handling(void) @@ -878,10 +900,11 @@ static int parse_writer_args(void) const char *cmd; struct audio_format_info *a; - for (i = 0; i < conf.writer_given; i++) { + 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; @@ -923,10 +946,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; @@ -1012,9 +1036,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; @@ -1029,7 +1054,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: @@ -1055,8 +1080,8 @@ static int parse_stream_args(void) /* does not unlink socket on errors */ static void init_local_sockets(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", @@ -1064,7 +1089,7 @@ 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, @@ -1249,7 +1274,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); } @@ -1330,7 +1354,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) { @@ -1398,7 +1422,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")); @@ -1414,36 +1438,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. * @@ -1459,14 +1467,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 * @@ -1481,38 +1508,34 @@ 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(); - 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]); - } init_random_seed_or_die(); + daemon_set_priority(OPT_UINT32_VAL(PRIORITY)); + recv_init(); + 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))); + } 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(); @@ -1530,7 +1553,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) { @@ -1547,6 +1570,10 @@ int main(int argc, char *argv[]) sched_shutdown(&sched); signal_shutdown(signal_task); +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;