summaryrefslogtreecommitdiff
path: root/usr.bin/tmux/arguments.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2019-04-28 20:05:51 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2019-04-28 20:05:51 +0000
commit33d544b49816a3e9c53b23a441cbbb44ca3e7104 (patch)
tree1158b262afa2b9ef235acca14ebdf29f2362fad2 /usr.bin/tmux/arguments.c
parent85a27b2729a3964babaadc7ed78346074dbc638c (diff)
Support multiple occurances of the same argument. Use this for a new
flag -e to new-window, split-window, respawn-window, respawn-pane to pass environment variables into the newly created process. From Steffen Christgau in GitHub issue 1697.
Diffstat (limited to 'usr.bin/tmux/arguments.c')
-rw-r--r--usr.bin/tmux/arguments.c159
1 files changed, 111 insertions, 48 deletions
diff --git a/usr.bin/tmux/arguments.c b/usr.bin/tmux/arguments.c
index 5f8bfa633ae..051adf26dd9 100644
--- a/usr.bin/tmux/arguments.c
+++ b/usr.bin/tmux/arguments.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: arguments.c,v 1.20 2017/08/23 09:14:21 nicm Exp $ */
+/* $OpenBSD: arguments.c,v 1.21 2019/04/28 20:05:50 nicm Exp $ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -29,9 +29,15 @@
* Manipulate command arguments.
*/
+struct args_value {
+ char *value;
+ TAILQ_ENTRY(args_value) entry;
+};
+TAILQ_HEAD(args_values, args_value);
+
struct args_entry {
u_char flag;
- char *value;
+ struct args_values values;
RB_ENTRY(args_entry) entry;
};
@@ -93,12 +99,18 @@ args_free(struct args *args)
{
struct args_entry *entry;
struct args_entry *entry1;
+ struct args_value *value;
+ struct args_value *value1;
cmd_free_argv(args->argc, args->argv);
RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
RB_REMOVE(args_tree, &args->tree, entry);
- free(entry->value);
+ TAILQ_FOREACH_SAFE(value, &entry->values, entry, value1) {
+ TAILQ_REMOVE(&entry->values, value, entry);
+ free(value->value);
+ free(value);
+ }
free(entry);
}
@@ -124,22 +136,69 @@ args_print_add(char **buf, size_t *len, const char *fmt, ...)
free(s);
}
+/* Add value to string. */
+static void
+args_print_add_value(char **buf, size_t *len, struct args_entry *entry,
+ struct args_value *value)
+{
+ static const char quoted[] = " #\"';$";
+ char *escaped;
+ int flags;
+
+ if (**buf != '\0')
+ args_print_add(buf, len, " -%c ", entry->flag);
+ else
+ args_print_add(buf, len, "-%c ", entry->flag);
+
+ flags = VIS_OCTAL|VIS_TAB|VIS_NL;
+ if (value->value[strcspn(value->value, quoted)] != '\0')
+ flags |= VIS_DQ;
+ utf8_stravis(&escaped, value->value, flags);
+ if (flags & VIS_DQ)
+ args_print_add(buf, len, "\"%s\"", escaped);
+ else
+ args_print_add(buf, len, "%s", escaped);
+ free(escaped);
+}
+
+/* Add argument to string. */
+static void
+args_print_add_argument(char **buf, size_t *len, const char *argument)
+{
+ static const char quoted[] = " #\"';$";
+ char *escaped;
+ int flags;
+
+ if (**buf != '\0')
+ args_print_add(buf, len, " ");
+
+ flags = VIS_OCTAL|VIS_TAB|VIS_NL;
+ if (argument[strcspn(argument, quoted)] != '\0')
+ flags |= VIS_DQ;
+ utf8_stravis(&escaped, argument, flags);
+ if (flags & VIS_DQ)
+ args_print_add(buf, len, "\"%s\"", escaped);
+ else
+ args_print_add(buf, len, "%s", escaped);
+ free(escaped);
+}
+
/* Print a set of arguments. */
char *
args_print(struct args *args)
{
size_t len;
- char *buf, *escaped;
- int i, flags;
+ char *buf;
+ int i;
struct args_entry *entry;
- static const char quoted[] = " #\"';$";
+ struct args_value *value;
len = 1;
buf = xcalloc(1, len);
/* Process the flags first. */
RB_FOREACH(entry, args_tree, &args->tree) {
- if (entry->value != NULL)
+ if (!TAILQ_EMPTY(&entry->values))
continue;
if (*buf == '\0')
@@ -149,40 +208,13 @@ args_print(struct args *args)
/* Then the flags with arguments. */
RB_FOREACH(entry, args_tree, &args->tree) {
- if (entry->value == NULL)
- continue;
-
- if (*buf != '\0')
- args_print_add(&buf, &len, " -%c ", entry->flag);
- else
- args_print_add(&buf, &len, "-%c ", entry->flag);
-
- flags = VIS_OCTAL|VIS_TAB|VIS_NL;
- if (entry->value[strcspn(entry->value, quoted)] != '\0')
- flags |= VIS_DQ;
- utf8_stravis(&escaped, entry->value, flags);
- if (flags & VIS_DQ)
- args_print_add(&buf, &len, "\"%s\"", escaped);
- else
- args_print_add(&buf, &len, "%s", escaped);
- free(escaped);
+ TAILQ_FOREACH(value, &entry->values, entry)
+ args_print_add_value(&buf, &len, entry, value);
}
/* And finally the argument vector. */
- for (i = 0; i < args->argc; i++) {
- if (*buf != '\0')
- args_print_add(&buf, &len, " ");
-
- flags = VIS_OCTAL|VIS_TAB|VIS_NL;
- if (args->argv[i][strcspn(args->argv[i], quoted)] != '\0')
- flags |= VIS_DQ;
- utf8_stravis(&escaped, args->argv[i], flags);
- if (flags & VIS_DQ)
- args_print_add(&buf, &len, "\"%s\"", escaped);
- else
- args_print_add(&buf, &len, "%s", escaped);
- free(escaped);
- }
+ for (i = 0; i < args->argc; i++)
+ args_print_add_argument(&buf, &len, args->argv[i]);
return (buf);
}
@@ -196,22 +228,24 @@ args_has(struct args *args, u_char ch)
/* Set argument value in the arguments tree. */
void
-args_set(struct args *args, u_char ch, const char *value)
+args_set(struct args *args, u_char ch, const char *s)
{
struct args_entry *entry;
+ struct args_value *value;
- /* Replace existing argument. */
- if ((entry = args_find(args, ch)) != NULL) {
- free(entry->value);
- entry->value = NULL;
- } else {
+ entry = args_find(args, ch);
+ if (entry == NULL) {
entry = xcalloc(1, sizeof *entry);
entry->flag = ch;
+ TAILQ_INIT(&entry->values);
RB_INSERT(args_tree, &args->tree, entry);
}
- if (value != NULL)
- entry->value = xstrdup(value);
+ if (s != NULL) {
+ value = xcalloc(1, sizeof *value);
+ value->value = xstrdup(s);
+ TAILQ_INSERT_TAIL(&entry->values, value, entry);
+ }
}
/* Get argument value. Will be NULL if it isn't present. */
@@ -222,7 +256,34 @@ args_get(struct args *args, u_char ch)
if ((entry = args_find(args, ch)) == NULL)
return (NULL);
- return (entry->value);
+ return (TAILQ_LAST(&entry->values, args_values)->value);
+}
+
+/* Get first value in argument. */
+const char *
+args_first_value(struct args *args, u_char ch, struct args_value **value)
+{
+ struct args_entry *entry;
+
+ if ((entry = args_find(args, ch)) == NULL)
+ return (NULL);
+
+ *value = TAILQ_FIRST(&entry->values);
+ if (*value == NULL)
+ return (NULL);
+ return ((*value)->value);
+}
+
+/* Get next value in argument. */
+const char *
+args_next_value(struct args_value **value)
+{
+ if (*value == NULL)
+ return (NULL);
+ *value = TAILQ_NEXT(*value, entry);
+ if (*value == NULL)
+ return (NULL);
+ return ((*value)->value);
}
/* Convert an argument value to a number. */
@@ -233,13 +294,15 @@ args_strtonum(struct args *args, u_char ch, long long minval, long long maxval,
const char *errstr;
long long ll;
struct args_entry *entry;
+ struct args_value *value;
if ((entry = args_find(args, ch)) == NULL) {
*cause = xstrdup("missing");
return (0);
}
+ value = TAILQ_LAST(&entry->values, args_values);
- ll = strtonum(entry->value, minval, maxval, &errstr);
+ ll = strtonum(value->value, minval, maxval, &errstr);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);