GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/arguments.c Lines: 0 87 0.0 %
Date: 2016-12-06 Branches: 0 252 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: arguments.c,v 1.13 2016/01/19 15:59:12 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <getopt.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <unistd.h>
25
26
#include "tmux.h"
27
28
/*
29
 * Manipulate command arguments.
30
 */
31
32
struct args_entry {
33
	u_char			 flag;
34
	char			*value;
35
	RB_ENTRY(args_entry)	 entry;
36
};
37
38
struct args_entry	*args_find(struct args *, u_char);
39
40
RB_GENERATE(args_tree, args_entry, entry, args_cmp);
41
42
/* Arguments tree comparison function. */
43
int
44
args_cmp(struct args_entry *a1, struct args_entry *a2)
45
{
46
	return (a1->flag - a2->flag);
47
}
48
49
/* Create an arguments set with no flags. */
50
struct args *
51
args_create(int argc, ...)
52
{
53
	struct args	*args;
54
	va_list		 ap;
55
	int		 i;
56
57
	args = xcalloc(1, sizeof *args);
58
59
	args->argc = argc;
60
	if (argc == 0)
61
		args->argv = NULL;
62
	else
63
		args->argv = xcalloc(argc, sizeof *args->argv);
64
65
	va_start(ap, argc);
66
	for (i = 0; i < argc; i++)
67
		args->argv[i] = xstrdup(va_arg(ap, char *));
68
	va_end(ap);
69
70
	return (args);
71
}
72
73
/* Find a flag in the arguments tree. */
74
struct args_entry *
75
args_find(struct args *args, u_char ch)
76
{
77
	struct args_entry	entry;
78
79
	entry.flag = ch;
80
	return (RB_FIND(args_tree, &args->tree, &entry));
81
}
82
83
/* Parse an argv and argc into a new argument set. */
84
struct args *
85
args_parse(const char *template, int argc, char **argv)
86
{
87
	struct args	*args;
88
	int		 opt;
89
90
	args = xcalloc(1, sizeof *args);
91
92
	optreset = 1;
93
	optind = 1;
94
95
	while ((opt = getopt(argc, argv, template)) != -1) {
96
		if (opt < 0)
97
			continue;
98
		if (opt == '?' || strchr(template, opt) == NULL) {
99
			args_free(args);
100
			return (NULL);
101
		}
102
		args_set(args, opt, optarg);
103
	}
104
	argc -= optind;
105
	argv += optind;
106
107
	args->argc = argc;
108
	args->argv = cmd_copy_argv(argc, argv);
109
110
	return (args);
111
}
112
113
/* Free an arguments set. */
114
void
115
args_free(struct args *args)
116
{
117
	struct args_entry	*entry;
118
	struct args_entry	*entry1;
119
120
	cmd_free_argv(args->argc, args->argv);
121
122
	RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
123
		RB_REMOVE(args_tree, &args->tree, entry);
124
		free(entry->value);
125
		free(entry);
126
	}
127
128
	free(args);
129
}
130
131
/* Add to string. */
132
static void printflike(3, 4)
133
args_print_add(char **buf, size_t *len, const char *fmt, ...)
134
{
135
	va_list  ap;
136
	char	*s;
137
	size_t	 slen;
138
139
	va_start(ap, fmt);
140
	slen = xvasprintf(&s, fmt, ap);
141
	va_end(ap);
142
143
	*len += slen;
144
	*buf = xrealloc(*buf, *len);
145
146
	strlcat(*buf, s, *len);
147
	free(s);
148
}
149
150
/* Print a set of arguments. */
151
char *
152
args_print(struct args *args)
153
{
154
	size_t		 	 len;
155
	char			*buf;
156
	int			 i;
157
	struct args_entry	*entry;
158
159
	len = 1;
160
	buf = xcalloc(1, len);
161
162
	/* Process the flags first. */
163
	RB_FOREACH(entry, args_tree, &args->tree) {
164
		if (entry->value != NULL)
165
			continue;
166
167
		if (*buf == '\0')
168
			args_print_add(&buf, &len, "-");
169
		args_print_add(&buf, &len, "%c", entry->flag);
170
	}
171
172
	/* Then the flags with arguments. */
173
	RB_FOREACH(entry, args_tree, &args->tree) {
174
		if (entry->value == NULL)
175
			continue;
176
177
		if (*buf != '\0')
178
			args_print_add(&buf, &len, " -%c ", entry->flag);
179
		else
180
			args_print_add(&buf, &len, "-%c ", entry->flag);
181
		if (strchr(entry->value, ' ') != NULL)
182
			args_print_add(&buf, &len, "\"%s\"", entry->value);
183
		else
184
			args_print_add(&buf, &len, "%s", entry->value);
185
	}
186
187
	/* And finally the argument vector. */
188
	for (i = 0; i < args->argc; i++) {
189
		if (*buf != '\0')
190
			args_print_add(&buf, &len, " ");
191
		if (strchr(args->argv[i], ' ') != NULL)
192
			args_print_add(&buf, &len, "\"%s\"", args->argv[i]);
193
		else
194
			args_print_add(&buf, &len, "%s", args->argv[i]);
195
	}
196
197
	return (buf);
198
}
199
200
/* Return if an argument is present. */
201
int
202
args_has(struct args *args, u_char ch)
203
{
204
	return (args_find(args, ch) == NULL ? 0 : 1);
205
}
206
207
/* Set argument value in the arguments tree. */
208
void
209
args_set(struct args *args, u_char ch, const char *value)
210
{
211
	struct args_entry	*entry;
212
213
	/* Replace existing argument. */
214
	if ((entry = args_find(args, ch)) != NULL) {
215
		free(entry->value);
216
		entry->value = NULL;
217
	} else {
218
		entry = xcalloc(1, sizeof *entry);
219
		entry->flag = ch;
220
		RB_INSERT(args_tree, &args->tree, entry);
221
	}
222
223
	if (value != NULL)
224
		entry->value = xstrdup(value);
225
}
226
227
/* Get argument value. Will be NULL if it isn't present. */
228
const char *
229
args_get(struct args *args, u_char ch)
230
{
231
	struct args_entry	*entry;
232
233
	if ((entry = args_find(args, ch)) == NULL)
234
		return (NULL);
235
	return (entry->value);
236
}
237
238
/* Convert an argument value to a number. */
239
long long
240
args_strtonum(struct args *args, u_char ch, long long minval, long long maxval,
241
    char **cause)
242
{
243
	const char		*errstr;
244
	long long 	 	 ll;
245
	struct args_entry	*entry;
246
247
	if ((entry = args_find(args, ch)) == NULL) {
248
		*cause = xstrdup("missing");
249
		return (0);
250
	}
251
252
	ll = strtonum(entry->value, minval, maxval, &errstr);
253
	if (errstr != NULL) {
254
		*cause = xstrdup(errstr);
255
		return (0);
256
	}
257
258
	*cause = NULL;
259
	return (ll);
260
}