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, 65bbd6d60aSBrian Feldman &dot_cmd, 664cf49a43SJulian Elischer &help_cmd, 674cf49a43SJulian Elischer &list_cmd, 684cf49a43SJulian Elischer &mkpeer_cmd, 69f8307e12SArchie Cobbs &msg_cmd, 704cf49a43SJulian Elischer &name_cmd, 714cf49a43SJulian Elischer &read_cmd, 724cf49a43SJulian Elischer &rmhook_cmd, 734cf49a43SJulian Elischer &show_cmd, 744cf49a43SJulian Elischer &shutdown_cmd, 754cf49a43SJulian Elischer &status_cmd, 764cf49a43SJulian Elischer &types_cmd, 77be44fce4SArchie Cobbs &write_cmd, 784cf49a43SJulian Elischer &quit_cmd, 794cf49a43SJulian Elischer NULL 804cf49a43SJulian Elischer }; 814cf49a43SJulian Elischer 824cf49a43SJulian Elischer /* Commands defined in this file */ 834cf49a43SJulian Elischer const struct ngcmd read_cmd = { 844cf49a43SJulian Elischer ReadCmd, 854cf49a43SJulian Elischer "read <filename>", 864cf49a43SJulian Elischer "Read and execute commands from a file", 87f8307e12SArchie Cobbs NULL, 88f8307e12SArchie Cobbs { "source", "." } 894cf49a43SJulian Elischer }; 904cf49a43SJulian Elischer const struct ngcmd help_cmd = { 914cf49a43SJulian Elischer HelpCmd, 924cf49a43SJulian Elischer "help [command]", 934cf49a43SJulian Elischer "Show command summary or get more help on a specific command", 94f8307e12SArchie Cobbs NULL, 95f8307e12SArchie Cobbs { "?" } 964cf49a43SJulian Elischer }; 974cf49a43SJulian Elischer const struct ngcmd quit_cmd = { 984cf49a43SJulian Elischer QuitCmd, 994cf49a43SJulian Elischer "quit", 1004cf49a43SJulian Elischer "Exit program", 101f8307e12SArchie Cobbs NULL, 102f8307e12SArchie Cobbs { "exit" } 1034cf49a43SJulian Elischer }; 1044cf49a43SJulian Elischer 1054cf49a43SJulian Elischer /* Our control and data sockets */ 1064cf49a43SJulian Elischer int csock, dsock; 1074cf49a43SJulian Elischer 1084cf49a43SJulian Elischer /* 1094cf49a43SJulian Elischer * main() 1104cf49a43SJulian Elischer */ 1114cf49a43SJulian Elischer int 1124cf49a43SJulian Elischer main(int ac, char *av[]) 1134cf49a43SJulian Elischer { 1149d901d3bSHartmut Brandt char name[NG_NODESIZ]; 1154cf49a43SJulian Elischer int interactive = isatty(0) && isatty(1); 1164cf49a43SJulian Elischer FILE *fp = NULL; 1174cf49a43SJulian Elischer int ch, rtn = 0; 1184cf49a43SJulian Elischer 1194cf49a43SJulian Elischer /* Set default node name */ 1204cf49a43SJulian Elischer snprintf(name, sizeof(name), "ngctl%d", getpid()); 1214cf49a43SJulian Elischer 1224cf49a43SJulian Elischer /* Parse command line */ 1234cf49a43SJulian Elischer while ((ch = getopt(ac, av, "df:n:")) != EOF) { 1244cf49a43SJulian Elischer switch (ch) { 1254cf49a43SJulian Elischer case 'd': 1264cf49a43SJulian Elischer NgSetDebug(NgSetDebug(-1) + 1); 1274cf49a43SJulian Elischer break; 1284cf49a43SJulian Elischer case 'f': 1294cf49a43SJulian Elischer if (strcmp(optarg, "-") == 0) 1304cf49a43SJulian Elischer fp = stdin; 1314cf49a43SJulian Elischer else if ((fp = fopen(optarg, "r")) == NULL) 1324cf49a43SJulian Elischer err(EX_NOINPUT, "%s", optarg); 1334cf49a43SJulian Elischer break; 1344cf49a43SJulian Elischer case 'n': 1354cf49a43SJulian Elischer snprintf(name, sizeof(name), "%s", optarg); 1364cf49a43SJulian Elischer break; 1374cf49a43SJulian Elischer case '?': 1384cf49a43SJulian Elischer default: 1394cf49a43SJulian Elischer Usage((char *)NULL); 1404cf49a43SJulian Elischer break; 1414cf49a43SJulian Elischer } 1424cf49a43SJulian Elischer } 1434cf49a43SJulian Elischer ac -= optind; 1444cf49a43SJulian Elischer av += optind; 1454cf49a43SJulian Elischer 1464cf49a43SJulian Elischer /* Create a new socket node */ 147b08b2814SArchie Cobbs if (NgMkSockNode(name, &csock, &dsock) < 0) 1484cf49a43SJulian Elischer err(EX_OSERR, "can't create node"); 1494cf49a43SJulian Elischer 1504cf49a43SJulian Elischer /* Do commands as requested */ 1514cf49a43SJulian Elischer if (ac == 0) { 1524cf49a43SJulian Elischer if (fp != NULL) { 1534cf49a43SJulian Elischer rtn = ReadFile(fp); 1544cf49a43SJulian Elischer } else if (interactive) { 1554cf49a43SJulian Elischer rtn = DoInteractive(); 1564cf49a43SJulian Elischer } else 1574cf49a43SJulian Elischer Usage("no command specified"); 1584cf49a43SJulian Elischer } else { 1594cf49a43SJulian Elischer rtn = DoCommand(ac, av); 1604cf49a43SJulian Elischer } 1614cf49a43SJulian Elischer 1624cf49a43SJulian Elischer /* Convert command return code into system exit code */ 1634cf49a43SJulian Elischer switch (rtn) { 1644cf49a43SJulian Elischer case CMDRTN_OK: 1654cf49a43SJulian Elischer case CMDRTN_QUIT: 1664cf49a43SJulian Elischer rtn = 0; 1674cf49a43SJulian Elischer break; 1684cf49a43SJulian Elischer case CMDRTN_USAGE: 1694cf49a43SJulian Elischer rtn = EX_USAGE; 1704cf49a43SJulian Elischer break; 1714cf49a43SJulian Elischer case CMDRTN_ERROR: 1724cf49a43SJulian Elischer rtn = EX_OSERR; 1734cf49a43SJulian Elischer break; 1744cf49a43SJulian Elischer } 1754cf49a43SJulian Elischer return(rtn); 1764cf49a43SJulian Elischer } 1774cf49a43SJulian Elischer 1784cf49a43SJulian Elischer /* 1794cf49a43SJulian Elischer * Process commands from a file 1804cf49a43SJulian Elischer */ 1814cf49a43SJulian Elischer static int 1824cf49a43SJulian Elischer ReadFile(FILE *fp) 1834cf49a43SJulian Elischer { 1844cf49a43SJulian Elischer char line[LINE_MAX]; 1854cf49a43SJulian Elischer int num, rtn; 1864cf49a43SJulian Elischer 1874cf49a43SJulian Elischer for (num = 1; fgets(line, sizeof(line), fp) != NULL; num++) { 1884cf49a43SJulian Elischer if (*line == '#') 1894cf49a43SJulian Elischer continue; 1904cf49a43SJulian Elischer if ((rtn = DoParseCommand(line)) != 0) { 1914cf49a43SJulian Elischer warnx("line %d: error in file", num); 1924cf49a43SJulian Elischer return(rtn); 1934cf49a43SJulian Elischer } 1944cf49a43SJulian Elischer } 1954cf49a43SJulian Elischer return(CMDRTN_OK); 1964cf49a43SJulian Elischer } 1974cf49a43SJulian Elischer 1984cf49a43SJulian Elischer /* 1994cf49a43SJulian Elischer * Interactive mode 2004cf49a43SJulian Elischer */ 2014cf49a43SJulian Elischer static int 2024cf49a43SJulian Elischer DoInteractive(void) 2034cf49a43SJulian Elischer { 204f8307e12SArchie Cobbs const int maxfd = MAX(csock, dsock) + 1; 205f8307e12SArchie Cobbs 206f8307e12SArchie Cobbs (*help_cmd.func)(0, NULL); 207f8307e12SArchie Cobbs while (1) { 208f8307e12SArchie Cobbs struct timeval tv; 209f8307e12SArchie Cobbs fd_set rfds; 210f8307e12SArchie Cobbs 211f8307e12SArchie Cobbs /* See if any data or control messages are arriving */ 212f8307e12SArchie Cobbs FD_ZERO(&rfds); 213f8307e12SArchie Cobbs FD_SET(csock, &rfds); 214f8307e12SArchie Cobbs FD_SET(dsock, &rfds); 215f8307e12SArchie Cobbs memset(&tv, 0, sizeof(tv)); 216f8307e12SArchie Cobbs if (select(maxfd, &rfds, NULL, NULL, &tv) <= 0) { 217f8307e12SArchie Cobbs 218f8307e12SArchie Cobbs /* Issue prompt and wait for anything to happen */ 219f8307e12SArchie Cobbs printf("%s", PROMPT); 220f8307e12SArchie Cobbs fflush(stdout); 221f8307e12SArchie Cobbs FD_ZERO(&rfds); 222f8307e12SArchie Cobbs FD_SET(0, &rfds); 223f8307e12SArchie Cobbs FD_SET(csock, &rfds); 224f8307e12SArchie Cobbs FD_SET(dsock, &rfds); 225f8307e12SArchie Cobbs if (select(maxfd, &rfds, NULL, NULL, NULL) < 0) 226f8307e12SArchie Cobbs err(EX_OSERR, "select"); 227f8307e12SArchie Cobbs 228f8307e12SArchie Cobbs /* If not user input, print a newline first */ 229f8307e12SArchie Cobbs if (!FD_ISSET(0, &rfds)) 230f8307e12SArchie Cobbs printf("\n"); 231f8307e12SArchie Cobbs } 232f8307e12SArchie Cobbs 233f8307e12SArchie Cobbs /* Display any incoming control message */ 2346ebb8ebbSArchie Cobbs if (FD_ISSET(csock, &rfds)) 2356ebb8ebbSArchie Cobbs MsgRead(); 236f8307e12SArchie Cobbs 237f8307e12SArchie Cobbs /* Display any incoming data packet */ 2386ebb8ebbSArchie Cobbs if (FD_ISSET(dsock, &rfds)) { 239f8307e12SArchie Cobbs u_char buf[8192]; 2409d901d3bSHartmut Brandt char hook[NG_HOOKSIZ]; 241f8307e12SArchie Cobbs int rl; 242f8307e12SArchie Cobbs 243f8307e12SArchie Cobbs /* Read packet from socket */ 244f8307e12SArchie Cobbs if ((rl = NgRecvData(dsock, 245f8307e12SArchie Cobbs buf, sizeof(buf), hook)) < 0) 2466ebb8ebbSArchie Cobbs err(EX_OSERR, "reading hook \"%s\"", hook); 247f8307e12SArchie Cobbs if (rl == 0) 248f8307e12SArchie Cobbs errx(EX_OSERR, "EOF from hook \"%s\"?", hook); 249f8307e12SArchie Cobbs 250f8307e12SArchie Cobbs /* Write packet to stdout */ 251f8307e12SArchie Cobbs printf("Rec'd data packet on hook \"%s\":\n", hook); 252f8307e12SArchie Cobbs DumpAscii(buf, rl); 253f8307e12SArchie Cobbs } 254f8307e12SArchie Cobbs 255f8307e12SArchie Cobbs /* Get any user input */ 256f8307e12SArchie Cobbs if (FD_ISSET(0, &rfds)) { 2570c5c7719SPoul-Henning Kamp char buf[LINE_MAX]; 2580c5c7719SPoul-Henning Kamp 2590c5c7719SPoul-Henning Kamp if (fgets(buf, sizeof(buf), stdin) == NULL) { 2600c5c7719SPoul-Henning Kamp printf("\n"); 2610c5c7719SPoul-Henning Kamp break; 2620c5c7719SPoul-Henning Kamp } 2630c5c7719SPoul-Henning Kamp if (DoParseCommand(buf) == CMDRTN_QUIT) 264f8307e12SArchie Cobbs break; 265f8307e12SArchie Cobbs } 266f8307e12SArchie Cobbs } 2674cf49a43SJulian Elischer return(CMDRTN_QUIT); 2684cf49a43SJulian Elischer } 2694cf49a43SJulian Elischer 2704cf49a43SJulian Elischer /* 2714cf49a43SJulian Elischer * Parse a command line and execute the command 2724cf49a43SJulian Elischer */ 2734cf49a43SJulian Elischer static int 2744cf49a43SJulian Elischer DoParseCommand(char *line) 2754cf49a43SJulian Elischer { 2764cf49a43SJulian Elischer char *av[MAX_ARGS]; 2774cf49a43SJulian Elischer int ac; 2784cf49a43SJulian Elischer 2794cf49a43SJulian Elischer /* Parse line */ 2804cf49a43SJulian Elischer for (ac = 0, av[0] = strtok(line, WHITESPACE); 2814cf49a43SJulian Elischer ac < MAX_ARGS - 1 && av[ac]; 2824cf49a43SJulian Elischer av[++ac] = strtok(NULL, WHITESPACE)); 2834cf49a43SJulian Elischer 2844cf49a43SJulian Elischer /* Do command */ 2854cf49a43SJulian Elischer return(DoCommand(ac, av)); 2864cf49a43SJulian Elischer } 2874cf49a43SJulian Elischer 2884cf49a43SJulian Elischer /* 2894cf49a43SJulian Elischer * Execute the command 2904cf49a43SJulian Elischer */ 2914cf49a43SJulian Elischer static int 2924cf49a43SJulian Elischer DoCommand(int ac, char **av) 2934cf49a43SJulian Elischer { 2944cf49a43SJulian Elischer const struct ngcmd *cmd; 2954cf49a43SJulian Elischer int rtn; 2964cf49a43SJulian Elischer 2974cf49a43SJulian Elischer if (ac == 0 || *av[0] == 0) 2984cf49a43SJulian Elischer return(CMDRTN_OK); 2994cf49a43SJulian Elischer if ((cmd = FindCommand(av[0])) == NULL) 3004cf49a43SJulian Elischer return(CMDRTN_ERROR); 3014cf49a43SJulian Elischer if ((rtn = (*cmd->func)(ac, av)) == CMDRTN_USAGE) 3024cf49a43SJulian Elischer warnx("usage: %s", cmd->cmd); 3034cf49a43SJulian Elischer return(rtn); 3044cf49a43SJulian Elischer } 3054cf49a43SJulian Elischer 3064cf49a43SJulian Elischer /* 3074cf49a43SJulian Elischer * Find a command 3084cf49a43SJulian Elischer */ 3094cf49a43SJulian Elischer static const struct ngcmd * 3104cf49a43SJulian Elischer FindCommand(const char *string) 3114cf49a43SJulian Elischer { 312f8307e12SArchie Cobbs int k, found = -1; 3134cf49a43SJulian Elischer 314f8307e12SArchie Cobbs for (k = 0; cmds[k] != NULL; k++) { 315f8307e12SArchie Cobbs if (MatchCommand(cmds[k], string)) { 3164cf49a43SJulian Elischer if (found != -1) { 3174cf49a43SJulian Elischer warnx("\"%s\": ambiguous command", string); 3184cf49a43SJulian Elischer return(NULL); 3194cf49a43SJulian Elischer } 3204cf49a43SJulian Elischer found = k; 3214cf49a43SJulian Elischer } 3224cf49a43SJulian Elischer } 3234cf49a43SJulian Elischer if (found == -1) { 3244cf49a43SJulian Elischer warnx("\"%s\": unknown command", string); 3254cf49a43SJulian Elischer return(NULL); 3264cf49a43SJulian Elischer } 3274cf49a43SJulian Elischer return(cmds[found]); 3284cf49a43SJulian Elischer } 3294cf49a43SJulian Elischer 3304cf49a43SJulian Elischer /* 331f8307e12SArchie Cobbs * See if string matches a prefix of "cmd" (or an alias) case insensitively 332f8307e12SArchie Cobbs */ 333f8307e12SArchie Cobbs static int 334f8307e12SArchie Cobbs MatchCommand(const struct ngcmd *cmd, const char *s) 335f8307e12SArchie Cobbs { 336f8307e12SArchie Cobbs int a; 337f8307e12SArchie Cobbs 338f8307e12SArchie Cobbs /* Try to match command, ignoring the usage stuff */ 339f8307e12SArchie Cobbs if (strlen(s) <= strcspn(cmd->cmd, WHITESPACE)) { 340f8307e12SArchie Cobbs if (strncasecmp(s, cmd->cmd, strlen(s)) == 0) 341f8307e12SArchie Cobbs return (1); 342f8307e12SArchie Cobbs } 343f8307e12SArchie Cobbs 344f8307e12SArchie Cobbs /* Try to match aliases */ 345f8307e12SArchie Cobbs for (a = 0; a < MAX_CMD_ALIAS && cmd->aliases[a] != NULL; a++) { 346f8307e12SArchie Cobbs if (strlen(cmd->aliases[a]) >= strlen(s)) { 347f8307e12SArchie Cobbs if (strncasecmp(s, cmd->aliases[a], strlen(s)) == 0) 348f8307e12SArchie Cobbs return (1); 349f8307e12SArchie Cobbs } 350f8307e12SArchie Cobbs } 351f8307e12SArchie Cobbs 352f8307e12SArchie Cobbs /* No match */ 353f8307e12SArchie Cobbs return (0); 354f8307e12SArchie Cobbs } 355f8307e12SArchie Cobbs 356f8307e12SArchie Cobbs /* 3574cf49a43SJulian Elischer * ReadCmd() 3584cf49a43SJulian Elischer */ 3594cf49a43SJulian Elischer static int 3604cf49a43SJulian Elischer ReadCmd(int ac, char **av) 3614cf49a43SJulian Elischer { 3624cf49a43SJulian Elischer FILE *fp; 3634cf49a43SJulian Elischer int rtn; 3644cf49a43SJulian Elischer 3654cf49a43SJulian Elischer /* Open file */ 3664cf49a43SJulian Elischer switch (ac) { 3674cf49a43SJulian Elischer case 2: 368f35e82dfSArchie Cobbs if ((fp = fopen(av[1], "r")) == NULL) { 3694cf49a43SJulian Elischer warn("%s", av[1]); 3704cf49a43SJulian Elischer return(CMDRTN_ERROR); 371f35e82dfSArchie Cobbs } 372f35e82dfSArchie Cobbs break; 3734cf49a43SJulian Elischer default: 3744cf49a43SJulian Elischer return(CMDRTN_USAGE); 3754cf49a43SJulian Elischer } 3764cf49a43SJulian Elischer 3774cf49a43SJulian Elischer /* Process it */ 3784cf49a43SJulian Elischer rtn = ReadFile(fp); 3794cf49a43SJulian Elischer fclose(fp); 3804cf49a43SJulian Elischer return(rtn); 3814cf49a43SJulian Elischer } 3824cf49a43SJulian Elischer 3834cf49a43SJulian Elischer /* 3844cf49a43SJulian Elischer * HelpCmd() 3854cf49a43SJulian Elischer */ 3864cf49a43SJulian Elischer static int 3874cf49a43SJulian Elischer HelpCmd(int ac, char **av) 3884cf49a43SJulian Elischer { 3894cf49a43SJulian Elischer const struct ngcmd *cmd; 3904cf49a43SJulian Elischer int k; 3914cf49a43SJulian Elischer 3924cf49a43SJulian Elischer switch (ac) { 3934cf49a43SJulian Elischer case 0: 3944cf49a43SJulian Elischer case 1: 3954cf49a43SJulian Elischer /* Show all commands */ 3964cf49a43SJulian Elischer printf("Available commands:\n"); 3974cf49a43SJulian Elischer for (k = 0; cmds[k] != NULL; k++) { 3984cf49a43SJulian Elischer char *s, buf[100]; 3994cf49a43SJulian Elischer 4004cf49a43SJulian Elischer cmd = cmds[k]; 4014cf49a43SJulian Elischer snprintf(buf, sizeof(buf), "%s", cmd->cmd); 4024cf49a43SJulian Elischer for (s = buf; *s != '\0' && !isspace(*s); s++); 4034cf49a43SJulian Elischer *s = '\0'; 4044cf49a43SJulian Elischer printf(" %-10s %s\n", buf, cmd->desc); 4054cf49a43SJulian Elischer } 4064cf49a43SJulian Elischer return(CMDRTN_OK); 4074cf49a43SJulian Elischer default: 4084cf49a43SJulian Elischer /* Show help on a specific command */ 4094cf49a43SJulian Elischer if ((cmd = FindCommand(av[1])) != NULL) { 410d3974088SDag-Erling Smørgrav printf("usage: %s\n", cmd->cmd); 411f8307e12SArchie Cobbs if (cmd->aliases[0] != NULL) { 412f8307e12SArchie Cobbs int a = 0; 413f8307e12SArchie Cobbs 414f8307e12SArchie Cobbs printf("Aliases: "); 415f8307e12SArchie Cobbs while (1) { 416f8307e12SArchie Cobbs printf("%s", cmd->aliases[a++]); 417f8307e12SArchie Cobbs if (a == MAX_CMD_ALIAS 418f8307e12SArchie Cobbs || cmd->aliases[a] == NULL) { 419f8307e12SArchie Cobbs printf("\n"); 420f8307e12SArchie Cobbs break; 421f8307e12SArchie Cobbs } 422f8307e12SArchie Cobbs printf(", "); 423f8307e12SArchie Cobbs } 424f8307e12SArchie Cobbs } 4254cf49a43SJulian Elischer printf("Summary: %s\n", cmd->desc); 4264cf49a43SJulian Elischer if (cmd->help != NULL) { 4274cf49a43SJulian Elischer const char *s; 4284cf49a43SJulian Elischer char buf[65]; 4294cf49a43SJulian Elischer int tot, len, done; 4304cf49a43SJulian Elischer 4314cf49a43SJulian Elischer printf("Description:\n"); 4324cf49a43SJulian Elischer for (s = cmd->help; *s != '\0'; s += len) { 4334cf49a43SJulian Elischer while (isspace(*s)) 4344cf49a43SJulian Elischer s++; 4354cf49a43SJulian Elischer tot = snprintf(buf, 4364cf49a43SJulian Elischer sizeof(buf), "%s", s); 4374cf49a43SJulian Elischer len = strlen(buf); 4384cf49a43SJulian Elischer done = len == tot; 4394cf49a43SJulian Elischer if (!done) { 4404cf49a43SJulian Elischer while (len > 0 4414cf49a43SJulian Elischer && !isspace(buf[len-1])) 4424cf49a43SJulian Elischer buf[--len] = '\0'; 4434cf49a43SJulian Elischer } 4444cf49a43SJulian Elischer printf(" %s\n", buf); 4454cf49a43SJulian Elischer } 4464cf49a43SJulian Elischer } 4474cf49a43SJulian Elischer } 4484cf49a43SJulian Elischer } 4494cf49a43SJulian Elischer return(CMDRTN_OK); 4504cf49a43SJulian Elischer } 4514cf49a43SJulian Elischer 4524cf49a43SJulian Elischer /* 4534cf49a43SJulian Elischer * QuitCmd() 4544cf49a43SJulian Elischer */ 4554cf49a43SJulian Elischer static int 456723c1c2eSRuslan Ermilov QuitCmd(int ac __unused, char **av __unused) 4574cf49a43SJulian Elischer { 4584cf49a43SJulian Elischer return(CMDRTN_QUIT); 4594cf49a43SJulian Elischer } 4604cf49a43SJulian Elischer 4614cf49a43SJulian Elischer /* 462f8307e12SArchie Cobbs * Dump data in hex and ASCII form 463f8307e12SArchie Cobbs */ 4646ebb8ebbSArchie Cobbs void 465f8307e12SArchie Cobbs DumpAscii(const u_char *buf, int len) 466f8307e12SArchie Cobbs { 467f8307e12SArchie Cobbs char ch, sbuf[100]; 468f8307e12SArchie Cobbs int k, count; 469f8307e12SArchie Cobbs 470f8307e12SArchie Cobbs for (count = 0; count < len; count += DUMP_BYTES_PER_LINE) { 471f8307e12SArchie Cobbs snprintf(sbuf, sizeof(sbuf), "%04x: ", count); 472f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 473f8307e12SArchie Cobbs if (count + k < len) { 474f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 475f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), 476f8307e12SArchie Cobbs "%02x ", buf[count + k]); 477f8307e12SArchie Cobbs } else { 478f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 479f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 480f8307e12SArchie Cobbs } 481f8307e12SArchie Cobbs } 482f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " "); 483f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 484f8307e12SArchie Cobbs if (count + k < len) { 485f8307e12SArchie Cobbs ch = isprint(buf[count + k]) ? 486f8307e12SArchie Cobbs buf[count + k] : '.'; 487f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 488f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), "%c", ch); 489f8307e12SArchie Cobbs } else { 490f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 491f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 492f8307e12SArchie Cobbs } 493f8307e12SArchie Cobbs } 494f8307e12SArchie Cobbs printf("%s\n", sbuf); 495f8307e12SArchie Cobbs } 496f8307e12SArchie Cobbs } 497f8307e12SArchie Cobbs 498f8307e12SArchie Cobbs /* 4994cf49a43SJulian Elischer * Usage() 5004cf49a43SJulian Elischer */ 5014cf49a43SJulian Elischer static void 5024cf49a43SJulian Elischer Usage(const char *msg) 5034cf49a43SJulian Elischer { 5044cf49a43SJulian Elischer if (msg) 5054cf49a43SJulian Elischer warnx("%s", msg); 506b00304d4SPhilippe Charnier fprintf(stderr, 507b00304d4SPhilippe Charnier "usage: ngctl [-d] [-f file] [-n name] [command ...]\n"); 508b00304d4SPhilippe Charnier exit(EX_USAGE); 5094cf49a43SJulian Elischer } 510