GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/bgplg/bgplgsh/../bgplgsh.c Lines: 0 104 0.0 %
Date: 2017-11-13 Branches: 0 98 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: bgplgsh.c,v 1.8 2015/12/09 17:52:24 mmcc Exp $	*/
2
3
/*
4
 * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
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 USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/stat.h>
21
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <signal.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <limits.h>
28
#include <ctype.h>
29
#include <errno.h>
30
#include <fcntl.h>
31
32
#include <readline/readline.h>
33
#include <readline/history.h>
34
35
#include "bgplg.h"
36
37
#define BGPDSOCK	"/var/www/run/bgpd.rsock"
38
#define BGPCTL		"/usr/sbin/bgpctl", "-s", BGPDSOCK
39
#define PING		"/sbin/ping"
40
#define TRACEROUTE	"/usr/sbin/traceroute"
41
#define PING6		"/sbin/ping6"
42
#define TRACEROUTE6	"/usr/sbin/traceroute6"
43
44
static volatile int quit;
45
46
static struct cmd cmds[] = CMDS;
47
48
char		**lg_arg2argv(char *, int *);
49
char		**lg_argextra(char **, int, int, struct cmd *);
50
int		  lg_checkarg(char *);
51
int		  lg_checkcmd(int, char **, int *, struct cmd *);
52
char		 *lg_completion(const char *, int);
53
54
int
55
lg_checkarg(char *arg)
56
{
57
	size_t len;
58
	u_int i;
59
60
	if (!(len = strlen(arg)))
61
		return (0);
62
63
#define allowed_in_string(_x)                                           \
64
	((isalnum((unsigned char)_x) || isprint((unsigned char)_x)) &&	\
65
	(_x != '%' && _x != '\\' && _x != ';' && _x != '&' && _x != '|'))
66
67
	for (i = 0; i < len; i++) {
68
		if (!allowed_in_string(arg[i])) {
69
			fprintf(stderr, "invalid character in input\n");
70
			return (EPERM);
71
		}
72
	}
73
#undef allowed_in_string
74
	return (0);
75
}
76
77
char **
78
lg_arg2argv(char *arg, int *argc)
79
{
80
	char **argv, *ptr = arg;
81
	size_t len;
82
	u_int i, c = 1;
83
84
	if (lg_checkarg(arg) != 0)
85
		return (NULL);
86
	if (!(len = strlen(arg)))
87
		return (NULL);
88
89
	/* Count elements */
90
	for (i = 0; i < len; i++) {
91
		if (isspace((unsigned char)arg[i])) {
92
			/* filter out additional options */
93
			if (arg[i + 1] == '-') {
94
				printf("invalid input\n");
95
				return (NULL);
96
			}
97
			arg[i] = '\0';
98
			c++;
99
		}
100
	}
101
	if (arg[0] == '\0')
102
		return (NULL);
103
104
	/* Generate array */
105
	if ((argv = calloc(c + 1, sizeof(char *))) == NULL) {
106
		printf("fatal error: %s\n", strerror(errno));
107
		return (NULL);
108
	}
109
110
	argv[c] = NULL;
111
	*argc = c;
112
113
	/* Fill array */
114
	for (i = c = 0; i < len; i++) {
115
		if (arg[i] == '\0' || i == 0) {
116
			if (i != 0)
117
				ptr = &arg[i + 1];
118
			argv[c++] = ptr;
119
		}
120
	}
121
122
	return (argv);
