int cli_usage_args(const int argc, const char *const *args, const struct cli_schema *commands, XPRINTF xpf) { unsigned cmd; int matched_any = 0; for (cmd = 0; commands[cmd].function; ++cmd) { unsigned opt; const char *word; int matched = 1; for (opt = 0; matched && opt < argc && (word = commands[cmd].words[opt]); ++opt) if (strncmp(word, args[opt], strlen(args[opt])) != 0) matched = 0; if (matched) { matched_any = 1; for (opt = 0; (word = commands[cmd].words[opt]); ++opt) { if (word[0] == '|') ++word; xprintf(xpf, " %s", word); } xputc('\n', xpf); if (commands[cmd].description && commands[cmd].description[0]) xprintf(xpf, " %s\n", commands[cmd].description); } } if (!matched_any && argc) { strbuf b = strbuf_alloca(160); strbuf_append_argv(b, argc, args); xprintf(xpf, " No commands matching %s\n", strbuf_str(b)); } return 0; }
void logArgv(int level, struct __sourceloc whence, const char *label, int argc, const char *const *argv) { if (level != LOG_LEVEL_SILENT) { struct strbuf b; strbuf_init(&b, NULL, 0); strbuf_append_argv(&b, argc, argv); size_t len = strbuf_count(&b); strbuf_init(&b, alloca(len + 1), len + 1); strbuf_append_argv(&b, argc, argv); _log_iterator it; _log_iterator_start(&it); _rotate_log_file(&it); while (_log_iterator_next(&it, level)) { _log_prefix_whence(&it, whence); if (label) { xputs(label, it.xpf); xputc(' ', it.xpf); } xputs(strbuf_str(&b), it.xpf); } } }
int dna_helper_start() { if (!config.dna.helper.executable[0]) { /* Check if we have a helper configured. If not, then set dna_helper_pid to magic value of 0 so that we don't waste time in future looking up the dna helper configuration value. */ INFO("DNAHELPER none configured"); dna_helper_pid = 0; return 0; } if (!my_subscriber) return WHY("Unable to lookup my SID"); const char *mysid = alloca_tohex_sid_t(my_subscriber->sid); dna_helper_close_pipes(); int stdin_fds[2], stdout_fds[2], stderr_fds[2]; if (pipe(stdin_fds) == -1) return WHY_perror("pipe"); if (pipe(stdout_fds) == -1) { WHY_perror("pipe"); close(stdin_fds[0]); close(stdin_fds[1]); return -1; } if (pipe(stderr_fds) == -1) { WHY_perror("pipe"); close(stdin_fds[0]); close(stdin_fds[1]); close(stdout_fds[0]); close(stdout_fds[1]); return -1; } // Construct argv[] for execv() and log messages. const char *argv[config.dna.helper.argv.ac + 2]; argv[0] = config.dna.helper.executable; unsigned i; for (i = 0; i < config.dna.helper.argv.ac; ++i) argv[i + 1] = config.dna.helper.argv.av[i].value; argv[i + 1] = NULL; strbuf argv_sb = strbuf_append_argv(strbuf_alloca(1024), config.dna.helper.argv.ac + 1, argv); switch (dna_helper_pid = fork()) { case 0: /* Child, should exec() to become helper after installing file descriptors. */ close_log_file(); setenv("MYSID", mysid, 1); signal(SIGTERM, SIG_DFL); close(stdin_fds[1]); close(stdout_fds[0]); close(stderr_fds[0]); if (dup2(stderr_fds[1], 2) == -1 || dup2(stdout_fds[1], 1) == -1 || dup2(stdin_fds[0], 0) == -1) { LOG_perror(LOG_LEVEL_FATAL, "dup2"); _exit(-1); } { execv(config.dna.helper.executable, (char **)argv); LOGF_perror(LOG_LEVEL_FATAL, "execv(%s, [%s])", alloca_str_toprint(config.dna.helper.executable), strbuf_str(argv_sb) ); } do { _exit(-1); } while (1); break; case -1: /* fork failed */ WHY_perror("fork"); close(stdin_fds[0]); close(stdin_fds[1]); close(stdout_fds[0]); close(stdout_fds[1]); close(stderr_fds[0]); close(stderr_fds[1]); return -1; default: /* Parent, should put file descriptors into place for use */ close(stdin_fds[0]); close(stdout_fds[1]); close(stderr_fds[1]); dna_helper_started = 0; dna_helper_stdin = stdin_fds[1]; dna_helper_stdout = stdout_fds[0]; dna_helper_stderr = stderr_fds[0]; INFOF("STARTED DNA HELPER pid=%u stdin=%d stdout=%d stderr=%d executable=%s argv=[%s]", dna_helper_pid, dna_helper_stdin, dna_helper_stdout, dna_helper_stderr, alloca_str_toprint(config.dna.helper.executable), strbuf_str(argv_sb) ); sched_replies.poll.fd = dna_helper_stdout; sched_replies.poll.events = POLLIN; sched_errors.poll.fd = dna_helper_stderr; sched_errors.poll.events = POLLIN; sched_requests.poll.fd = -1; sched_requests.poll.events = POLLOUT; sched_harvester.alarm = gettime_ms() + 1000; sched_harvester.deadline = sched_harvester.alarm + 1000; reply_bufend = reply_buffer; discarding_until_nl = 0; awaiting_reply = 0; watch(&sched_replies); watch(&sched_errors); schedule(&sched_harvester); return 0; } return -1; }