- args = conf.inputs_num?
- concat_args(conf.inputs_num, conf.inputs) :
- para_strdup("stat");
- buf = para_malloc(conf.bufsize_arg);
- if (conf.socket_given)
- socket_name = para_strdup(conf.socket_arg);
- else
- socket_name = make_message(
- "/var/paraslash/audiod_socket.%s", hn);
- if (conf.tmpdir_given)
- tmpsocket_name = make_message("%s/audioc.sock.%s.%s",
- conf.tmpdir_arg, hn, randname);
+ return ret;
+}
+
+static struct audioc_task audioc_task, *at = &audioc_task;
+
+static int audioc_i9e_line_handler(char *line)
+{
+ int argc, ret;
+ char *args, **argv;
+
+ PARA_DEBUG_LOG("line: %s\n", line);
+ ret = create_argv(line, " ", &argv);
+ if (ret < 0)
+ return ret;
+ argc = ret;
+ args = concat_args(argc, argv);
+ free_argv(argv);
+ if (!args)
+ return 0;
+ ret = connect_audiod(socket_name, args);
+ free(args);
+ if (ret < 0)
+ return ret;
+ at->fd = ret;
+ ret = mark_fd_nonblocking(at->fd);
+ if (ret < 0)
+ goto close;
+ at->btrn = btr_new_node(&(struct btr_node_description)
+ EMBRACE(.name = "audioc line handler"));
+ at->task = task_register(&(struct task_info) {
+ .name = "audioc",
+ .pre_select = audioc_pre_select,
+ .post_select = audioc_post_select,
+ .context = at,
+ }, &sched);
+ i9e_attach_to_stdout(at->btrn);
+ return 1;
+close:
+ close(at->fd);
+ return ret;
+}
+
+__noreturn static void interactive_session(void)
+{
+ int ret;
+ char *history_file;
+ struct sigaction act;
+ struct i9e_client_info ici = {
+ .fds = {0, 1, 2},
+ .prompt = "para_audioc> ",
+ .line_handler = audioc_i9e_line_handler,
+ .loglevel = loglevel,
+ .completers = audiod_completers,
+ };
+
+ PARA_NOTICE_LOG("\n%s\n", version_text("audioc"));
+ if (OPT_GIVEN(HISTORY_FILE))
+ history_file = para_strdup(OPT_STRING_VAL(HISTORY_FILE));
+ else {
+ char *home = para_homedir();
+ history_file = make_message("%s/.paraslash/audioc.history",
+ home);
+ free(home);
+ }
+ ici.history_file = history_file;
+
+ act.sa_handler = i9e_signal_dispatch;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGINT, &act, NULL);
+ sched.select_function = i9e_select;
+
+ sched.default_timeout.tv_sec = 1;
+ ret = i9e_open(&ici, &sched);
+ if (ret < 0)
+ goto out;
+ para_log = i9e_log;
+ ret = schedule(&sched);
+ sched_shutdown(&sched);
+ i9e_close();
+ para_log = stderr_log;
+out:
+ free(history_file);
+ free(socket_name);
+ if (ret < 0)
+ PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+__noreturn static void print_completions(void)
+{
+ int ret = i9e_print_completions(audiod_completers);
+ exit(ret <= 0? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+#else /* HAVE_READLINE */
+
+__noreturn static void interactive_session(void)
+{
+ PARA_EMERG_LOG("interactive sessions not available\n");
+ exit(EXIT_FAILURE);
+}
+
+__noreturn static void print_completions(void)
+{
+ PARA_EMERG_LOG("command completion not available\n");
+ exit(EXIT_FAILURE);
+}
+
+#endif /* HAVE_READLINE */
+
+static void handle_help_flag(void)
+{
+ char *help;
+
+ if (OPT_GIVEN(DETAILED_HELP))
+ help = lls_long_help(CMD_PTR);
+ else if (OPT_GIVEN(HELP))
+ help = lls_short_help(CMD_PTR);