forked from openbsd/ports
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Validate command argument types (string or command list) and give more
useful error messages.
- Loading branch information
Showing
12 changed files
with
242 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: arguments.c,v 1.46 2021/08/23 17:05:43 nicm Exp $ */ | ||
/* $OpenBSD: arguments.c,v 1.47 2021/08/25 08:51:55 nicm Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2010 Nicholas Marriott <[email protected]> | ||
|
@@ -124,10 +124,11 @@ args_create(void) | |
/* Parse arguments into a new argument set. */ | ||
struct args * | ||
args_parse(const struct args_parse *parse, struct args_value *values, | ||
u_int count) | ||
u_int count, char **cause) | ||
{ | ||
struct args *args; | ||
u_int i; | ||
enum args_parse_type type; | ||
struct args_value *value, *new; | ||
u_char flag, argument; | ||
const char *found, *string, *s; | ||
|
@@ -153,11 +154,13 @@ args_parse(const struct args_parse *parse, struct args_value *values, | |
if (flag == '\0') | ||
break; | ||
if (!isalnum(flag)) { | ||
xasprintf(cause, "invalid flag -%c", flag); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
found = strchr(parse->template, flag); | ||
if (found == NULL) { | ||
xasprintf(cause, "unknown flag -%c", flag); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
|
@@ -167,12 +170,22 @@ args_parse(const struct args_parse *parse, struct args_value *values, | |
args_set(args, flag, NULL); | ||
continue; | ||
} | ||
new = xcalloc(1, sizeof *value); | ||
new = xcalloc(1, sizeof *new); | ||
if (*string != '\0') { | ||
new->type = ARGS_STRING; | ||
new->string = xstrdup(string); | ||
} else { | ||
if (i == count) { | ||
xasprintf(cause, | ||
"-%c expects an argument", | ||
flag); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
if (values[i].type != ARGS_STRING) { | ||
xasprintf(cause, | ||
"-%c argument must be a string", | ||
flag); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
|
@@ -192,14 +205,60 @@ args_parse(const struct args_parse *parse, struct args_value *values, | |
s = args_value_as_string(value); | ||
log_debug("%s: %u = %s", __func__, i, s); | ||
|
||
if (parse->cb != NULL) { | ||
type = parse->cb(args, args->count, cause); | ||
if (type == ARGS_PARSE_INVALID) { | ||
args_free(args); | ||
return (NULL); | ||
} | ||
} else | ||
type = ARGS_PARSE_STRING; | ||
|
||
args->values = xrecallocarray(args->values, | ||
args->count, args->count + 1, sizeof *args->values); | ||
args_copy_value(&args->values[args->count++], value); | ||
new = &args->values[args->count++]; | ||
|
||
switch (type) { | ||
case ARGS_PARSE_INVALID: | ||
fatalx("unexpected argument type"); | ||
case ARGS_PARSE_STRING: | ||
if (value->type != ARGS_STRING) { | ||
xasprintf(cause, | ||
"argument %u must be \"string\"", | ||
args->count); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
args_copy_value(new, value); | ||
break; | ||
case ARGS_PARSE_COMMANDS_OR_STRING: | ||
args_copy_value(new, value); | ||
break; | ||
case ARGS_PARSE_COMMANDS: | ||
if (value->type != ARGS_COMMANDS) { | ||
xasprintf(cause, | ||
"argument %u must be { commands }", | ||
args->count); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
args_copy_value(new, value); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if ((parse->lower != -1 && args->count < (u_int)parse->lower) || | ||
(parse->upper != -1 && args->count > (u_int)parse->upper)) { | ||
if (parse->lower != -1 && args->count < (u_int)parse->lower) { | ||
xasprintf(cause, | ||
"too few arguments (need at least %u)", | ||
parse->lower); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
if (parse->upper != -1 && args->count > (u_int)parse->upper) { | ||
xasprintf(cause, | ||
"too many arguments (need at most %u)", | ||
parse->upper); | ||
args_free(args); | ||
return (NULL); | ||
} | ||
|
@@ -254,15 +313,25 @@ args_free(struct args *args) | |
void | ||
args_vector(struct args *args, int *argc, char ***argv) | ||
{ | ||
struct args_value *value; | ||
u_int i; | ||
char *s; | ||
u_int i; | ||
|
||
*argc = 0; | ||
*argv = NULL; | ||
|
||
for (i = 0; i < args->count; i++) { | ||
value = &args->values[i]; | ||
cmd_append_argv(argc, argv, args_value_as_string(value)); | ||
switch (args->values[i].type) { | ||
case ARGS_NONE: | ||
break; | ||
case ARGS_STRING: | ||
cmd_append_argv(argc, argv, args->values[i].string); | ||
break; | ||
case ARGS_COMMANDS: | ||
s = cmd_list_print(args->values[i].cmdlist, 0); | ||
cmd_append_argv(argc, argv, s); | ||
free(s); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: cmd-bind-key.c,v 1.43 2021/08/23 11:48:21 nicm Exp $ */ | ||
/* $OpenBSD: cmd-bind-key.c,v 1.44 2021/08/25 08:51:55 nicm Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2007 Nicholas Marriott <[email protected]> | ||
|
@@ -27,20 +27,32 @@ | |
* Bind a key to a command. | ||
*/ | ||
|
||
static enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmdq_item *); | ||
static enum args_parse_type cmd_bind_key_args_parse(struct args *, u_int, | ||
char **); | ||
static enum cmd_retval cmd_bind_key_exec(struct cmd *, | ||
struct cmdq_item *); | ||
|
||
const struct cmd_entry cmd_bind_key_entry = { | ||
.name = "bind-key", | ||
.alias = "bind", | ||
|
||
.args = { "nrN:T:", 1, -1, NULL }, | ||
.args = { "nrN:T:", 1, -1, cmd_bind_key_args_parse }, | ||
.usage = "[-nr] [-T key-table] [-N note] key " | ||
"[command [arguments]]", | ||
|
||
.flags = CMD_AFTERHOOK, | ||
.exec = cmd_bind_key_exec | ||
}; | ||
|
||
static enum args_parse_type | ||
cmd_bind_key_args_parse(__unused struct args *args, u_int idx, | ||
__unused char **cause) | ||
{ | ||
if (idx == 1) | ||
return (ARGS_PARSE_COMMANDS_OR_STRING); | ||
return (ARGS_PARSE_STRING); | ||
} | ||
|
||
static enum cmd_retval | ||
cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item) | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: cmd-command-prompt.c,v 1.61 2021/08/25 06:36:05 nicm Exp $ */ | ||
/* $OpenBSD: cmd-command-prompt.c,v 1.62 2021/08/25 08:51:55 nicm Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2008 Nicholas Marriott <[email protected]> | ||
|
@@ -29,8 +29,10 @@ | |
* Prompt for command in client. | ||
*/ | ||
|
||
static enum cmd_retval cmd_command_prompt_exec(struct cmd *, | ||
struct cmdq_item *); | ||
static enum args_parse_type cmd_command_prompt_args_parse(struct args *, | ||
u_int, char **); | ||
static enum cmd_retval cmd_command_prompt_exec(struct cmd *, | ||
struct cmdq_item *); | ||
|
||
static int cmd_command_prompt_callback(struct client *, void *, | ||
const char *, int); | ||
|
@@ -40,7 +42,7 @@ const struct cmd_entry cmd_command_prompt_entry = { | |
.name = "command-prompt", | ||
.alias = NULL, | ||
|
||
.args = { "1bFkiI:Np:t:T:", 0, 1, NULL }, | ||
.args = { "1bFkiI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse }, | ||
.usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE | ||
" [-T type] [template]", | ||
|
||
|
@@ -68,6 +70,13 @@ struct cmd_command_prompt_cdata { | |
char **argv; | ||
}; | ||
|
||
static enum args_parse_type | ||
cmd_command_prompt_args_parse(__unused struct args *args, __unused u_int idx, | ||
__unused char **cause) | ||
{ | ||
return (ARGS_PARSE_COMMANDS_OR_STRING); | ||
} | ||
|
||
static enum cmd_retval | ||
cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item) | ||
{ | ||
|
@@ -197,8 +206,8 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s, | |
return (1); | ||
|
||
out: | ||
if (item != NULL) | ||
cmdq_continue(item); | ||
if (item != NULL) | ||
cmdq_continue(item); | ||
return (0); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: cmd-confirm-before.c,v 1.49 2021/08/23 12:33:55 nicm Exp $ */ | ||
/* $OpenBSD: cmd-confirm-before.c,v 1.50 2021/08/25 08:51:55 nicm Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2009 Tiago Cunha <[email protected]> | ||
|
@@ -28,8 +28,10 @@ | |
* Asks for confirmation before executing a command. | ||
*/ | ||
|
||
static enum cmd_retval cmd_confirm_before_exec(struct cmd *, | ||
struct cmdq_item *); | ||
static enum args_parse_type cmd_confirm_before_args_parse(struct args *, | ||
u_int, char **); | ||
static enum cmd_retval cmd_confirm_before_exec(struct cmd *, | ||
struct cmdq_item *); | ||
|
||
static int cmd_confirm_before_callback(struct client *, void *, | ||
const char *, int); | ||
|
@@ -39,7 +41,7 @@ const struct cmd_entry cmd_confirm_before_entry = { | |
.name = "confirm-before", | ||
.alias = "confirm", | ||
|
||
.args = { "bp:t:", 1, 1, NULL }, | ||
.args = { "bp:t:", 1, 1, cmd_confirm_before_args_parse }, | ||
.usage = "[-b] [-p prompt] " CMD_TARGET_CLIENT_USAGE " command", | ||
|
||
.flags = CMD_CLIENT_TFLAG, | ||
|
@@ -51,6 +53,13 @@ struct cmd_confirm_before_data { | |
struct cmd_list *cmdlist; | ||
}; | ||
|
||
static enum args_parse_type | ||
cmd_confirm_before_args_parse(__unused struct args *args, __unused u_int idx, | ||
__unused char **cause) | ||
{ | ||
return (ARGS_PARSE_COMMANDS_OR_STRING); | ||
} | ||
|
||
static enum cmd_retval | ||
cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item) | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: cmd-display-menu.c,v 1.31 2021/08/23 08:17:41 nicm Exp $ */ | ||
/* $OpenBSD: cmd-display-menu.c,v 1.32 2021/08/25 08:51:55 nicm Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2019 Nicholas Marriott <[email protected]> | ||
|
@@ -28,16 +28,18 @@ | |
* Display a menu on a client. | ||
*/ | ||
|
||
static enum cmd_retval cmd_display_menu_exec(struct cmd *, | ||
struct cmdq_item *); | ||
static enum cmd_retval cmd_display_popup_exec(struct cmd *, | ||
struct cmdq_item *); | ||
static enum args_parse_type cmd_display_menu_args_parse(struct args *, | ||
u_int, char **); | ||
static enum cmd_retval cmd_display_menu_exec(struct cmd *, | ||
struct cmdq_item *); | ||
static enum cmd_retval cmd_display_popup_exec(struct cmd *, | ||
struct cmdq_item *); | ||
|
||
const struct cmd_entry cmd_display_menu_entry = { | ||
.name = "display-menu", | ||
.alias = "menu", | ||
|
||
.args = { "c:t:OT:x:y:", 1, -1, NULL }, | ||
.args = { "c:t:OT:x:y:", 1, -1, cmd_display_menu_args_parse }, | ||
.usage = "[-O] [-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] " | ||
"[-x position] [-y position] name key command ...", | ||
|
||
|
@@ -53,15 +55,39 @@ const struct cmd_entry cmd_display_popup_entry = { | |
|
||
.args = { "BCc:d:Eh:t:w:x:y:", 0, -1, NULL }, | ||
.usage = "[-BCE] [-c target-client] [-d start-directory] [-h height] " | ||
CMD_TARGET_PANE_USAGE " [-w width] " | ||
"[-x position] [-y position] [command]", | ||
CMD_TARGET_PANE_USAGE " [-w width] " | ||
"[-x position] [-y position] [shell-command]", | ||
|
||
.target = { 't', CMD_FIND_PANE, 0 }, | ||
|
||
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG, | ||
.exec = cmd_display_popup_exec | ||
}; | ||
|
||
static enum args_parse_type | ||
cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause) | ||
{ | ||
u_int i = 0; | ||
enum args_parse_type type = ARGS_PARSE_STRING; | ||
|
||
for (;;) { | ||
type = ARGS_PARSE_STRING; | ||
if (i == idx) | ||
break; | ||
if (*args_string(args, i++) == '\0') | ||
continue; | ||
|
||
type = ARGS_PARSE_STRING; | ||
if (i++ == idx) | ||
break; | ||
|
||
type = ARGS_PARSE_COMMANDS_OR_STRING; | ||
if (i++ == idx) | ||
break; | ||
} | ||
return (type); | ||
} | ||
|
||
static int | ||
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, | ||
struct args *args, u_int *px, u_int *py, u_int w, u_int h) | ||
|
Oops, something went wrong.