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[] = { 624cf49a43SJulian Elischer &connect_cmd, 634cf49a43SJulian Elischer &debug_cmd, 644cf49a43SJulian Elischer &help_cmd, 654cf49a43SJulian Elischer &list_cmd, 664cf49a43SJulian Elischer &mkpeer_cmd, 67f8307e12SArchie Cobbs &msg_cmd, 684cf49a43SJulian Elischer &name_cmd, 694cf49a43SJulian Elischer &read_cmd, 704cf49a43SJulian Elischer &rmhook_cmd, 714cf49a43SJulian Elischer &show_cmd, 724cf49a43SJulian Elischer &shutdown_cmd, 734cf49a43SJulian Elischer &status_cmd, 744cf49a43SJulian Elischer &types_cmd, 754cf49a43SJulian Elischer &quit_cmd, 764cf49a43SJulian Elischer NULL 774cf49a43SJulian Elischer }; 784cf49a43SJulian Elischer 794cf49a43SJulian Elischer /* Commands defined in this file */ 804cf49a43SJulian Elischer const struct ngcmd read_cmd = { 814cf49a43SJulian Elischer ReadCmd, 824cf49a43SJulian Elischer "read <filename>", 834cf49a43SJulian Elischer "Read and execute commands from a file", 84f8307e12SArchie Cobbs NULL, 85f8307e12SArchie Cobbs { "source", "." } 864cf49a43SJulian Elischer }; 874cf49a43SJulian Elischer const struct ngcmd help_cmd = { 884cf49a43SJulian Elischer HelpCmd, 894cf49a43SJulian Elischer "help [command]", 904cf49a43SJulian Elischer "Show command summary or get more help on a specific command", 91f8307e12SArchie Cobbs NULL, 92f8307e12SArchie Cobbs { "?" } 934cf49a43SJulian Elischer }; 944cf49a43SJulian Elischer const struct ngcmd quit_cmd = { 954cf49a43SJulian Elischer QuitCmd, 964cf49a43SJulian Elischer "quit", 974cf49a43SJulian Elischer "Exit program", 98f8307e12SArchie Cobbs NULL, 99f8307e12SArchie Cobbs { "exit" } 1004cf49a43SJulian Elischer }; 1014cf49a43SJulian Elischer 1024cf49a43SJulian Elischer /* Our control and data sockets */ 1034cf49a43SJulian Elischer int csock, dsock; 1044cf49a43SJulian Elischer 1054cf49a43SJulian Elischer /* 1064cf49a43SJulian Elischer * main() 1074cf49a43SJulian Elischer */ 1084cf49a43SJulian Elischer int 1094cf49a43SJulian Elischer main(int ac, char *av[]) 1104cf49a43SJulian Elischer { 1114cf49a43SJulian Elischer char name[NG_NODELEN + 1]; 1124cf49a43SJulian Elischer int interactive = isatty(0) && isatty(1); 1134cf49a43SJulian Elischer FILE *fp = NULL; 1144cf49a43SJulian Elischer int ch, rtn = 0; 1154cf49a43SJulian Elischer 1164cf49a43SJulian Elischer /* Set default node name */ 1174cf49a43SJulian Elischer snprintf(name, sizeof(name), "ngctl%d", getpid()); 1184cf49a43SJulian Elischer 1194cf49a43SJulian Elischer /* Parse command line */ 1204cf49a43SJulian Elischer while ((ch = getopt(ac, av, "df:n:")) != EOF) { 1214cf49a43SJulian Elischer switch (ch) { 1224cf49a43SJulian Elischer case 'd': 1234cf49a43SJulian Elischer NgSetDebug(NgSetDebug(-1) + 1); 1244cf49a43SJulian Elischer break; 1254cf49a43SJulian Elischer case 'f': 1264cf49a43SJulian Elischer if (strcmp(optarg, "-") == 0) 1274cf49a43SJulian Elischer fp = stdin; 1284cf49a43SJulian Elischer else if ((fp = fopen(optarg, "r")) == NULL) 1294cf49a43SJulian Elischer err(EX_NOINPUT, "%s", optarg); 1304cf49a43SJulian Elischer break; 1314cf49a43SJulian Elischer case 'n': 1324cf49a43SJulian Elischer snprintf(name, sizeof(name), "%s", optarg); 1334cf49a43SJulian Elischer break; 1344cf49a43SJulian Elischer case '?': 1354cf49a43SJulian Elischer default: 1364cf49a43SJulian Elischer Usage((char *)NULL); 1374cf49a43SJulian Elischer break; 1384cf49a43SJulian Elischer } 1394cf49a43SJulian Elischer } 1404cf49a43SJulian Elischer ac -= optind; 1414cf49a43SJulian Elischer av += optind; 1424cf49a43SJulian Elischer 1434cf49a43SJulian Elischer /* Create a new socket node */ 144b08b2814SArchie Cobbs if (NgMkSockNode(name, &csock, &dsock) < 0) 1454cf49a43SJulian Elischer err(EX_OSERR, "can't create node"); 1464cf49a43SJulian Elischer 1474cf49a43SJulian Elischer /* Do commands as requested */ 1484cf49a43SJulian Elischer if (ac == 0) { 1494cf49a43SJulian Elischer if (fp != NULL) { 1504cf49a43SJulian Elischer rtn = ReadFile(fp); 1514cf49a43SJulian Elischer } else if (interactive) { 1524cf49a43SJulian Elischer rtn = DoInteractive(); 1534cf49a43SJulian Elischer } else 1544cf49a43SJulian Elischer Usage("no command specified"); 1554cf49a43SJulian Elischer } else { 1564cf49a43SJulian Elischer rtn = DoCommand(ac, av); 1574cf49a43SJulian Elischer } 1584cf49a43SJulian Elischer 1594cf49a43SJulian Elischer /* Convert command return code into system exit code */ 1604cf49a43SJulian Elischer switch (rtn) { 1614cf49a43SJulian Elischer case CMDRTN_OK: 1624cf49a43SJulian Elischer case CMDRTN_QUIT: 1634cf49a43SJulian Elischer rtn = 0; 1644cf49a43SJulian Elischer break; 1654cf49a43SJulian Elischer case CMDRTN_USAGE: 1664cf49a43SJulian Elischer rtn = EX_USAGE; 1674cf49a43SJulian Elischer break; 1684cf49a43SJulian Elischer case CMDRTN_ERROR: 1694cf49a43SJulian Elischer rtn = EX_OSERR; 1704cf49a43SJulian Elischer break; 1714cf49a43SJulian Elischer } 1724cf49a43SJulian Elischer return(rtn); 1734cf49a43SJulian Elischer } 1744cf49a43SJulian Elischer 1754cf49a43SJulian Elischer /* 1764cf49a43SJulian Elischer * Process commands from a file 1774cf49a43SJulian Elischer */ 1784cf49a43SJulian Elischer static int 1794cf49a43SJulian Elischer ReadFile(FILE *fp) 1804cf49a43SJulian Elischer { 1814cf49a43SJulian Elischer char line[LINE_MAX]; 1824cf49a43SJulian Elischer int num, rtn; 1834cf49a43SJulian Elischer 1844cf49a43SJulian Elischer for (num = 1; fgets(line, sizeof(line), fp) != NULL; num++) { 1854cf49a43SJulian Elischer if (*line == '#') 1864cf49a43SJulian Elischer continue; 1874cf49a43SJulian Elischer if ((rtn = DoParseCommand(line)) != 0) { 1884cf49a43SJulian Elischer warnx("line %d: error in file", num); 1894cf49a43SJulian Elischer return(rtn); 1904cf49a43SJulian Elischer } 1914cf49a43SJulian Elischer } 1924cf49a43SJulian Elischer return(CMDRTN_OK); 1934cf49a43SJulian Elischer } 1944cf49a43SJulian Elischer 1954cf49a43SJulian Elischer /* 1964cf49a43SJulian Elischer * Interactive mode 1974cf49a43SJulian Elischer */ 1984cf49a43SJulian Elischer static int 1994cf49a43SJulian Elischer DoInteractive(void) 2004cf49a43SJulian Elischer { 201f8307e12SArchie Cobbs const int maxfd = MAX(csock, dsock) + 1; 202f8307e12SArchie Cobbs 203f8307e12SArchie Cobbs (*help_cmd.func)(0, NULL); 204f8307e12SArchie Cobbs while (1) { 205f8307e12SArchie Cobbs struct timeval tv; 206f8307e12SArchie Cobbs fd_set rfds; 207f8307e12SArchie Cobbs 208f8307e12SArchie Cobbs /* See if any data or control messages are arriving */ 209f8307e12SArchie Cobbs FD_ZERO(&rfds); 210f8307e12SArchie Cobbs FD_SET(csock, &rfds); 211f8307e12SArchie Cobbs FD_SET(dsock, &rfds); 212f8307e12SArchie Cobbs memset(&tv, 0, sizeof(tv)); 213f8307e12SArchie Cobbs if (select(maxfd, &rfds, NULL, NULL, &tv) <= 0) { 214f8307e12SArchie Cobbs 215f8307e12SArchie Cobbs /* Issue prompt and wait for anything to happen */ 216f8307e12SArchie Cobbs printf("%s", PROMPT); 217f8307e12SArchie Cobbs fflush(stdout); 218f8307e12SArchie Cobbs FD_ZERO(&rfds); 219f8307e12SArchie Cobbs FD_SET(0, &rfds); 220f8307e12SArchie Cobbs FD_SET(csock, &rfds); 221f8307e12SArchie Cobbs FD_SET(dsock, &rfds); 222f8307e12SArchie Cobbs if (select(maxfd, &rfds, NULL, NULL, NULL) < 0) 223f8307e12SArchie Cobbs err(EX_OSERR, "select"); 224f8307e12SArchie Cobbs 225f8307e12SArchie Cobbs /* If not user input, print a newline first */ 226f8307e12SArchie Cobbs if (!FD_ISSET(0, &rfds)) 227f8307e12SArchie Cobbs printf("\n"); 228f8307e12SArchie Cobbs } 229f8307e12SArchie Cobbs 230f8307e12SArchie Cobbs /* Display any incoming control message */ 2316ebb8ebbSArchie Cobbs if (FD_ISSET(csock, &rfds)) 2326ebb8ebbSArchie Cobbs MsgRead(); 233f8307e12SArchie Cobbs 234f8307e12SArchie Cobbs /* Display any incoming data packet */ 2356ebb8ebbSArchie Cobbs if (FD_ISSET(dsock, &rfds)) { 236f8307e12SArchie Cobbs u_char buf[8192]; 237f8307e12SArchie Cobbs char hook[NG_HOOKLEN + 1]; 238f8307e12SArchie Cobbs int rl; 239f8307e12SArchie Cobbs 240f8307e12SArchie Cobbs /* Read packet from socket */ 241f8307e12SArchie Cobbs if ((rl = NgRecvData(dsock, 242f8307e12SArchie Cobbs buf, sizeof(buf), hook)) < 0) 2436ebb8ebbSArchie Cobbs err(EX_OSERR, "reading hook \"%s\"", hook); 244f8307e12SArchie Cobbs if (rl == 0) 245f8307e12SArchie Cobbs errx(EX_OSERR, "EOF from hook \"%s\"?", hook); 246f8307e12SArchie Cobbs 247f8307e12SArchie Cobbs /* Write packet to stdout */ 248f8307e12SArchie Cobbs printf("Rec'd data packet on hook \"%s\":\n", hook); 249f8307e12SArchie Cobbs DumpAscii(buf, rl); 250f8307e12SArchie Cobbs } 251f8307e12SArchie Cobbs 252f8307e12SArchie Cobbs /* Get any user input */ 253f8307e12SArchie Cobbs if (FD_ISSET(0, &rfds)) { 2544cf49a43SJulian Elischer char buf[LINE_MAX]; 2554cf49a43SJulian Elischer 256f8307e12SArchie Cobbs if (fgets(buf, sizeof(buf), stdin) == NULL) { 257f8307e12SArchie Cobbs printf("\n"); 2584cf49a43SJulian Elischer break; 259f8307e12SArchie Cobbs } 260f8307e12SArchie Cobbs if (DoParseCommand(buf) == CMDRTN_QUIT) 261f8307e12SArchie Cobbs break; 262f8307e12SArchie Cobbs } 263f8307e12SArchie Cobbs } 2644cf49a43SJulian Elischer return(CMDRTN_QUIT); 2654cf49a43SJulian Elischer } 2664cf49a43SJulian Elischer 2674cf49a43SJulian Elischer /* 2684cf49a43SJulian Elischer * Parse a command line and execute the command 2694cf49a43SJulian Elischer */ 2704cf49a43SJulian Elischer static int 2714cf49a43SJulian Elischer DoParseCommand(char *line) 2724cf49a43SJulian Elischer { 2734cf49a43SJulian Elischer char *av[MAX_ARGS]; 2744cf49a43SJulian Elischer int ac; 2754cf49a43SJulian Elischer 2764cf49a43SJulian Elischer /* Parse line */ 2774cf49a43SJulian Elischer for (ac = 0, av[0] = strtok(line, WHITESPACE); 2784cf49a43SJulian Elischer ac < MAX_ARGS - 1 && av[ac]; 2794cf49a43SJulian Elischer av[++ac] = strtok(NULL, WHITESPACE)); 2804cf49a43SJulian Elischer 2814cf49a43SJulian Elischer /* Do command */ 2824cf49a43SJulian Elischer return(DoCommand(ac, av)); 2834cf49a43SJulian Elischer } 2844cf49a43SJulian Elischer 2854cf49a43SJulian Elischer /* 2864cf49a43SJulian Elischer * Execute the command 2874cf49a43SJulian Elischer */ 2884cf49a43SJulian Elischer static int 2894cf49a43SJulian Elischer DoCommand(int ac, char **av) 2904cf49a43SJulian Elischer { 2914cf49a43SJulian Elischer const struct ngcmd *cmd; 2924cf49a43SJulian Elischer int rtn; 2934cf49a43SJulian Elischer 2944cf49a43SJulian Elischer if (ac == 0 || *av[0] == 0) 2954cf49a43SJulian Elischer return(CMDRTN_OK); 2964cf49a43SJulian Elischer if ((cmd = FindCommand(av[0])) == NULL) 2974cf49a43SJulian Elischer return(CMDRTN_ERROR); 2984cf49a43SJulian Elischer if ((rtn = (*cmd->func)(ac, av)) == CMDRTN_USAGE) 2994cf49a43SJulian Elischer warnx("usage: %s", cmd->cmd); 3004cf49a43SJulian Elischer return(rtn); 3014cf49a43SJulian Elischer } 3024cf49a43SJulian Elischer 3034cf49a43SJulian Elischer /* 3044cf49a43SJulian Elischer * Find a command 3054cf49a43SJulian Elischer */ 3064cf49a43SJulian Elischer static const struct ngcmd * 3074cf49a43SJulian Elischer FindCommand(const char *string) 3084cf49a43SJulian Elischer { 309f8307e12SArchie Cobbs int k, found = -1; 3104cf49a43SJulian Elischer 311f8307e12SArchie Cobbs for (k = 0; cmds[k] != NULL; k++) { 312f8307e12SArchie Cobbs if (MatchCommand(cmds[k], string)) { 3134cf49a43SJulian Elischer if (found != -1) { 3144cf49a43SJulian Elischer warnx("\"%s\": ambiguous command", string); 3154cf49a43SJulian Elischer return(NULL); 3164cf49a43SJulian Elischer } 3174cf49a43SJulian Elischer found = k; 3184cf49a43SJulian Elischer } 3194cf49a43SJulian Elischer } 3204cf49a43SJulian Elischer if (found == -1) { 3214cf49a43SJulian Elischer warnx("\"%s\": unknown command", string); 3224cf49a43SJulian Elischer return(NULL); 3234cf49a43SJulian Elischer } 3244cf49a43SJulian Elischer return(cmds[found]); 3254cf49a43SJulian Elischer } 3264cf49a43SJulian Elischer 3274cf49a43SJulian Elischer /* 328f8307e12SArchie Cobbs * See if string matches a prefix of "cmd" (or an alias) case insensitively 329f8307e12SArchie Cobbs */ 330f8307e12SArchie Cobbs static int 331f8307e12SArchie Cobbs MatchCommand(const struct ngcmd *cmd, const char *s) 332f8307e12SArchie Cobbs { 333f8307e12SArchie Cobbs int a; 334f8307e12SArchie Cobbs 335f8307e12SArchie Cobbs /* Try to match command, ignoring the usage stuff */ 336f8307e12SArchie Cobbs if (strlen(s) <= strcspn(cmd->cmd, WHITESPACE)) { 337f8307e12SArchie Cobbs if (strncasecmp(s, cmd->cmd, strlen(s)) == 0) 338f8307e12SArchie Cobbs return (1); 339f8307e12SArchie Cobbs } 340f8307e12SArchie Cobbs 341f8307e12SArchie Cobbs /* Try to match aliases */ 342f8307e12SArchie Cobbs for (a = 0; a < MAX_CMD_ALIAS && cmd->aliases[a] != NULL; a++) { 343f8307e12SArchie Cobbs if (strlen(cmd->aliases[a]) >= strlen(s)) { 344f8307e12SArchie Cobbs if (strncasecmp(s, cmd->aliases[a], strlen(s)) == 0) 345f8307e12SArchie Cobbs return (1); 346f8307e12SArchie Cobbs } 347f8307e12SArchie Cobbs } 348f8307e12SArchie Cobbs 349f8307e12SArchie Cobbs /* No match */ 350f8307e12SArchie Cobbs return (0); 351f8307e12SArchie Cobbs } 352f8307e12SArchie Cobbs 353f8307e12SArchie Cobbs /* 3544cf49a43SJulian Elischer * ReadCmd() 3554cf49a43SJulian Elischer */ 3564cf49a43SJulian Elischer static int 3574cf49a43SJulian Elischer ReadCmd(int ac, char **av) 3584cf49a43SJulian Elischer { 3594cf49a43SJulian Elischer FILE *fp; 3604cf49a43SJulian Elischer int rtn; 3614cf49a43SJulian Elischer 3624cf49a43SJulian Elischer /* Open file */ 3634cf49a43SJulian Elischer switch (ac) { 3644cf49a43SJulian Elischer case 2: 3654cf49a43SJulian Elischer if ((fp = fopen(av[1], "r")) == NULL) 3664cf49a43SJulian Elischer warn("%s", av[1]); 3674cf49a43SJulian Elischer return(CMDRTN_ERROR); 3684cf49a43SJulian Elischer default: 3694cf49a43SJulian Elischer return(CMDRTN_USAGE); 3704cf49a43SJulian Elischer } 3714cf49a43SJulian Elischer 3724cf49a43SJulian Elischer /* Process it */ 3734cf49a43SJulian Elischer rtn = ReadFile(fp); 3744cf49a43SJulian Elischer fclose(fp); 3754cf49a43SJulian Elischer return(rtn); 3764cf49a43SJulian Elischer } 3774cf49a43SJulian Elischer 3784cf49a43SJulian Elischer /* 3794cf49a43SJulian Elischer * HelpCmd() 3804cf49a43SJulian Elischer */ 3814cf49a43SJulian Elischer static int 3824cf49a43SJulian Elischer HelpCmd(int ac, char **av) 3834cf49a43SJulian Elischer { 3844cf49a43SJulian Elischer const struct ngcmd *cmd; 3854cf49a43SJulian Elischer int k; 3864cf49a43SJulian Elischer 3874cf49a43SJulian Elischer switch (ac) { 3884cf49a43SJulian Elischer case 0: 3894cf49a43SJulian Elischer case 1: 3904cf49a43SJulian Elischer /* Show all commands */ 3914cf49a43SJulian Elischer printf("Available commands:\n"); 3924cf49a43SJulian Elischer for (k = 0; cmds[k] != NULL; k++) { 3934cf49a43SJulian Elischer char *s, buf[100]; 3944cf49a43SJulian Elischer 3954cf49a43SJulian Elischer cmd = cmds[k]; 3964cf49a43SJulian Elischer snprintf(buf, sizeof(buf), "%s", cmd->cmd); 3974cf49a43SJulian Elischer for (s = buf; *s != '\0' && !isspace(*s); s++); 3984cf49a43SJulian Elischer *s = '\0'; 3994cf49a43SJulian Elischer printf(" %-10s %s\n", buf, cmd->desc); 4004cf49a43SJulian Elischer } 4014cf49a43SJulian Elischer return(CMDRTN_OK); 4024cf49a43SJulian Elischer default: 4034cf49a43SJulian Elischer /* Show help on a specific command */ 4044cf49a43SJulian Elischer if ((cmd = FindCommand(av[1])) != NULL) { 4054cf49a43SJulian Elischer printf("Usage: %s\n", cmd->cmd); 406f8307e12SArchie Cobbs if (cmd->aliases[0] != NULL) { 407f8307e12SArchie Cobbs int a = 0; 408f8307e12SArchie Cobbs 409f8307e12SArchie Cobbs printf("Aliases: "); 410f8307e12SArchie Cobbs while (1) { 411f8307e12SArchie Cobbs printf("%s", cmd->aliases[a++]); 412f8307e12SArchie Cobbs if (a == MAX_CMD_ALIAS 413f8307e12SArchie Cobbs || cmd->aliases[a] == NULL) { 414f8307e12SArchie Cobbs printf("\n"); 415f8307e12SArchie Cobbs break; 416f8307e12SArchie Cobbs } 417f8307e12SArchie Cobbs printf(", "); 418f8307e12SArchie Cobbs } 419f8307e12SArchie Cobbs } 4204cf49a43SJulian Elischer printf("Summary: %s\n", cmd->desc); 4214cf49a43SJulian Elischer if (cmd->help != NULL) { 4224cf49a43SJulian Elischer const char *s; 4234cf49a43SJulian Elischer char buf[65]; 4244cf49a43SJulian Elischer int tot, len, done; 4254cf49a43SJulian Elischer 4264cf49a43SJulian Elischer printf("Description:\n"); 4274cf49a43SJulian Elischer for (s = cmd->help; *s != '\0'; s += len) { 4284cf49a43SJulian Elischer while (isspace(*s)) 4294cf49a43SJulian Elischer s++; 4304cf49a43SJulian Elischer tot = snprintf(buf, 4314cf49a43SJulian Elischer sizeof(buf), "%s", s); 4324cf49a43SJulian Elischer len = strlen(buf); 4334cf49a43SJulian Elischer done = len == tot; 4344cf49a43SJulian Elischer if (!done) { 4354cf49a43SJulian Elischer while (len > 0 4364cf49a43SJulian Elischer && !isspace(buf[len-1])) 4374cf49a43SJulian Elischer buf[--len] = '\0'; 4384cf49a43SJulian Elischer } 4394cf49a43SJulian Elischer printf(" %s\n", buf); 4404cf49a43SJulian Elischer } 4414cf49a43SJulian Elischer } 4424cf49a43SJulian Elischer } 4434cf49a43SJulian Elischer } 4444cf49a43SJulian Elischer return(CMDRTN_OK); 4454cf49a43SJulian Elischer } 4464cf49a43SJulian Elischer 4474cf49a43SJulian Elischer /* 4484cf49a43SJulian Elischer * QuitCmd() 4494cf49a43SJulian Elischer */ 4504cf49a43SJulian Elischer static int 4514cf49a43SJulian Elischer QuitCmd(int ac, char **av) 4524cf49a43SJulian Elischer { 4534cf49a43SJulian Elischer return(CMDRTN_QUIT); 4544cf49a43SJulian Elischer } 4554cf49a43SJulian Elischer 4564cf49a43SJulian Elischer /* 457f8307e12SArchie Cobbs * Dump data in hex and ASCII form 458f8307e12SArchie Cobbs */ 4596ebb8ebbSArchie Cobbs void 460f8307e12SArchie Cobbs DumpAscii(const u_char *buf, int len) 461f8307e12SArchie Cobbs { 462f8307e12SArchie Cobbs char ch, sbuf[100]; 463f8307e12SArchie Cobbs int k, count; 464f8307e12SArchie Cobbs 465f8307e12SArchie Cobbs for (count = 0; count < len; count += DUMP_BYTES_PER_LINE) { 466f8307e12SArchie Cobbs snprintf(sbuf, sizeof(sbuf), "%04x: ", count); 467f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 468f8307e12SArchie Cobbs if (count + k < len) { 469f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 470f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), 471f8307e12SArchie Cobbs "%02x ", buf[count + k]); 472f8307e12SArchie Cobbs } else { 473f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 474f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 475f8307e12SArchie Cobbs } 476f8307e12SArchie Cobbs } 477f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " "); 478f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 479f8307e12SArchie Cobbs if (count + k < len) { 480f8307e12SArchie Cobbs ch = isprint(buf[count + k]) ? 481f8307e12SArchie Cobbs buf[count + k] : '.'; 482f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 483f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), "%c", ch); 484f8307e12SArchie Cobbs } else { 485f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 486f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 487f8307e12SArchie Cobbs } 488f8307e12SArchie Cobbs } 489f8307e12SArchie Cobbs printf("%s\n", sbuf); 490f8307e12SArchie Cobbs } 491f8307e12SArchie Cobbs } 492f8307e12SArchie Cobbs 493f8307e12SArchie Cobbs /* 4944cf49a43SJulian Elischer * Usage() 4954cf49a43SJulian Elischer */ 4964cf49a43SJulian Elischer static void 4974cf49a43SJulian Elischer Usage(const char *msg) 4984cf49a43SJulian Elischer { 4994cf49a43SJulian Elischer if (msg) 5004cf49a43SJulian Elischer warnx("%s", msg); 5014cf49a43SJulian Elischer errx(EX_USAGE, "usage: ngctl [-d] [-f file] [-n name] [command ...]"); 5024cf49a43SJulian Elischer } 5034cf49a43SJulian Elischer 504