summaryrefslogtreecommitdiff
path: root/usr.bin/bgplg/bgplgsh.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/bgplg/bgplgsh.c')
-rw-r--r--usr.bin/bgplg/bgplgsh.c281
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);
+}