diff options
Diffstat (limited to 'usr.bin/bgplg/bgplgsh.c')
-rw-r--r-- | usr.bin/bgplg/bgplgsh.c | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/usr.bin/bgplg/bgplgsh.c b/usr.bin/bgplg/bgplgsh.c new file mode 100644 index 00000000000..ef719699ce6 --- /dev/null +++ b/usr.bin/bgplg/bgplgsh.c @@ -0,0 +1,281 @@ +/* $OpenBSD: bgplgsh.c,v 1.1 2006/12/11 23:10:10 reyk Exp $ */ + +/* + * Copyright (c) 2005, 2006 Reyk Floeter <reyk@vantronix.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/param.h> + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> + +#include <readline/readline.h> +#include <readline/history.h> + +#include "bgplg.h" + +#define BGPDSOCK "/var/www/logs/bgpd.rsock" +#define BGPCTL "/usr/sbin/bgpctl", "-s", BGPDSOCK +#define PING "/sbin/ping" +#define TRACEROUTE "/usr/sbin/traceroute" + +static volatile int quit; + +static struct cmd cmds[] = CMDS; + +char **lg_arg2argv(char *, int *); +char **lg_argextra(char **, int, int, struct cmd *); +int lg_checkarg(char *); +int lg_checkcmd(int, char **, int *, struct cmd *); +char *lg_completion(const char *, int); + +int +lg_checkarg(char *arg) +{ + size_t len; + u_int i; + + if (!(len = strlen(arg))) + return (0); + +#define allowed_in_string(_x) \ + ((isalnum(_x) || isprint(_x)) && \ + (_x != '%' && _x != '\\' && _x != ';' && _x != '&' && _x != '|')) + + for (i = 0; i < len; i++) { + if (!allowed_in_string(arg[i])) { + fprintf(stderr, "invalid character in input\n"); + return (EPERM); + } + } + + return (0); +} + +char ** +lg_arg2argv(char *arg, int *argc) +{ + char **argv, *ptr = arg; + size_t len; + u_int i, c = 1; + + if (lg_checkarg(arg) != 0) + return (NULL); + if (!(len = strlen(arg))) + return (NULL); + + /* Count elements */ + for (i = 0; i < len; i++) { + if (isspace(arg[i])) { + /* filter out additional options */ + if (arg[i + 1] == '-') { + printf("invalid input\n"); + return (NULL); + } + arg[i] = '\0'; + c++; + } + } + if (arg[0] == '\0') + return (NULL); + + /* Generate array */ + if ((argv = calloc(c + 1, sizeof(char *))) == NULL) { + printf("fatal error: %s\n", strerror(errno)); + return (NULL); + } + + argv[c] = NULL; + *argc = c; + + /* Fill array */ + for (i = c = 0; i < len; i++) { + if (arg[i] == '\0' || i == 0) { + if (i != 0) + ptr = &arg[i + 1]; + argv[c++] = ptr; + } + } + + return (argv); +} + +char ** +lg_argextra(char **argv, int argc, int off, struct cmd *cmdp) +{ + char **new_argv; + int i, c = 0, n; + + if ((n = argc - off) < 0) + return (NULL); + + /* Count elements */ + for (i = 0; cmdp->earg[i] != NULL; i++) + c++; + + /* Generate array */ + if ((new_argv = calloc(c + n + 1, sizeof(char *))) == NULL) { + printf("fatal error: %s\n", strerror(errno)); + return (NULL); + } + + /* Fill array */ + for (i = c = 0; cmdp->earg[i] != NULL; i++) + new_argv[c++] = cmdp->earg[i]; + + /* Append old array */ + for (i = n; i < argc; i++) + new_argv[c++] = argv[i]; + + new_argv[c] = NULL; + + if (argv != NULL) + free(argv); + + return (new_argv); +} + +int +lg_checkcmd(int argc, char **argv, int *off, struct cmd *cmd) +{ + char **cmdp = NULL, *cmdstr = NULL; + int i, ncmd, v, ret = -1; + + if ((cmdstr = strdup(cmd->name)) == NULL) + goto done; + if ((cmdp = lg_arg2argv(cmdstr, &ncmd)) == NULL) + goto done; + if (ncmd > argc || argc > (ncmd + cmd->maxargs)) + goto done; + + for (i = 0; i < ncmd; i++) + if (strcmp(argv[i], cmdp[i]) != 0) + goto done; + + if ((v = argc - ncmd) < 0 || + (*off != -1 && *off < v)) + goto done; + if (cmd->minargs && v < cmd->minargs) { + ret = EINVAL; + goto done; + } + *off = v; + ret = 0; + + done: + if (cmdp != NULL) + free(cmdp); + if (cmdstr != NULL) + free(cmdstr); + return (ret); +} + +char * +lg_completion(const char *str, int state) +{ + static int lg_complidx, len; + const char *name; + + if (state == 0) { + len = strlen(str); + lg_complidx = 0; + } + while ((name = cmds[lg_complidx].name) != NULL) { + lg_complidx++; + if (strncmp(name, str, len) == 0) + return (strdup(name)); + } + + return (NULL); +} + +int +main(void) +{ + struct cmd *cmd = NULL; + char prompt[MAXHOSTNAMELEN], *line, **argp = NULL; + int ncmd, ret, v = -1; + u_int i; + + rl_readline_name = NAME; + rl_completion_entry_function = lg_completion; + + /* Ignore the whitespace character */ + rl_basic_word_break_characters = "\t\n\"\\'`@$><=;|&{("; + + while (!quit) { + v = -1; + gethostname(prompt, sizeof(prompt) - 2); + strlcat(prompt, "> ", sizeof(prompt)); + + if ((line = readline(prompt)) == NULL) { + printf("\n"); + lg_help(cmds, NULL); + continue; + } + if (!lg_strip(line)) + goto next; + if (strcmp(line, "exit") == 0) { + quit = 1; + goto next; + } + + add_history(line); + + if ((argp = lg_arg2argv(line, &ncmd)) == NULL) + goto next; + + for (i = 0; cmds[i].name != NULL; i++) { + ret = lg_checkcmd(ncmd, argp, &v, &cmds[i]); + if (ret == 0) + cmd = &cmds[i]; + else if (ret == EINVAL) { + printf("invalid number of arguments\n"); + goto next; + } + } + + if (cmd == NULL) { + printf("invalid command\n"); + } else if (cmd->func != NULL) { + cmd->func(cmds, argp); + } else { + if ((argp = lg_argextra(argp, ncmd, v, cmd)) == NULL) + goto next; + lg_exec(cmd->earg[0], argp); + } + + next: + if (argp != NULL) { + free(argp); + argp = NULL; + } + if (line != NULL) { + free(line); + line = NULL; + } + cmd = NULL; + } + + return (0); +} |