int cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv) { int i; size_t arglen; if (argc == 0) return (0); *argv = xcalloc(argc, sizeof **argv); buf[len - 1] = '\0'; for (i = 0; i < argc; i++) { if (len == 0) { cmd_free_argv(argc, *argv); return (-1); } arglen = strlen(buf) + 1; (*argv)[i] = xstrdup(buf); buf += arglen; len -= arglen; } cmd_log_argv(argc, *argv, __func__); return (0); }
struct cmd_list * cmd_string_parse(const char *s, const char *file, u_int line, char **cause) { struct cmd_list *cmdlist = NULL; int argc; char **argv; *cause = NULL; if (cmd_string_split(s, &argc, &argv) != 0) goto error; if (argc != 0) { cmdlist = cmd_list_parse(argc, argv, file, line, cause); if (cmdlist == NULL) { cmd_free_argv(argc, argv); goto error; } } cmd_free_argv(argc, argv); return (cmdlist); error: xasprintf(cause, "invalid or unknown command: %s", s); return (NULL); }
static void handle_exec_cmd(__unused struct tmate_session *session, struct tmate_unpacker *uk) { struct cmd_q *cmd_q; struct cmd_list *cmdlist; struct cmd *cmd; char *cause; u_int i; unsigned int argc; char **argv; int client_id = unpack_int(uk); argc = uk->argc; argv = xmalloc(sizeof(char *) * argc); for (i = 0; i < argc; i++) argv[i] = unpack_string(uk); cmd = cmd_parse(argc, argv, NULL, 0, &cause); if (!cmd) { tmate_failed_cmd(client_id, cause); free(cause); goto out; } cmdlist = xcalloc(1, sizeof *cmdlist); cmdlist->references = 1; TAILQ_INIT(&cmdlist->list); TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry); cmd_q = cmdq_new(NULL); cmdq_run(cmd_q, cmdlist, NULL); cmd_list_free(cmdlist); cmdq_free(cmd_q); /* error messages land in cfg_causes */ for (i = 0; i < cfg_ncauses; i++) { tmate_failed_cmd(client_id, cfg_causes[i]); free(cfg_causes[i]); } free(cfg_causes); cfg_causes = NULL; cfg_ncauses = 0; out: cmd_free_argv(argc, argv); }
static int cmd_try_alias(int *argc, char ***argv) { struct options_entry *o; int old_argc = *argc, new_argc; char **old_argv = *argv, **new_argv; u_int size, idx; int i; size_t wanted; const char *s, *cp = NULL; o = options_get_only(global_options, "command-alias"); if (o == NULL || options_array_size(o, &size) == -1 || size == 0) return (-1); wanted = strlen(old_argv[0]); for (idx = 0; idx < size; idx++) { s = options_array_get(o, idx); if (s == NULL) continue; cp = strchr(s, '='); if (cp == NULL || (size_t)(cp - s) != wanted) continue; if (strncmp(old_argv[0], s, wanted) == 0) break; } if (idx == size) return (-1); if (cmd_string_split(cp + 1, &new_argc, &new_argv) != 0) return (-1); *argc = new_argc + old_argc - 1; *argv = xcalloc((*argc) + 1, sizeof **argv); for (i = 0; i < new_argc; i++) (*argv)[i] = xstrdup(new_argv[i]); for (i = 1; i < old_argc; i++) (*argv)[new_argc + i - 1] = xstrdup(old_argv[i]); log_debug("alias: %s=%s", old_argv[0], cp + 1); for (i = 0; i < *argc; i++) log_debug("alias: argv[%d] = %s", i, (*argv)[i]); cmd_free_argv(new_argc, new_argv); return (0); }
static int cmd_try_alias(int *argc, char ***argv) { struct options_entry *o; struct options_array_item *a; union options_value *ov; int old_argc = *argc, new_argc, i; char **old_argv = *argv, **new_argv; size_t wanted; const char *cp = NULL; o = options_get_only(global_options, "command-alias"); if (o == NULL) return (-1); wanted = strlen(old_argv[0]); a = options_array_first(o); while (a != NULL) { ov = options_array_item_value(a); cp = strchr(ov->string, '='); if (cp != NULL && (size_t)(cp - ov->string) == wanted && strncmp(old_argv[0], ov->string, wanted) == 0) break; a = options_array_next(a); } if (a == NULL) return (-1); if (cmd_string_split(cp + 1, &new_argc, &new_argv) != 0) return (-1); *argc = new_argc + old_argc - 1; *argv = xcalloc((*argc) + 1, sizeof **argv); for (i = 0; i < new_argc; i++) (*argv)[i] = xstrdup(new_argv[i]); for (i = 1; i < old_argc; i++) (*argv)[new_argc + i - 1] = xstrdup(old_argv[i]); log_debug("alias: %s=%s", old_argv[0], cp + 1); for (i = 0; i < *argc; i++) log_debug("alias: argv[%d] = %s", i, (*argv)[i]); cmd_free_argv(new_argc, new_argv); return (0); }
int cmd_string_split(const char *s, int *rargc, char ***rargv) { size_t p = 0; int ch, argc = 0, append = 0; char **argv = NULL, *buf = NULL, *t; const char *whitespace, *equals; size_t len = 0; for (;;) { ch = cmd_string_getc(s, &p); switch (ch) { case '\'': if ((t = cmd_string_string(s, &p, '\'', 0)) == NULL) goto error; cmd_string_copy(&buf, t, &len); break; case '"': if ((t = cmd_string_string(s, &p, '"', 1)) == NULL) goto error; cmd_string_copy(&buf, t, &len); break; case '$': if ((t = cmd_string_variable(s, &p)) == NULL) goto error; cmd_string_copy(&buf, t, &len); break; case '#': /* Comment: discard rest of line. */ while ((ch = cmd_string_getc(s, &p)) != EOF) ; /* FALLTHROUGH */ case EOF: case ' ': case '\t': if (buf != NULL) { buf = xrealloc(buf, len + 1); buf[len] = '\0'; argv = xreallocarray(argv, argc + 1, sizeof *argv); argv[argc++] = buf; buf = NULL; len = 0; } if (ch != EOF) break; while (argc != 0) { equals = strchr(argv[0], '='); whitespace = argv[0] + strcspn(argv[0], " \t"); if (equals == NULL || equals > whitespace) break; environ_put(global_environ, argv[0]); argc--; memmove(argv, argv + 1, argc * (sizeof *argv)); } goto done; case '~': if (buf != NULL) { append = 1; break; } t = cmd_string_expand_tilde(s, &p); if (t == NULL) goto error; cmd_string_copy(&buf, t, &len); break; default: append = 1; break; } if (append) { if (len >= SIZE_MAX - 2) goto error; buf = xrealloc(buf, len + 1); buf[len++] = ch; } append = 0; } done: *rargc = argc; *rargv = argv; free(buf); return (0); error: if (argv != NULL) cmd_free_argv(argc, argv); free(buf); return (-1); }