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); 55f8307e12SArchie Cobbs static void DumpAscii(const u_char *buf, int len); 564cf49a43SJulian Elischer static void Usage(const char *msg); 574cf49a43SJulian Elischer static int ReadCmd(int ac, char **av); 584cf49a43SJulian Elischer static int HelpCmd(int ac, char **av); 594cf49a43SJulian Elischer static int QuitCmd(int ac, char **av); 604cf49a43SJulian Elischer 614cf49a43SJulian Elischer /* List of commands */ 624cf49a43SJulian Elischer static const struct ngcmd *const cmds[] = { 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 */ 232f8307e12SArchie Cobbs while (FD_ISSET(csock, &rfds)) { 233f8307e12SArchie Cobbs u_char buf[2 * sizeof(struct ng_mesg) + 8192]; 234f8307e12SArchie Cobbs struct ng_mesg *const m = (struct ng_mesg *)buf; 235f8307e12SArchie Cobbs struct ng_mesg *const ascii = (struct ng_mesg *)m->data; 236f8307e12SArchie Cobbs char path[NG_PATHLEN+1]; 237f8307e12SArchie Cobbs 238f8307e12SArchie Cobbs /* Get incoming message (in binary form) */ 239f8307e12SArchie Cobbs if (NgRecvMsg(csock, m, sizeof(buf), path) < 0) { 240f8307e12SArchie Cobbs warn("recv incoming message"); 241f8307e12SArchie Cobbs break; 242f8307e12SArchie Cobbs } 243f8307e12SArchie Cobbs 244f8307e12SArchie Cobbs /* Ask originating node to convert to ASCII */ 245f8307e12SArchie Cobbs if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, 246f8307e12SArchie Cobbs NGM_BINARY2ASCII, m, 247f8307e12SArchie Cobbs sizeof(*m) + m->header.arglen) < 0 248f8307e12SArchie Cobbs || NgRecvMsg(csock, m, sizeof(buf), NULL) < 0) { 249f8307e12SArchie Cobbs printf("Rec'd %s %d from \"%s\":\n", 250f8307e12SArchie Cobbs (m->header.flags & NGF_RESP) != 0 ? 251f8307e12SArchie Cobbs "response" : "command", 252f8307e12SArchie Cobbs m->header.cmd, path); 253f8307e12SArchie Cobbs if (m->header.arglen == 0) 254f8307e12SArchie Cobbs printf("No arguments\n"); 255f8307e12SArchie Cobbs else 256f8307e12SArchie Cobbs DumpAscii(m->data, m->header.arglen); 257f8307e12SArchie Cobbs break; 258f8307e12SArchie Cobbs } 259f8307e12SArchie Cobbs 260f8307e12SArchie Cobbs /* Display message in ASCII form */ 261f8307e12SArchie Cobbs printf("Rec'd %s \"%s\" (%d) from \"%s\":\n", 262f8307e12SArchie Cobbs (ascii->header.flags & NGF_RESP) != 0 ? 263f8307e12SArchie Cobbs "response" : "command", 264f8307e12SArchie Cobbs ascii->header.cmdstr, ascii->header.cmd, path); 265f8307e12SArchie Cobbs if (*ascii->data != '\0') 266f8307e12SArchie Cobbs printf("Args:\t%s\n", ascii->data); 267f8307e12SArchie Cobbs else 268f8307e12SArchie Cobbs printf("No arguments\n"); 269f8307e12SArchie Cobbs break; 270f8307e12SArchie Cobbs } 271f8307e12SArchie Cobbs 272f8307e12SArchie Cobbs /* Display any incoming data packet */ 273f8307e12SArchie Cobbs while (FD_ISSET(dsock, &rfds)) { 274f8307e12SArchie Cobbs u_char buf[8192]; 275f8307e12SArchie Cobbs char hook[NG_HOOKLEN + 1]; 276f8307e12SArchie Cobbs int rl; 277f8307e12SArchie Cobbs 278f8307e12SArchie Cobbs /* Read packet from socket */ 279f8307e12SArchie Cobbs if ((rl = NgRecvData(dsock, 280f8307e12SArchie Cobbs buf, sizeof(buf), hook)) < 0) 281f8307e12SArchie Cobbs err(EX_OSERR, "read(hook)"); 282f8307e12SArchie Cobbs if (rl == 0) 283f8307e12SArchie Cobbs errx(EX_OSERR, "EOF from hook \"%s\"?", hook); 284f8307e12SArchie Cobbs 285f8307e12SArchie Cobbs /* Write packet to stdout */ 286f8307e12SArchie Cobbs printf("Rec'd data packet on hook \"%s\":\n", hook); 287f8307e12SArchie Cobbs DumpAscii(buf, rl); 288f8307e12SArchie Cobbs break; 289f8307e12SArchie Cobbs } 290f8307e12SArchie Cobbs 291f8307e12SArchie Cobbs /* Get any user input */ 292f8307e12SArchie Cobbs if (FD_ISSET(0, &rfds)) { 2934cf49a43SJulian Elischer char buf[LINE_MAX]; 2944cf49a43SJulian Elischer 295f8307e12SArchie Cobbs if (fgets(buf, sizeof(buf), stdin) == NULL) { 296f8307e12SArchie Cobbs printf("\n"); 2974cf49a43SJulian Elischer break; 298f8307e12SArchie Cobbs } 299f8307e12SArchie Cobbs if (DoParseCommand(buf) == CMDRTN_QUIT) 300f8307e12SArchie Cobbs break; 301f8307e12SArchie Cobbs } 302f8307e12SArchie Cobbs } 3034cf49a43SJulian Elischer return(CMDRTN_QUIT); 3044cf49a43SJulian Elischer } 3054cf49a43SJulian Elischer 3064cf49a43SJulian Elischer /* 3074cf49a43SJulian Elischer * Parse a command line and execute the command 3084cf49a43SJulian Elischer */ 3094cf49a43SJulian Elischer static int 3104cf49a43SJulian Elischer DoParseCommand(char *line) 3114cf49a43SJulian Elischer { 3124cf49a43SJulian Elischer char *av[MAX_ARGS]; 3134cf49a43SJulian Elischer int ac; 3144cf49a43SJulian Elischer 3154cf49a43SJulian Elischer /* Parse line */ 3164cf49a43SJulian Elischer for (ac = 0, av[0] = strtok(line, WHITESPACE); 3174cf49a43SJulian Elischer ac < MAX_ARGS - 1 && av[ac]; 3184cf49a43SJulian Elischer av[++ac] = strtok(NULL, WHITESPACE)); 3194cf49a43SJulian Elischer 3204cf49a43SJulian Elischer /* Do command */ 3214cf49a43SJulian Elischer return(DoCommand(ac, av)); 3224cf49a43SJulian Elischer } 3234cf49a43SJulian Elischer 3244cf49a43SJulian Elischer /* 3254cf49a43SJulian Elischer * Execute the command 3264cf49a43SJulian Elischer */ 3274cf49a43SJulian Elischer static int 3284cf49a43SJulian Elischer DoCommand(int ac, char **av) 3294cf49a43SJulian Elischer { 3304cf49a43SJulian Elischer const struct ngcmd *cmd; 3314cf49a43SJulian Elischer int rtn; 3324cf49a43SJulian Elischer 3334cf49a43SJulian Elischer if (ac == 0 || *av[0] == 0) 3344cf49a43SJulian Elischer return(CMDRTN_OK); 3354cf49a43SJulian Elischer if ((cmd = FindCommand(av[0])) == NULL) 3364cf49a43SJulian Elischer return(CMDRTN_ERROR); 3374cf49a43SJulian Elischer if ((rtn = (*cmd->func)(ac, av)) == CMDRTN_USAGE) 3384cf49a43SJulian Elischer warnx("usage: %s", cmd->cmd); 3394cf49a43SJulian Elischer return(rtn); 3404cf49a43SJulian Elischer } 3414cf49a43SJulian Elischer 3424cf49a43SJulian Elischer /* 3434cf49a43SJulian Elischer * Find a command 3444cf49a43SJulian Elischer */ 3454cf49a43SJulian Elischer static const struct ngcmd * 3464cf49a43SJulian Elischer FindCommand(const char *string) 3474cf49a43SJulian Elischer { 348f8307e12SArchie Cobbs int k, found = -1; 3494cf49a43SJulian Elischer 350f8307e12SArchie Cobbs for (k = 0; cmds[k] != NULL; k++) { 351f8307e12SArchie Cobbs if (MatchCommand(cmds[k], string)) { 3524cf49a43SJulian Elischer if (found != -1) { 3534cf49a43SJulian Elischer warnx("\"%s\": ambiguous command", string); 3544cf49a43SJulian Elischer return(NULL); 3554cf49a43SJulian Elischer } 3564cf49a43SJulian Elischer found = k; 3574cf49a43SJulian Elischer } 3584cf49a43SJulian Elischer } 3594cf49a43SJulian Elischer if (found == -1) { 3604cf49a43SJulian Elischer warnx("\"%s\": unknown command", string); 3614cf49a43SJulian Elischer return(NULL); 3624cf49a43SJulian Elischer } 3634cf49a43SJulian Elischer return(cmds[found]); 3644cf49a43SJulian Elischer } 3654cf49a43SJulian Elischer 3664cf49a43SJulian Elischer /* 367f8307e12SArchie Cobbs * See if string matches a prefix of "cmd" (or an alias) case insensitively 368f8307e12SArchie Cobbs */ 369f8307e12SArchie Cobbs static int 370f8307e12SArchie Cobbs MatchCommand(const struct ngcmd *cmd, const char *s) 371f8307e12SArchie Cobbs { 372f8307e12SArchie Cobbs int a; 373f8307e12SArchie Cobbs 374f8307e12SArchie Cobbs /* Try to match command, ignoring the usage stuff */ 375f8307e12SArchie Cobbs if (strlen(s) <= strcspn(cmd->cmd, WHITESPACE)) { 376f8307e12SArchie Cobbs if (strncasecmp(s, cmd->cmd, strlen(s)) == 0) 377f8307e12SArchie Cobbs return (1); 378f8307e12SArchie Cobbs } 379f8307e12SArchie Cobbs 380f8307e12SArchie Cobbs /* Try to match aliases */ 381f8307e12SArchie Cobbs for (a = 0; a < MAX_CMD_ALIAS && cmd->aliases[a] != NULL; a++) { 382f8307e12SArchie Cobbs if (strlen(cmd->aliases[a]) >= strlen(s)) { 383f8307e12SArchie Cobbs if (strncasecmp(s, cmd->aliases[a], strlen(s)) == 0) 384f8307e12SArchie Cobbs return (1); 385f8307e12SArchie Cobbs } 386f8307e12SArchie Cobbs } 387f8307e12SArchie Cobbs 388f8307e12SArchie Cobbs /* No match */ 389f8307e12SArchie Cobbs return (0); 390f8307e12SArchie Cobbs } 391f8307e12SArchie Cobbs 392f8307e12SArchie Cobbs /* 3934cf49a43SJulian Elischer * ReadCmd() 3944cf49a43SJulian Elischer */ 3954cf49a43SJulian Elischer static int 3964cf49a43SJulian Elischer ReadCmd(int ac, char **av) 3974cf49a43SJulian Elischer { 3984cf49a43SJulian Elischer FILE *fp; 3994cf49a43SJulian Elischer int rtn; 4004cf49a43SJulian Elischer 4014cf49a43SJulian Elischer /* Open file */ 4024cf49a43SJulian Elischer switch (ac) { 4034cf49a43SJulian Elischer case 2: 4044cf49a43SJulian Elischer if ((fp = fopen(av[1], "r")) == NULL) 4054cf49a43SJulian Elischer warn("%s", av[1]); 4064cf49a43SJulian Elischer return(CMDRTN_ERROR); 4074cf49a43SJulian Elischer default: 4084cf49a43SJulian Elischer return(CMDRTN_USAGE); 4094cf49a43SJulian Elischer } 4104cf49a43SJulian Elischer 4114cf49a43SJulian Elischer /* Process it */ 4124cf49a43SJulian Elischer rtn = ReadFile(fp); 4134cf49a43SJulian Elischer fclose(fp); 4144cf49a43SJulian Elischer return(rtn); 4154cf49a43SJulian Elischer } 4164cf49a43SJulian Elischer 4174cf49a43SJulian Elischer /* 4184cf49a43SJulian Elischer * HelpCmd() 4194cf49a43SJulian Elischer */ 4204cf49a43SJulian Elischer static int 4214cf49a43SJulian Elischer HelpCmd(int ac, char **av) 4224cf49a43SJulian Elischer { 4234cf49a43SJulian Elischer const struct ngcmd *cmd; 4244cf49a43SJulian Elischer int k; 4254cf49a43SJulian Elischer 4264cf49a43SJulian Elischer switch (ac) { 4274cf49a43SJulian Elischer case 0: 4284cf49a43SJulian Elischer case 1: 4294cf49a43SJulian Elischer /* Show all commands */ 4304cf49a43SJulian Elischer printf("Available commands:\n"); 4314cf49a43SJulian Elischer for (k = 0; cmds[k] != NULL; k++) { 4324cf49a43SJulian Elischer char *s, buf[100]; 4334cf49a43SJulian Elischer 4344cf49a43SJulian Elischer cmd = cmds[k]; 4354cf49a43SJulian Elischer snprintf(buf, sizeof(buf), "%s", cmd->cmd); 4364cf49a43SJulian Elischer for (s = buf; *s != '\0' && !isspace(*s); s++); 4374cf49a43SJulian Elischer *s = '\0'; 4384cf49a43SJulian Elischer printf(" %-10s %s\n", buf, cmd->desc); 4394cf49a43SJulian Elischer } 4404cf49a43SJulian Elischer return(CMDRTN_OK); 4414cf49a43SJulian Elischer default: 4424cf49a43SJulian Elischer /* Show help on a specific command */ 4434cf49a43SJulian Elischer if ((cmd = FindCommand(av[1])) != NULL) { 4444cf49a43SJulian Elischer printf("Usage: %s\n", cmd->cmd); 445f8307e12SArchie Cobbs if (cmd->aliases[0] != NULL) { 446f8307e12SArchie Cobbs int a = 0; 447f8307e12SArchie Cobbs 448f8307e12SArchie Cobbs printf("Aliases: "); 449f8307e12SArchie Cobbs while (1) { 450f8307e12SArchie Cobbs printf("%s", cmd->aliases[a++]); 451f8307e12SArchie Cobbs if (a == MAX_CMD_ALIAS 452f8307e12SArchie Cobbs || cmd->aliases[a] == NULL) { 453f8307e12SArchie Cobbs printf("\n"); 454f8307e12SArchie Cobbs break; 455f8307e12SArchie Cobbs } 456f8307e12SArchie Cobbs printf(", "); 457f8307e12SArchie Cobbs } 458f8307e12SArchie Cobbs } 4594cf49a43SJulian Elischer printf("Summary: %s\n", cmd->desc); 4604cf49a43SJulian Elischer if (cmd->help != NULL) { 4614cf49a43SJulian Elischer const char *s; 4624cf49a43SJulian Elischer char buf[65]; 4634cf49a43SJulian Elischer int tot, len, done; 4644cf49a43SJulian Elischer 4654cf49a43SJulian Elischer printf("Description:\n"); 4664cf49a43SJulian Elischer for (s = cmd->help; *s != '\0'; s += len) { 4674cf49a43SJulian Elischer while (isspace(*s)) 4684cf49a43SJulian Elischer s++; 4694cf49a43SJulian Elischer tot = snprintf(buf, 4704cf49a43SJulian Elischer sizeof(buf), "%s", s); 4714cf49a43SJulian Elischer len = strlen(buf); 4724cf49a43SJulian Elischer done = len == tot; 4734cf49a43SJulian Elischer if (!done) { 4744cf49a43SJulian Elischer while (len > 0 4754cf49a43SJulian Elischer && !isspace(buf[len-1])) 4764cf49a43SJulian Elischer buf[--len] = '\0'; 4774cf49a43SJulian Elischer } 4784cf49a43SJulian Elischer printf(" %s\n", buf); 4794cf49a43SJulian Elischer } 4804cf49a43SJulian Elischer } 4814cf49a43SJulian Elischer } 4824cf49a43SJulian Elischer } 4834cf49a43SJulian Elischer return(CMDRTN_OK); 4844cf49a43SJulian Elischer } 4854cf49a43SJulian Elischer 4864cf49a43SJulian Elischer /* 4874cf49a43SJulian Elischer * QuitCmd() 4884cf49a43SJulian Elischer */ 4894cf49a43SJulian Elischer static int 4904cf49a43SJulian Elischer QuitCmd(int ac, char **av) 4914cf49a43SJulian Elischer { 4924cf49a43SJulian Elischer return(CMDRTN_QUIT); 4934cf49a43SJulian Elischer } 4944cf49a43SJulian Elischer 4954cf49a43SJulian Elischer /* 496f8307e12SArchie Cobbs * Dump data in hex and ASCII form 497f8307e12SArchie Cobbs */ 498f8307e12SArchie Cobbs static void 499f8307e12SArchie Cobbs DumpAscii(const u_char *buf, int len) 500f8307e12SArchie Cobbs { 501f8307e12SArchie Cobbs char ch, sbuf[100]; 502f8307e12SArchie Cobbs int k, count; 503f8307e12SArchie Cobbs 504f8307e12SArchie Cobbs for (count = 0; count < len; count += DUMP_BYTES_PER_LINE) { 505f8307e12SArchie Cobbs snprintf(sbuf, sizeof(sbuf), "%04x: ", count); 506f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 507f8307e12SArchie Cobbs if (count + k < len) { 508f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 509f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), 510f8307e12SArchie Cobbs "%02x ", buf[count + k]); 511f8307e12SArchie Cobbs } else { 512f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 513f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 514f8307e12SArchie Cobbs } 515f8307e12SArchie Cobbs } 516f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " "); 517f8307e12SArchie Cobbs for (k = 0; k < DUMP_BYTES_PER_LINE; k++) { 518f8307e12SArchie Cobbs if (count + k < len) { 519f8307e12SArchie Cobbs ch = isprint(buf[count + k]) ? 520f8307e12SArchie Cobbs buf[count + k] : '.'; 521f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 522f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), "%c", ch); 523f8307e12SArchie Cobbs } else { 524f8307e12SArchie Cobbs snprintf(sbuf + strlen(sbuf), 525f8307e12SArchie Cobbs sizeof(sbuf) - strlen(sbuf), " "); 526f8307e12SArchie Cobbs } 527f8307e12SArchie Cobbs } 528f8307e12SArchie Cobbs printf("%s\n", sbuf); 529f8307e12SArchie Cobbs } 530f8307e12SArchie Cobbs } 531f8307e12SArchie Cobbs 532f8307e12SArchie Cobbs /* 5334cf49a43SJulian Elischer * Usage() 5344cf49a43SJulian Elischer */ 5354cf49a43SJulian Elischer static void 5364cf49a43SJulian Elischer Usage(const char *msg) 5374cf49a43SJulian Elischer { 5384cf49a43SJulian Elischer if (msg) 5394cf49a43SJulian Elischer warnx("%s", msg); 5404cf49a43SJulian Elischer errx(EX_USAGE, "usage: ngctl [-d] [-f file] [-n name] [command ...]"); 5414cf49a43SJulian Elischer } 5424cf49a43SJulian Elischer 543