14cf49a43SJulian Elischer 24cf49a43SJulian Elischer /* 34cf49a43SJulian Elischer * main.c 44cf49a43SJulian Elischer * 54cf49a43SJulian Elischer * Copyright (c) 1996-1999 Whistle Communications, Inc. 64cf49a43SJulian Elischer * All rights reserved. 74cf49a43SJulian Elischer * 84cf49a43SJulian Elischer * Subject to the following obligations and disclaimer of warranty, use and 94cf49a43SJulian Elischer * redistribution of this software, in source or object code forms, with or 104cf49a43SJulian Elischer * without modifications are expressly permitted by Whistle Communications; 114cf49a43SJulian Elischer * provided, however, that: 124cf49a43SJulian Elischer * 1. Any and all reproductions of the source or object code must include the 134cf49a43SJulian Elischer * copyright notice above and the following disclaimer of warranties; and 144cf49a43SJulian Elischer * 2. No rights are granted, in any manner or form, to use Whistle 154cf49a43SJulian Elischer * Communications, Inc. trademarks, including the mark "WHISTLE 164cf49a43SJulian Elischer * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 174cf49a43SJulian Elischer * such appears in the above copyright notice or in the software. 184cf49a43SJulian Elischer * 194cf49a43SJulian Elischer * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 204cf49a43SJulian Elischer * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 214cf49a43SJulian Elischer * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 224cf49a43SJulian Elischer * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 234cf49a43SJulian Elischer * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 244cf49a43SJulian Elischer * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 254cf49a43SJulian Elischer * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 264cf49a43SJulian Elischer * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 274cf49a43SJulian Elischer * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 284cf49a43SJulian Elischer * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 294cf49a43SJulian Elischer * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 304cf49a43SJulian Elischer * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 314cf49a43SJulian Elischer * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 324cf49a43SJulian Elischer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 334cf49a43SJulian Elischer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 344cf49a43SJulian Elischer * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 354cf49a43SJulian Elischer * OF SUCH DAMAGE. 364cf49a43SJulian Elischer * 374cf49a43SJulian Elischer * $FreeBSD$ 38f8307e12SArchie Cobbs * $Whistle: main.c,v 1.12 1999/11/29 19:17:46 archie Exp $ 394cf49a43SJulian Elischer */ 404cf49a43SJulian Elischer 414cf49a43SJulian Elischer #include "ngctl.h" 424cf49a43SJulian Elischer 434cf49a43SJulian Elischer #define PROMPT "+ " 444cf49a43SJulian Elischer #define MAX_ARGS 512 454cf49a43SJulian Elischer #define WHITESPACE " \t\r\n\v\f" 46f8307e12SArchie Cobbs #define DUMP_BYTES_PER_LINE 16 474cf49a43SJulian Elischer 484cf49a43SJulian Elischer /* Internal functions */ 494cf49a43SJulian Elischer static int ReadFile(FILE *fp); 504cf49a43SJulian Elischer static int DoParseCommand(char *line); 514cf49a43SJulian Elischer static int DoCommand(int ac, char **av); 524cf49a43SJulian Elischer static int DoInteractive(void); 534cf49a43SJulian Elischer static const struct ngcmd *FindCommand(const char *string); 54f8307e12SArchie Cobbs static int MatchCommand(const struct ngcmd *cmd, const char *s); 554cf49a43SJulian Elischer static void Usage(const char *msg); 564cf49a43SJulian Elischer static int ReadCmd(int ac, char **av); 574cf49a43SJulian Elischer static int HelpCmd(int ac, char **av); 584cf49a43SJulian Elischer static int QuitCmd(int ac, char **av); 594cf49a43SJulian Elischer 604cf49a43SJulian Elischer /* List of commands */ 614cf49a43SJulian Elischer static const struct ngcmd *const cmds[] = { 627095e097SPoul-Henning Kamp &config_cmd, 634cf49a43SJulian Elischer &connect_cmd, 644cf49a43SJulian Elischer &debug_cmd, 654cf49a43SJulian Elischer &help_cmd, 664cf49a43SJulian Elischer &list_cmd, 674cf49a43SJulian Elischer &mkpeer_cmd, 68f8307e12SArchie Cobbs &msg_cmd, 694cf49a43SJulian Elischer &name_cmd, 704cf49a43SJulian Elischer &read_cmd, 714cf49a43SJulian Elischer &rmhook_cmd, 724cf49a43SJulian Elischer &show_cmd, 734cf49a43SJulian Elischer &shutdown_cmd, 744cf49a43SJulian Elischer &status_cmd, 754cf49a43SJulian Elischer &types_cmd, 764cf49a43SJulian Elischer &quit_cmd, 774cf49a43SJulian Elischer NULL 784cf49a43SJulian Elischer }; 794cf49a43SJulian Elischer 804cf49a43SJulian Elischer /* Commands defined in this file */ 814cf49a43SJulian Elischer const struct ngcmd read_cmd = { 824cf49a43SJulian Elischer ReadCmd, 834cf49a43SJulian Elischer "read <filename>", 844cf49a43SJulian Elischer "Read and execute commands from a file", 85f8307e12SArchie Cobbs NULL, 86f8307e12SArchie Cobbs { "source", "." } 874cf49a43SJulian Elischer }; 884cf49a43SJulian Elischer const struct ngcmd help_cmd = { 894cf49a43SJulian Elischer HelpCmd, 904cf49a43SJulian Elischer "help [command]", 914cf49a43SJulian Elischer "Show command summary or get more help on a specific command", 92f8307e12SArchie Cobbs NULL, 93f8307e12SArchie Cobbs { "?" } 944cf49a43SJulian Elischer }; 954cf49a43SJulian Elischer const struct ngcmd quit_cmd = { 964cf49a43SJulian Elischer QuitCmd, 974cf49a43SJulian Elischer "quit", 984cf49a43SJulian Elischer "Exit program", 99f8307e12SArchie Cobbs NULL, 100f8307e12SArchie Cobbs { "exit" } 1014cf49a43SJulian Elischer }; 1024cf49a43SJulian Elischer 1034cf49a43SJulian Elischer /* Our control and data sockets */ 1044cf49a43SJulian Elischer int csock, dsock; 1054cf49a43SJulian Elischer 1064cf49a43SJulian Elischer /* 1074cf49a43SJulian Elischer * main() 1084cf49a43SJulian Elischer */ 1094cf49a43SJulian Elischer int 1104cf49a43SJulian Elischer main(int ac, char *av[]) 1114cf49a43SJulian Elischer { 1124cf49a43SJulian Elischer char name[NG_NODELEN + 1]; 1134cf49a43SJulian Elischer int interactive = isatty(0) && isatty(1); 1144cf49a43SJulian Elischer FILE *fp = NULL; 1154cf49a43SJulian Elischer int ch, rtn = 0; 1164cf49a43SJulian Elischer 1174cf49a43SJulian Elischer /* Set default node name */ 1184cf49a43SJulian Elischer snprintf(name, sizeof(name), "ngctl%d", getpid()); 1194cf49a43SJulian Elischer 1204cf49a43SJulian Elischer /* Parse command line */ 1214cf49a43SJulian Elischer while ((ch = getopt(ac, av, "df:n:")) != EOF) { 1224cf49a43SJulian Elischer switch (ch) { 1234cf49a43SJulian Elischer case 'd': 1244cf49a43SJulian Elischer NgSetDebug(NgSetDebug(-1) + 1); 1254cf49a43SJulian Elischer break; 1264cf49a43SJulian Elischer case 'f': 1274cf49a43SJulian Elischer if (strcmp(optarg, "-") == 0) 1284cf49a43SJulian Elischer fp = stdin; 1294cf49a43SJulian Elischer else if ((fp = fopen(optarg, "r")) == NULL) 1304cf49a43SJulian Elischer err(EX_NOINPUT, "%s", optarg); 1314cf49a43SJulian Elischer break; 1324cf49a43SJulian Elischer case 'n': 1334cf49a43SJulian Elischer snprintf(name, sizeof(name), "%s", optarg); 1344cf49a43SJulian Elischer break; 1354cf49a43SJulian Elischer case '?': 1364cf49a43SJulian Elischer default: 1374cf49a43SJulian Elischer Usage((char *)NULL); 1384cf49a43SJulian Elischer break; 1394cf49a43SJulian Elischer } 1404cf49a43SJulian Elischer } 1414cf49a43SJulian Elischer ac -= optind; 1424cf49a43SJulian Elischer av += optind; 1434cf49a43SJulian Elischer 1444cf49a43SJulian Elischer /* Create a new socket node */ 145b08b2814SArchie Cobbs if (NgMkSockNode(name, &csock, &dsock) < 0) 1464cf49a43SJulian Elischer err(EX_OSERR, "can't create node"); 1474cf49a43SJulian Elischer 1484cf49a43SJulian Elischer /* Do commands as requested */ 1494cf49a43SJulian Elischer if (ac == 0) { 1504cf49a43SJulian Elischer if (fp != NULL) { 1514cf49a43SJulian Elischer rtn = ReadFile(fp); 1524cf49a43SJulian Elischer } else if (interactive) { 1534cf49a43SJulian Elischer rtn = DoInteractive(); 1544cf49a43SJulian Elischer } else 1554cf49a43SJulian Elischer Usage("no command specified"); 1564cf49a43SJulian Elischer } else { 1574cf49a43SJulian Elischer rtn = DoCommand(ac, av); 1584cf49a43SJulian Elischer } 1594cf49a43SJulian Elischer 1604cf49a43SJulian Elischer /* Convert command return code into system exit code */ 1614cf49a43SJulian Elischer switch (rtn) { 1624cf49a43SJulian Elischer case CMDRTN_OK: 1634cf49a43SJulian Elischer case CMDRTN_QUIT: 1644cf49a43SJulian Elischer rtn = 0; 1654cf49a43SJulian Elischer break; 1664cf49a43SJulian Elischer case CMDRTN_USAGE: 1674cf49a43SJulian Elischer rtn = EX_USAGE; 1684cf49a43SJulian Elischer break; 1694cf49a43SJulian Elischer case CMDRTN_ERROR: 1704cf49a43SJulian Elischer rtn = EX_OSERR; 1714cf49a43SJulian Elischer break; 1724cf49a43SJulian Elischer } 1734cf49a43SJulian Elischer return(rtn); 1744cf49a43SJulian Elischer } 1754cf49a43SJulian Elischer 1764cf49a43SJulian Elischer /* 1774cf49a43SJulian Elischer * Process commands from a file 1784cf49a43SJulian Elischer */ 1794cf49a43SJulian Elischer static int 1804cf49a43SJulian Elischer ReadFile(FILE *fp) 1814cf49a43SJulian Elischer { 1824cf49a43SJulian Elischer char line[LINE_MAX]; 1834cf49a43SJulian Elischer int num, rtn; 1844cf49a43SJulian Elischer 1854cf49a43SJulian Elischer for (num = 1; fgets(line, sizeof(line), fp) != NULL; num++) { 1864cf49a43SJulian Elischer if (*line == '#') 1874cf49a43SJulian Elischer continue; 1884cf49a43SJulian Elischer if ((rtn = DoParseCommand(line)) != 0) { 1894cf49a43SJulian Elischer warnx("line %d: error in file", num); 1904cf49a43SJulian Elischer return(rtn); 1914cf49a43SJulian Elischer } 1924cf49a43SJulian Elischer } 1934cf49a43SJulian Elischer return(CMDRTN_OK); 1944cf49a43SJulian Elischer } 1954cf49a43SJulian Elischer 1964cf49a43SJulian Elischer /* 1974cf49a43SJulian Elischer * Interactive mode 1984cf49a43SJulian Elischer */ 1994cf49a43SJulian Elischer static int 2004cf49a43SJulian Elischer DoInteractive(void) 2014cf49a43SJulian Elischer { 202f8307e12SArchie Cobbs const int maxfd = MAX(csock, dsock) + 1; 203f8307e12SArchie Cobbs 204f8307e12SArchie Cobbs (*help_cmd.func)(0, NULL); 205f8307e12SArchie Cobbs while (1) { 206f8307e12SArchie Cobbs struct timeval tv; 207f8307e12SArchie Cobbs fd_set rfds; 208f8307e12SArchie Cobbs 209f8307e12SArchie Cobbs /* See if any data or control messages are arriving */ 210f8307e12SArchie Cobbs FD_ZERO(&rfds); 211f8307e12SArchie Cobbs FD_SET(csock, &rfds); 212f8307e12SArchie Cobbs FD_SET(dsock, &rfds); 213f8307e12SArchie Cobbs memset(&tv, 0, sizeof(tv)); 214f8307e12SArchie Cobbs if (select(maxfd, &rfds, NULL, NULL, &tv) <= 0) { 215f8307e12SArchie Cobbs 216f8307e12SArchie Cobbs /* Issue prompt and wait for anything to happen */ 217f8307e12SArchie Cobbs printf("%s", PROMPT); 218f8307e12SArchie Cobbs fflush(stdout); 219f8307e12SArchie Cobbs FD_ZERO(&rfds); 220f8307e12SArchie Cobbs FD_SET(0, &rfds); 221f8307e12SArchie Cobbs FD_SET(csock, &rfds); 222f8307e12SArchie Cobbs FD_SET(dsock, &rfds); 223f8307e12SArchie Cobbs if (select(maxfd, &rfds, NULL, NULL, NULL) < 0) 224f8307e12SArchie Cobbs err(EX_OSERR, "select"); 225f8307e12SArchie Cobbs 226f8307e12SArchie Cobbs /* If not user input, print a newline first */ 227f8307e12SArchie Cobbs if (!FD_ISSET(0, &rfds)) 228f8307e12SArchie Cobbs printf("\n"); 229f8307e12SArchie Cobbs } 230f8307e12SArchie Cobbs 231f8307e12SArchie Cobbs /* Display any incoming control message */ 2326ebb8ebbSArchie Cobbs if (FD_ISSET(csock, &rfds)) 2336ebb8ebbSArchie Cobbs MsgRead(); 234f8307e12SArchie Cobbs 235f8307e12SArchie Cobbs /* Display any incoming data packet */ 2366ebb8ebbSArchie Cobbs if (FD_ISSET(dsock, &rfds)) { 237f8307e12SArchie Cobbs u_char buf[8192]; 238f8307e12SArchie Cobbs char hook[NG_HOOKLEN + 1]; 239f8307e12SArchie Cobbs int rl; 240f8307e12SArchie Cobbs 241f8307e12SArchie Cobbs /* Read packet from socket */ 242f8307e12SArchie Cobbs if ((rl = NgRecvData(dsock, 243f8307e12SArchie Cobbs buf, sizeof(buf), hook)) < 0) 2446ebb8ebbSArchie Cobbs err(EX_OSERR, "reading hook \"%s\"", hook); 245f8307e12SArchie Cobbs if (rl == 0) 246f8307e12SArchie Cobbs errx(EX_OSERR, "EOF from hook \"%s\"?", hook); 247f8307e12SArchie Cobbs 248f8307e12SArchie Cobbs /* Write packet to stdout */ 249f8307e12SArchie Cobbs printf("Rec'd data packet on hook \"%s\":\n", hook); 250f8307e12SArchie Cobbs DumpAscii(buf, rl); 251f8307e12SArchie Cobbs } 252f8307e12SArchie Cobbs 253f8307e12SArchie Cobbs /* Get any user input */ 254f8307e12SArchie Cobbs if (FD_ISSET(0, &rfds)) { 2554cf49a43SJulian Elischer char buf[LINE_MAX]; 2564cf49a43SJulian Elischer 257f8307e12SArchie Cobbs if (fgets(buf, sizeof(buf), stdin) == NULL) { 258f8307e12SArchie Cobbs printf("\n"); 2594cf49a43SJulian Elischer break; 260f8307e12SArchie Cobbs } 261f8307e12SArchie Cobbs if (DoParseCommand(buf) == CMDRTN_QUIT) 262f8307e12SArchie Cobbs break; 263f8307e12SArchie Cobbs } 264f8307e12SArchie Cobbs } 2654cf49a43SJulian Elischer return(CMDRTN_QUIT); 2664cf49a43SJulian Elischer } 2674cf49a43SJulian Elischer 2684cf49a43SJulian Elischer /* 2694cf49a43SJulian Elischer * Parse a command line and execute the command 2704cf49a43SJulian Elischer */ 2714cf49a43SJulian Elischer static int 2724cf49a43SJulian Elischer DoParseCommand(char *line) 2734cf49a43SJulian Elischer { 2744cf49a43SJulian Elischer char *av[MAX_ARGS]; 2754cf49a43SJulian Elischer int ac; 2764cf49a43SJulian Elischer 2774cf49a43SJulian Elischer /* Parse line */ 2784cf49a43SJulian Elischer for (ac = 0, av[0] = strtok(line, WHITESPACE); 2794cf49a43SJulian Elischer ac < MAX_ARGS - 1 && av[ac]; 2804cf49a43SJulian Elischer av[++ac] = strtok(NULL, WHITESPACE)); 2814cf49a43SJulian Elischer 2824cf49a43SJulian Elischer /* Do command */ 2834cf49a43SJulian Elischer return(DoCommand(ac, av)); 2844cf49a43SJulian Elischer } 2854cf49a43SJulian Elischer 2864cf49a43SJulian Elischer /* 2874cf49a43SJulian Elischer * Execute the command 2884cf49a43SJulian Elischer */ 2894cf49a43SJulian Elischer static int 2904cf49a43SJulian Elischer DoCommand(int ac, char **av) 2914cf49a43SJulian Elischer { 2924cf49a43SJulian Elischer const struct ngcmd *cmd; 2934cf49a43SJulian Elischer int rtn; 2944cf49a43SJulian Elischer 2954cf49a43SJulian Elischer if (ac == 0 || *av[0] == 0) 2964cf49a43SJulian Elischer return(CMDRTN_OK); 2974cf49a43SJulian Elischer if ((cmd = FindCommand(av[0])) == NULL) 2984cf49a43SJulian Elischer return(CMDRTN_ERROR); 2994cf49a43SJulian Elischer if ((rtn = (*cmd->func)(ac, av)) == CMDRTN_USAGE) 3004cf49a43SJulian Elischer warnx("usage: %s", cmd->cmd); 3014cf49a43SJulian Elischer return(rtn); 3024cf49a43SJulian Elischer } 3034cf49a43SJulian Elischer 3044cf49a43SJulian Elischer /* 3054cf49a43SJulian Elischer * Find a command 3064cf49a43SJulian Elischer */ 3074cf49a43SJulian Elischer static const struct ngcmd * 3084cf49a43SJulian Elischer FindCommand(const char *string) 3094cf49a43SJulian Elischer { 310f8307e12SArchie Cobbs int k, found = -1; 3114cf49a43SJulian Elischer 312f8307e12SArchie Cobbs for (k = 0; cmds[k] != NULL; k++) { 313f8307e12SArchie Cobbs if (MatchCommand(cmds[k], string)) { 3144cf49a43SJulian Elischer if (found != -1) { 3154cf49a43SJulian Elischer warnx("\"%s\": ambiguous command", string); 3164cf49a43SJulian Elischer return(NULL); 3174cf49a43SJulian Elischer } 3184cf49a43SJulian Elischer found = k; 3194cf49a43SJulian Elischer } 3204cf49a43SJulian Elischer } 3214cf49a43SJulian Elischer if (found == -1) { 3224cf49a43SJulian Elischer warnx("\"%s\": unknown command", string); 3234cf49a43SJulian Elischer return(NULL); 3244cf49a43SJulian Elischer } 3254cf49a43SJulian Elischer return(cmds[found]); 3264cf49a43SJulian Elischer } 3274cf49a43SJulian Elischer 3284cf49a43SJulian Elischer /* 329f8307e12SArchie Cobbs * See if string matches a prefix of "cmd" (or an alias) case insensitively 330f8307e12SArchie Cobbs */ 331f8307e12SArchie Cobbs static int 332f8307e12SArchie Cobbs MatchCommand(const struct ngcmd *cmd, const char *s) 333f8307e12SArchie Cobbs { 334f8307e12SArchie Cobbs int a; 335f8307e12SArchie Cobbs 336f8307e12SArchie Cobbs /* Try to match command, ignoring the usage stuff */ 337f8307e12SArchie Cobbs if (strlen(s) <= strcspn(cmd->cmd, WHITESPACE)) { 338f8307e12SArchie Cobbs if (strncasecmp(s, cmd->cmd, strlen(s)) == 0) 339f8307e12SArchie Cobbs return (1); 340f8307e12SArchie Cobbs } 341f8307e12SArchie Cobbs 342f8307e12SArchie Cobbs /* Try to match aliases */ 343f8307e12SArchie Cobbs for (a = 0; a < MAX_CMD_ALIAS && cmd->aliases[a] != NULL; a++) { 344f8307e12SArchie Cobbs if (strlen(cmd->aliases[a]) >= strlen(s)) { 345f8307e12SArchie Cobbs if (strncasecmp(s, cmd->aliases[a], strlen(s)) == 0) 346f8307e12SArchie Cobbs return (1); 347f8307e12SArchie Cobbs } 348f8307e12SArchie Cobbs } 349f8307e12SArchie Cobbs 350f8307e12SArchie Cobbs /* No match */ 351f8307e12SArchie Cobbs return (0); 352f8307e12SArchie Cobbs } 353f8307e12SArchie Cobbs 354f8307e12SArchie Cobbs /* 3554cf49a43SJulian Elischer * ReadCmd() 3564cf49a43SJulian Elischer */ 3574cf49a43SJulian Elischer static int 3584cf49a43SJulian Elischer ReadCmd(int ac, char **av) 3594cf49a43SJulian Elischer { 3604cf49a43SJulian Elischer FILE *fp; 3614cf49a43SJulian Elischer int rtn; 3624cf49a43SJulian Elischer 3634cf49a43SJulian Elischer /* Open file */ 3644cf49a43SJulian Elischer switch (ac) { 3654cf49a43SJulian Elischer case 2: 366f35e82dfSArchie Cobbs if ((fp = fopen(av[1], "r")) == NULL) { 3674cf49a43SJulian Elischer warn("%s", av[1]); 3684cf49a43SJulian Elischer return(CMDRTN_ERROR); 369f35e82dfSArchie Cobbs } 370f35e82dfSArchie Cobbs break; 3714cf49a43SJulian Elischer default: 3724cf49a43SJulian Elischer return(CMDRTN_USAGE); 3734cf49a43SJulian Elischer } 3744cf49a43SJulian Elischer 3754cf49a43SJulian Elischer /* Process it */ 3764cf49a43SJulian Elischer rtn = ReadFile(fp); 3774cf49a43SJulian Elischer fclose(fp); 3784cf49a43SJulian Elischer return(rtn); 3794cf49a43SJulian Elischer } 3804cf49a43SJulian Elischer 3814cf49a43SJulian Elischer /* 3824cf49a43SJulian Elischer * HelpCmd() 3834cf49a43SJulian Elischer */ 3844cf49a43SJulian Elischer static int 3854cf49a43SJulian Elischer HelpCmd(int ac, char **av) 3864cf49a43SJulian Elischer { 3874cf49a43SJulian Elischer const struct ngcmd *cmd; 3884cf49a43SJulian Elischer int k; 3894cf49a43SJulian Elischer 3904cf49a43SJulian Elischer switch (ac) { 3914cf49a43SJulian Elischer case 0: 3924cf49a43SJulian Elischer case 1: 3934cf49a43SJulian Elischer /* Show all commands */ 3944cf49a43SJulian Elischer printf("Available commands:\n"); 3954cf49a43SJulian Elischer for (k = 0; cmds[k] != NULL; k++) { 3964cf49a43SJulian Elischer char *s, buf[100]; 3974cf49a43SJulian Elischer 3984cf49a43SJulian Elischer cmd = cmds[k]; 3994cf49a43SJulian Elischer snprintf(buf, sizeof(buf), "%s", cmd->cmd); 4004cf49a43SJulian Elischer for (s = buf; *s != '\0' && !isspace(*s); s++); 4014cf49a43SJulian Elischer *s = '\0'; 4024cf49a43SJulian Elischer printf(" %-10s %s\n", buf, cmd->desc); 4034cf49a43SJulian Elischer } 4044cf49a43SJulian Elischer return(CMDRTN_OK); 4054cf49a43SJulian Elischer default: 4064cf49a43SJulian Elischer /* Show help on a specific command */ 4074cf49a43SJulian Elischer if ((cmd = FindCommand(av[1])) != NULL) { 4084cf49a43SJulian Elischer printf("Usage: %s\n", cmd->cmd); 409f8307e12SArchie Cobbs if (cmd->aliases[0] != NULL) { 410f8307e12SArchie Cobbs int a = 0; 411f8307e12SArchie Cobbs 412f8307e12SArchie Cobbs printf("Aliases: "); 413f8307e12SArchie Cobbs while (1) { 414f8307e12SArchie Cobbs printf("%s", cmd->aliases[a++]); 415f8307e12SArchie Cobbs if (a == MAX_CMD_ALIAS 416f8307e12SArchie Cobbs || cmd->aliases[a] == NULL) { 417f8307e12SArchie Cobbs printf("\n"); 418f8307e12SArchie Cobbs break; 419f8307e12SArchie Cobbs } 420f8307e12SArchie Cobbs printf(", "); 421f8307e12SArchie Cobbs } 422f8307e12SArchie Cobbs } 4234cf49a43SJulian Elischer printf("Summary: %s\n", cmd->desc); 4244cf49a43SJulian Elischer if (cmd->help != NULL) { 4254cf49a43SJulian Elischer const char *s; 4264cf49a43SJulian Elischer char buf[65]; 4274cf49a43SJulian Elischer int tot, len, done; 4284cf49a43SJulian Elischer 4294cf49a43SJulian Elischer printf("Description:\n"); 4304cf49a43SJulian Elischer for (s = cmd->help; *s != '\0'; s += len) { 4314cf49a43SJulian Elischer while (isspace(*s)) 4324cf49a43SJulian Elischer s++; 4334cf49a43SJulian Elischer tot = snprintf(buf, 4344cf49a43SJulian Elischer sizeof(buf), "%s", s); 4354cf49a43SJulian Elischer len = strlen(buf); 4364cf49a43SJulian Elischer done = len == tot; 4374cf49a43SJulian Elischer if (!done) { 4384cf49a43SJulian Elischer while (len > 0 4394cf49a43SJulian Elischer && !isspace(buf[len-1])) 4404cf49a43SJulian Elischer buf[--len] = '\0'; 4414cf49a43SJulian Elischer } 4424cf49a43SJulian Elischer printf(" %s\n", buf); 4434cf49a43SJulian Elischer } 4444cf49a43SJulian Elischer } 4454cf49a43SJulian Elischer } 4464cf49a43SJulian Elischer } 4474cf49a43SJulian Elischer return(CMDRTN_OK); 4484cf49a43SJulian Elischer } 4494cf49a43SJulian Elischer 4504cf49a43SJulian Elischer /* 4514cf49a43SJulian Elischer * QuitCmd() 4524cf49a43SJulian Elischer */ 4534cf49a43SJulian Elischer static int 4544cf49a43SJulian Elischer QuitCmd(int ac, char **av) 4554cf49a43SJulian Elischer { 4564cf49a43SJulian Elischer return(CMDRTN_QUIT); 4574cf49a43SJulian Elischer } 4584cf49a43SJulian Elischer 4594cf49a43SJulian Elischer /* 460f8307e12SArchie Cobbs * Dump data in hex and ASCII form 461f8307e12SArchie Cobbs */ 4626ebb8ebbSArchie Cobbs void 463f8307e12SArchie Cobbs DumpAscii(const u_char *buf, int len) 464f8307e12SArchie Cobbs { 465f8307e12SArchie Cobbs char ch, sbuf[100]; 466f8307e12SArchie Cobbs int k, count; 467f8307e12SArchie Cobbs 468f8307e12SArchie Cobbs for (count = 0; count < len; count += DUMP_BYTES_PER_LINE) { 469f8307e12SArchie Cobbs snprintf(sbuf, sizeof(sbuf), "%04x: ", count); 470f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 471f8307e12SArchie Cobbs if (count + k < len) { 472f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 473f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), 474f8307e12SArchie Cobbs "%02x ", buf[count + k]); 475f8307e12SArchie Cobbs } else { 476f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 477f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 478f8307e12SArchie Cobbs } 479f8307e12SArchie Cobbs } 480f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " "); 481f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 482f8307e12SArchie Cobbs if (count + k < len) { 483f8307e12SArchie Cobbs ch = isprint(buf[count + k]) ? 484f8307e12SArchie Cobbs buf[count + k] : '.'; 485f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 486f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), "%c", ch); 487f8307e12SArchie Cobbs } else { 488f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 489f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 490f8307e12SArchie Cobbs } 491f8307e12SArchie Cobbs } 492f8307e12SArchie Cobbs printf("%s\n", sbuf); 493f8307e12SArchie Cobbs } 494f8307e12SArchie Cobbs } 495f8307e12SArchie Cobbs 496f8307e12SArchie Cobbs /* 4974cf49a43SJulian Elischer * Usage() 4984cf49a43SJulian Elischer */ 4994cf49a43SJulian Elischer static void 5004cf49a43SJulian Elischer Usage(const char *msg) 5014cf49a43SJulian Elischer { 5024cf49a43SJulian Elischer if (msg) 5034cf49a43SJulian Elischer warnx("%s", msg); 5044cf49a43SJulian Elischer errx(EX_USAGE, "usage: ngctl [-d] [-f file] [-n name] [command ...]"); 5054cf49a43SJulian Elischer } 5064cf49a43SJulian Elischer 507