1d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/*
2d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
3d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * All rights reserved.
4d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *
5d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Redistribution and use in source and binary forms, with or without
6d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * modification, are permitted provided that the following conditions
7d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * are met:
8d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 1. Redistributions of source code must retain the above copyright
9d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    notice, this list of conditions and the following disclaimer.
10d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright
11d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    notice, this list of conditions and the following disclaimer in the
12d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    documentation and/or other materials provided with the distribution.
13d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 3. The name of the author may not be used to endorse or promote products
14d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    derived from this software without specific prior written permission.
15d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *
16d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */
27d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
28d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include "defs.h"
29d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include "nsig.h"
30d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
31d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughestypedef unsigned int number_slot_t;
32d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#define BITS_PER_SLOT (sizeof(number_slot_t) * 8)
33d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
34d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set {
35d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	number_slot_t *vec;
36d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int nslots;
37d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	bool not;
38d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes};
39d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
40d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set read_set;
41d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set write_set;
42d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set signal_set;
43d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
44d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set abbrev_set[SUPPORTED_PERSONALITIES];
45d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set inject_set[SUPPORTED_PERSONALITIES];
46d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set raw_set[SUPPORTED_PERSONALITIES];
47d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set trace_set[SUPPORTED_PERSONALITIES];
48d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set verbose_set[SUPPORTED_PERSONALITIES];
49d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
50d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
51d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesnumber_setbit(const unsigned int i, number_slot_t *const vec)
52d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
53d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	vec[i / BITS_PER_SLOT] |= (number_slot_t) 1 << (i % BITS_PER_SLOT);
54d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
55d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
56d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool
57d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesnumber_isset(const unsigned int i, const number_slot_t *const vec)
58d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
59d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return vec[i / BITS_PER_SLOT] & ((number_slot_t) 1 << (i % BITS_PER_SLOT));
60d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
61d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
62d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
63d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesreallocate_number_set(struct number_set *const set, const unsigned int new_nslots)
64d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
65d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (new_nslots <= set->nslots)
66d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return;
67d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	set->vec = xreallocarray(set->vec, new_nslots, sizeof(*set->vec));
68d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	memset(set->vec + set->nslots, 0,
69d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	       sizeof(*set->vec) * (new_nslots - set->nslots));
70d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	set->nslots = new_nslots;
71d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
72d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
73d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
74d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesadd_number_to_set(const unsigned int number, struct number_set *const set)
75d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
76d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	reallocate_number_set(set, number / BITS_PER_SLOT + 1);
77d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	number_setbit(number, set->vec);
78d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
79d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
80d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesbool
81d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesis_number_in_set(const unsigned int number, const struct number_set *const set)
82d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
83d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return ((number / BITS_PER_SLOT < set->nslots)
84d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		&& number_isset(number, set->vec)) ^ set->not;
85d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
86d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
87d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughestypedef int (*string_to_uint_func)(const char *);
88d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
89d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/*
90d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Add numbers to SET according to STR specification.
91d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */
92d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
93d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_tokens(const char *const str, struct number_set *const set,
94d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	       string_to_uint_func func, const char *const name)
95d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
96d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/* Clear the set. */
97d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (set->nslots)
98d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		memset(set->vec, 0, sizeof(*set->vec) * set->nslots);
99d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	set->not = false;
100d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
101d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/*
102d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * Each leading ! character means inversion
103d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * of the remaining specification.
104d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 */
105d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const char *s = str;
106d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hugheshandle_inversion:
107d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	while (*s == '!') {
108d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		set->not = !set->not;
109d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		++s;
110d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
111d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
112d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (strcmp(s, "none") == 0) {
113d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		/*
114d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * No numbers are added to the set.
115d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * Subsequent is_number_in_set invocations will return set->not.
116d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 */
117d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return;
118d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	} else if (strcmp(s, "all") == 0) {
119d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		s = "!none";
120d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		goto handle_inversion;
121d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
122d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
123d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/*
124d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * Split the string into comma separated tokens.
125d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * For each token, find out the corresponding number
126d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * by calling FUNC, and add that number to the set.
127d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * The absence of tokens or a negative answer
128d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * from FUNC is a fatal error.
129d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 */
130d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *copy = xstrdup(s);
131d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *saveptr = NULL;
132d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const char *token;
133d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	int number = -1;
134d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
135d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (token = strtok_r(copy, ",", &saveptr); token;
136d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	     token = strtok_r(NULL, ",", &saveptr)) {
137d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		number = func(token);
138d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (number < 0) {
139d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			error_msg_and_die("invalid %s '%s'", name, token);
140d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
141d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
142d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		add_number_to_set(number, set);
143d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
144d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
145d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	free(copy);
146d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
147d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (number < 0) {
148d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		error_msg_and_die("invalid %s '%s'", name, str);
149d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
150d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
151d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
152d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic int
153d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughessigstr_to_uint(const char *s)
154d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
155d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	int i;
156d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
157d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (*s >= '0' && *s <= '9')
158d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return string_to_uint_upto(s, 255);
159d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
160d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (strncasecmp(s, "SIG", 3) == 0)
161d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		s += 3;
162d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
163d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (i = 0; i <= 255; ++i) {
164d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		const char *name = signame(i);
165d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
166d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (strncasecmp(name, "SIG", 3) != 0)
167d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			continue;
168d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
169d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		name += 3;
170d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
171d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (strcasecmp(name, s) != 0)
172d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			continue;
173d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
174d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return i;
175d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
176d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
177d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return -1;
178d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
179d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
180d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool
181d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_number(const char *s, struct number_set *set)
182d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
183d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	int n = string_to_uint(s);
184d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (n < 0)
185d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return false;
186d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
187d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int p;
188d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	bool done = false;
189d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
190d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
191d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if ((unsigned) n >= nsyscall_vec[p]) {
192d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			continue;
193d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
194d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		add_number_to_set(n, &set[p]);
195d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		done = true;
196d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
197d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
198d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return done;
199d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
200d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
201d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic unsigned int
202d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hugheslookup_class(const char *s)
203d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
204d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	static const struct {
205d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		const char *name;
206d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		unsigned int value;
207d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	} syscall_class[] = {
208d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ "desc",	TRACE_DESC	},
209d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ "file",	TRACE_FILE	},
210d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ "memory",	TRACE_MEMORY	},
211d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ "process",	TRACE_PROCESS	},
212d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ "signal",	TRACE_SIGNAL	},
213d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ "ipc",	TRACE_IPC	},
214d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ "network",	TRACE_NETWORK	},
215d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	};
216d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
217d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int i;
218d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (i = 0; i < ARRAY_SIZE(syscall_class); ++i) {
219d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (strcmp(s, syscall_class[i].name) == 0) {
220d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return syscall_class[i].value;
221d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
222d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
223d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
224d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return 0;
225d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
226d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
227d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool
228d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_class(const char *s, struct number_set *set)
229d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
230d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const unsigned int n = lookup_class(s);
231d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (!n)
232d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return false;
233d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
234d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int p;
235d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
236d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		unsigned int i;
237d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
238d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		for (i = 0; i < nsyscall_vec[p]; ++i) {
239d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			if (!sysent_vec[p][i].sys_name
240d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			    || (sysent_vec[p][i].sys_flags & n) != n) {
241d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				continue;
242d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			}
243d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			add_number_to_set(i, &set[p]);
244d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
245d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
246d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
247d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return true;
248d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
249d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
250d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool
251d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_name(const char *s, struct number_set *set)
252d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
253d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int p;
254d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	bool found = false;
255d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
256d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
257d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		unsigned int i;
258d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
259d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		for (i = 0; i < nsyscall_vec[p]; ++i) {
260d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			if (!sysent_vec[p][i].sys_name
261d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			    || strcmp(s, sysent_vec[p][i].sys_name)) {
262d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				continue;
263d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			}
264d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			add_number_to_set(i, &set[p]);
265d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			found = true;
266d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
267d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
268d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
269d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return found;
270d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
271d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
272d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool
273d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall(const char *token, struct number_set *set)
274d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
275d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (*token >= '0' && *token <= '9')
276d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return qualify_syscall_number(token, set);
277d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return qualify_syscall_class(token, set)
278d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	       || qualify_syscall_name(token, set);
279d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
280d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
281d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/*
282d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Add syscall numbers to SETs for each supported personality
283d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * according to STR specification.
284d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */
285d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
286d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_tokens(const char *const str, struct number_set *const set,
287d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		       const char *const name)
288d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
289d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/* Clear all sets. */
290d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int p;
291d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
292d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (set[p].nslots)
293d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			memset(set[p].vec, 0,
294d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			       sizeof(*set[p].vec) * set[p].nslots);
295d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		set[p].not = false;
296d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
297d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
298d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/*
299d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * Each leading ! character means inversion
300d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * of the remaining specification.
301d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 */
302d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const char *s = str;
303d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hugheshandle_inversion:
304d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	while (*s == '!') {
305d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
306d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			set[p].not = !set[p].not;
307d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
308d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		++s;
309d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
310d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
311d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (strcmp(s, "none") == 0) {
312d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		/*
313d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * No syscall numbers are added to sets.
314d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * Subsequent is_number_in_set invocations
315d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * will return set[p]->not.
316d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 */
317d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return;
318d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	} else if (strcmp(s, "all") == 0) {
319d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		s = "!none";
320d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		goto handle_inversion;
321d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
322d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
323d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/*
324d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * Split the string into comma separated tokens.
325d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * For each token, call qualify_syscall that will take care
326d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * if adding appropriate syscall numbers to sets.
327d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * The absence of tokens or a negative return code
328d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * from qualify_syscall is a fatal error.
329d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 */
330d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *copy = xstrdup(s);
331d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *saveptr = NULL;
332d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const char *token;
333d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	bool done = false;
334d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
335d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (token = strtok_r(copy, ",", &saveptr); token;
336d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	     token = strtok_r(NULL, ",", &saveptr)) {
337d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		done = qualify_syscall(token, set);
338d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (!done) {
339d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			error_msg_and_die("invalid %s '%s'", name, token);
340d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
341d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
342d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
343d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	free(copy);
344d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
345d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (!done) {
346d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		error_msg_and_die("invalid %s '%s'", name, str);
347d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
348d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
349d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
350d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/*
351d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Returns NULL if STR does not start with PREFIX,
352d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * or a pointer to the first char in STR after PREFIX.
353d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */
354d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic const char *
355d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstrip_prefix(const char *prefix, const char *str)
356d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
357d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	size_t len = strlen(prefix);
358d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
359d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return strncmp(prefix, str, len) ? NULL : str + len;
360d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
361d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
362d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic int
363d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesfind_errno_by_name(const char *name)
364d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
365d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int i;
366d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
367d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (i = 1; i < nerrnos; ++i) {
368d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (errnoent[i] && (strcasecmp(name, errnoent[i]) == 0))
369d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return i;
370d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
371d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
372d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return -1;
373d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
374d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
375d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool
376d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesparse_inject_token(const char *const token, struct inject_opts *const fopts,
377d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		   const bool fault_tokens_only)
378d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
379d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const char *val;
380d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	int intval;
381d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
382d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if ((val = strip_prefix("when=", token))) {
383d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		/*
384d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * 	== 1+1
385d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * F	== F+0
386d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * F+	== F+1
387d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 * F+S
388d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 */
389d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		char *end;
390d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		intval = string_to_uint_ex(val, &end, 0xffff, "+");
391d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (intval < 1)
392d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return false;
393d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
394d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		fopts->first = intval;
395d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
396d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (*end) {
397d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			val = end + 1;
398d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			if (*val) {
399d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				/* F+S */
400d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				intval = string_to_uint_upto(val, 0xffff);
401d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				if (intval < 1)
402d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					return false;
403d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				fopts->step = intval;
404d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			} else {
405d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				/* F+ == F+1 */
406d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				fopts->step = 1;
407d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			}
408d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		} else {
409d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			/* F == F+0 */
410d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			fopts->step = 0;
411d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
412d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	} else if ((val = strip_prefix("error=", token))) {
413d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (fopts->rval != INJECT_OPTS_RVAL_DEFAULT)
414d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return false;
415d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		intval = string_to_uint_upto(val, MAX_ERRNO_VALUE);
416d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (intval < 0)
417d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			intval = find_errno_by_name(val);
418d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (intval < 1)
419d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return false;
420d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		fopts->rval = -intval;
421d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	} else if (!fault_tokens_only && (val = strip_prefix("retval=", token))) {
422d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (fopts->rval != INJECT_OPTS_RVAL_DEFAULT)
423d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return false;
424d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		intval = string_to_uint(val);
425d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (intval < 0)
426d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return false;
427d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		fopts->rval = intval;
428d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	} else if (!fault_tokens_only && (val = strip_prefix("signal=", token))) {
429d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		intval = sigstr_to_uint(val);
430d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (intval < 1 || intval > NSIG_BYTES * 8)
431d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			return false;
432d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		fopts->signo = intval;
433d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	} else {
434d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return false;
435d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
436d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
437d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return true;
438d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
439d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
440d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic char *
441d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesparse_inject_expression(const char *const s, char **buf,
442d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			struct inject_opts *const fopts,
443d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			const bool fault_tokens_only)
444d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
445d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *saveptr = NULL;
446d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *name = NULL;
447d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *token;
448d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
449d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	*buf = xstrdup(s);
450d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (token = strtok_r(*buf, ":", &saveptr); token;
451d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	     token = strtok_r(NULL, ":", &saveptr)) {
452d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (!name)
453d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			name = token;
454d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		else if (!parse_inject_token(token, fopts, fault_tokens_only))
455d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			goto parse_error;
456d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
457d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
458d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (name)
459d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return name;
460d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
461d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesparse_error:
462d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	free(*buf);
463d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return *buf = NULL;
464d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
465d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
466d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
467d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_read(const char *const str)
468d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
469d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_tokens(str, &read_set, string_to_uint, "descriptor");
470d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
471d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
472d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
473d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_write(const char *const str)
474d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
475d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_tokens(str, &write_set, string_to_uint, "descriptor");
476d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
477d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
478d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
479d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_signals(const char *const str)
480d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
481d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_tokens(str, &signal_set, sigstr_to_uint, "signal");
482d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
483d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
484d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
485d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_trace(const char *const str)
486d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
487d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_syscall_tokens(str, trace_set, "system call");
488d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
489d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
490d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
491d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_abbrev(const char *const str)
492d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
493d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_syscall_tokens(str, abbrev_set, "system call");
494d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
495d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
496d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
497d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_verbose(const char *const str)
498d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
499d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_syscall_tokens(str, verbose_set, "system call");
500d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
501d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
502d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
503d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_raw(const char *const str)
504d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
505d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_syscall_tokens(str, raw_set, "system call");
506d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
507d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
508d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
509d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_inject_common(const char *const str,
510d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		      const bool fault_tokens_only,
511d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		      const char *const description)
512d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
513d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct inject_opts opts = {
514d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		.first = 1,
515d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		.step = 1,
516d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		.rval = INJECT_OPTS_RVAL_DEFAULT,
517d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		.signo = 0
518d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	};
519d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *buf = NULL;
520d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *name = parse_inject_expression(str, &buf, &opts, fault_tokens_only);
521d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (!name) {
522d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		error_msg_and_die("invalid %s '%s'", description, str);
523d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
524d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
525d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/* If neither of retval, error, or signal is specified, then ... */
526d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (opts.rval == INJECT_OPTS_RVAL_DEFAULT && !opts.signo) {
527d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (fault_tokens_only) {
528d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			/* in fault= syntax the default error code is ENOSYS. */
529d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			opts.rval = -ENOSYS;
530d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		} else {
531d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			/* in inject= syntax this is not allowed. */
532d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			error_msg_and_die("invalid %s '%s'", description, str);
533d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
534d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
535d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
536d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct number_set tmp_set[SUPPORTED_PERSONALITIES];
537d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	memset(tmp_set, 0, sizeof(tmp_set));
538d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_syscall_tokens(name, tmp_set, description);
539d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
540d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	free(buf);
541d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
542d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/*
543d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * Initialize inject_vec accourding to tmp_set.
544d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 * Merge tmp_set into inject_set.
545d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	 */
546d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int p;
547d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
548d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (!tmp_set[p].nslots && !tmp_set[p].not) {
549d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			continue;
550d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
551d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
552d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (!inject_vec[p]) {
553d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			inject_vec[p] = xcalloc(nsyscall_vec[p],
554d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					       sizeof(*inject_vec[p]));
555d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
556d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
557d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		unsigned int i;
558d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		for (i = 0; i < nsyscall_vec[p]; ++i) {
559d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			if (is_number_in_set(i, &tmp_set[p])) {
560d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				add_number_to_set(i, &inject_set[p]);
561d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				inject_vec[p][i] = opts;
562d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			}
563d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
564d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
565d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		free(tmp_set[p].vec);
566d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
567d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
568d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
569d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
570d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_fault(const char *const str)
571d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
572d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_inject_common(str, true, "fault argument");
573d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
574d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
575d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
576d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_inject(const char *const str)
577d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
578d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	qualify_inject_common(str, false, "inject argument");
579d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
580d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
581d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic const struct qual_options {
582d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const char *name;
583d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	void (*qualify)(const char *);
584d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} qual_options[] = {
585d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "trace",	qualify_trace	},
586d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "t",		qualify_trace	},
587d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "abbrev",	qualify_abbrev	},
588d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "a",		qualify_abbrev	},
589d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "verbose",	qualify_verbose	},
590d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "v",		qualify_verbose	},
591d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "raw",	qualify_raw	},
592d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "x",		qualify_raw	},
593d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "signal",	qualify_signals	},
594d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "signals",	qualify_signals	},
595d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "s",		qualify_signals	},
596d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "read",	qualify_read	},
597d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "reads",	qualify_read	},
598d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "r",		qualify_read	},
599d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "write",	qualify_write	},
600d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "writes",	qualify_write	},
601d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "w",		qualify_write	},
602d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "fault",	qualify_fault	},
603d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	{ "inject",	qualify_inject	},
604d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes};
605d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
606d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesvoid
607d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify(const char *str)
608d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
609d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const struct qual_options *opt = qual_options;
610d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	unsigned int i;
611d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
612d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (i = 0; i < ARRAY_SIZE(qual_options); ++i) {
613d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		const char *p = qual_options[i].name;
614d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		unsigned int len = strlen(p);
615d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
616d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (strncmp(str, p, len) || str[len] != '=')
617d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			continue;
618d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
619d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		opt = &qual_options[i];
620d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		str += len + 1;
621d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		break;
622d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
623d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
624d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	opt->qualify(str);
625d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
626d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
627d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesunsigned int
628d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqual_flags(const unsigned int scno)
629d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
630d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return	(is_number_in_set(scno, &trace_set[current_personality])
631d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		   ? QUAL_TRACE : 0)
632d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		| (is_number_in_set(scno, &abbrev_set[current_personality])
633d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		   ? QUAL_ABBREV : 0)
634d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		| (is_number_in_set(scno, &verbose_set[current_personality])
635d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		   ? QUAL_VERBOSE : 0)
636d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		| (is_number_in_set(scno, &raw_set[current_personality])
637d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		   ? QUAL_RAW : 0)
638d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		| (is_number_in_set(scno, &inject_set[current_personality])
639d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		   ? QUAL_INJECT : 0);
640d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
641