123
}
124
125
char **
126
lg_argextra(char **argv, int argc, int off, struct cmd *cmdp)
127
{
128
	char **new_argv;
129
	int i, c = 0, n;
130
131
	if ((n = argc - off) < 0)
132
		return (NULL);
133
134
	/* Count elements */
135
	for (i = 0; cmdp->earg[i] != NULL; i++)
136
		c++;
137
138
	/* Generate array */
139
	if ((new_argv = calloc(c + n + 1, sizeof(char *))) == NULL) {
140
		printf("fatal error: %s\n", strerror(errno));
141
		return (NULL);
142
	}
143
144
	/* Fill array */
145
	for (i = c = 0; cmdp->earg[i] != NULL; i++)
146
		new_argv[c++] = cmdp->earg[i];
147
148
	/* Append old array */
149
	for (i = n; i < argc; i++)
150
		new_argv[c++] = argv[i];
151
152
	new_argv[c] = NULL;
153
154
	free(argv);
155
156
	return (new_argv);
157
}
158
159
int
160
lg_checkcmd(int argc, char **argv, int *off, struct cmd *cmd)
161
{
162
	char **cmdp = NULL, *cmdstr = NULL;
163
	int i, ncmd, v, ret = -1;
164
165
	if ((cmdstr = strdup(cmd->name)) == NULL)
166
		goto done;
167
	if ((cmdp = lg_arg2argv(cmdstr, &ncmd)) == NULL)
168
		goto done;
169
	if (ncmd > argc || argc > (ncmd + cmd->maxargs))
170
		goto done;
171
172
	for (i = 0; i < ncmd; i++)
173
		if (strcmp(argv[i], cmdp[i]) != 0)
174
			goto done;
175
176
	if ((v = argc - ncmd) < 0 ||
177
	    (*off != -1 && *off < v))
178
		goto done;
179
	if (cmd->minargs && v < cmd->minargs) {
180
		ret = EINVAL;
181
		goto done;
182
	}
183
	*off = v;
184
	ret = 0;
185
186
 done:
187
	free(cmdp);
188
	free(cmdstr);
189
	return (ret);
190
}
191
192
char *
193
lg_completion(const char *str, int state)
194
{
195
	static int lg_complidx, len;
196
	const char *name;
197
198
	if (state == 0) {
199
		len = strlen(str);
200
		lg_complidx = 0;
201
	}
202
	while ((name = cmds[lg_complidx].name) != NULL) {
203
		lg_complidx++;
204
		if (strncmp(name, str, len) == 0)
205
			return (strdup(name));
206
	}
207
208
	return (NULL);
209
}
210
211
int
212
main(void)
213
{
214
	struct cmd *cmd = NULL;
215
	char prompt[HOST_NAME_MAX+1], *line, **argp = NULL;
216
	int ncmd, ret, v = -1;
217
	u_int i;
218
219
	rl_readline_name = NAME;
220
	rl_completion_entry_function = lg_completion;
221
222
	/* Ignore the whitespace character */
223
	rl_basic_word_break_characters = "\t\n\"\\'`@$><=;|&{(";
224
225
	while (!quit) {
226
		v = -1;
227
		gethostname(prompt, sizeof(prompt) - 2);
228
		strlcat(prompt, "> ", sizeof(prompt));
229
230
		if ((line = readline(prompt)) == NULL) {
231
			printf("\n");
232
			lg_help(cmds, NULL);
233
			continue;
234
		}
235
		if (!lg_strip(line))
236
			goto next;
237
		if (strcmp(line, "exit") == 0) {
238
			quit = 1;
239
			goto next;
240
		}
241
242
		add_history(line);
243
244
		if ((argp = lg_arg2argv(line, &ncmd)) == NULL)
245
			goto next;
246
247
		for (i = 0; cmds[i].name != NULL; i++) {
248
			ret = lg_checkcmd(ncmd, argp, &v, &cmds[i]);
249
			if (ret == 0)
250
				cmd = &cmds[i];
251
			else if (ret == EINVAL) {
252
				printf("invalid number of arguments\n");
253
				goto next;
254
			}
255
		}
256
257
		if (cmd == NULL) {
258
			printf("invalid command\n");
259
		} else if (cmd->func != NULL) {
260
			cmd->func(cmds, argp);
261
		} else {
262
			if ((argp = lg_argextra(argp, ncmd, v, cmd)) == NULL)
263
				goto next;
264
			lg_exec(cmd->earg[0], argp);
265
		}
266
267
 next:
268
		free(argp);
269
		argp = NULL;
270
		free(line);
271
		line = NULL;
272
		cmd = NULL;
273
	}
274
275
	return (0);
276
}