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