Deleted Added
full compact
main.c (158882) main.c (160002)
1
2/*
3 * main.c
4 *
5 * Copyright (c) 1996-1999 Whistle Communications, Inc.
6 * All rights reserved.
7 *
8 * Subject to the following obligations and disclaimer of warranty, use and
9 * redistribution of this software, in source or object code forms, with or
10 * without modifications are expressly permitted by Whistle Communications;
11 * provided, however, that:
12 * 1. Any and all reproductions of the source or object code must include the
13 * copyright notice above and the following disclaimer of warranties; and
14 * 2. No rights are granted, in any manner or form, to use Whistle
15 * Communications, Inc. trademarks, including the mark "WHISTLE
16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17 * such appears in the above copyright notice or in the software.
18 *
19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 *
1
2/*
3 * main.c
4 *
5 * Copyright (c) 1996-1999 Whistle Communications, Inc.
6 * All rights reserved.
7 *
8 * Subject to the following obligations and disclaimer of warranty, use and
9 * redistribution of this software, in source or object code forms, with or
10 * without modifications are expressly permitted by Whistle Communications;
11 * provided, however, that:
12 * 1. Any and all reproductions of the source or object code must include the
13 * copyright notice above and the following disclaimer of warranties; and
14 * 2. No rights are granted, in any manner or form, to use Whistle
15 * Communications, Inc. trademarks, including the mark "WHISTLE
16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17 * such appears in the above copyright notice or in the software.
18 *
19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 *
37 * $FreeBSD: head/usr.sbin/ngctl/main.c 158882 2006-05-24 14:46:55Z glebius $
37 * $FreeBSD: head/usr.sbin/ngctl/main.c 160002 2006-06-28 10:38:38Z glebius $
38 * $Whistle: main.c,v 1.12 1999/11/29 19:17:46 archie Exp $
39 */
40
41#include <sys/param.h>
42#include <sys/socket.h>
43#include <sys/select.h>
44
45#include <ctype.h>
46#include <err.h>
47#include <errno.h>
48#include <limits.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <sysexits.h>
53#include <unistd.h>
54
55#include <netgraph.h>
56
57#include "ngctl.h"
58
59#define PROMPT "+ "
60#define MAX_ARGS 512
61#define WHITESPACE " \t\r\n\v\f"
62#define DUMP_BYTES_PER_LINE 16
63
64/* Internal functions */
65static int ReadFile(FILE *fp);
66static int DoParseCommand(char *line);
67static int DoCommand(int ac, char **av);
68static int DoInteractive(void);
69static const struct ngcmd *FindCommand(const char *string);
70static int MatchCommand(const struct ngcmd *cmd, const char *s);
71static void Usage(const char *msg);
72static int ReadCmd(int ac, char **av);
73static int HelpCmd(int ac, char **av);
74static int QuitCmd(int ac, char **av);
75
76/* List of commands */
77static const struct ngcmd *const cmds[] = {
78 &config_cmd,
79 &connect_cmd,
80 &debug_cmd,
81 &dot_cmd,
82 &help_cmd,
83 &list_cmd,
84 &mkpeer_cmd,
85 &msg_cmd,
86 &name_cmd,
87 &read_cmd,
88 &rmhook_cmd,
89 &show_cmd,
90 &shutdown_cmd,
91 &status_cmd,
92 &types_cmd,
93 &write_cmd,
94 &quit_cmd,
95 NULL
96};
97
98/* Commands defined in this file */
99const struct ngcmd read_cmd = {
100 ReadCmd,
101 "read <filename>",
102 "Read and execute commands from a file",
103 NULL,
104 { "source", "." }
105};
106const struct ngcmd help_cmd = {
107 HelpCmd,
108 "help [command]",
109 "Show command summary or get more help on a specific command",
110 NULL,
111 { "?" }
112};
113const struct ngcmd quit_cmd = {
114 QuitCmd,
115 "quit",
116 "Exit program",
117 NULL,
118 { "exit" }
119};
120
121/* Our control and data sockets */
122int csock, dsock;
123
124/*
125 * main()
126 */
127int
128main(int ac, char *av[])
129{
130 char name[NG_NODESIZ];
131 int interactive = isatty(0) && isatty(1);
132 FILE *fp = NULL;
133 int ch, rtn = 0;
134
135 /* Set default node name */
136 snprintf(name, sizeof(name), "ngctl%d", getpid());
137
138 /* Parse command line */
139 while ((ch = getopt(ac, av, "df:n:")) != EOF) {
140 switch (ch) {
141 case 'd':
142 NgSetDebug(NgSetDebug(-1) + 1);
143 break;
144 case 'f':
145 if (strcmp(optarg, "-") == 0)
146 fp = stdin;
147 else if ((fp = fopen(optarg, "r")) == NULL)
148 err(EX_NOINPUT, "%s", optarg);
149 break;
150 case 'n':
151 snprintf(name, sizeof(name), "%s", optarg);
152 break;
153 case '?':
154 default:
155 Usage((char *)NULL);
156 break;
157 }
158 }
159 ac -= optind;
160 av += optind;
161
162 /* Create a new socket node */
163 if (NgMkSockNode(name, &csock, &dsock) < 0)
164 err(EX_OSERR, "can't create node");
165
166 /* Do commands as requested */
167 if (ac == 0) {
168 if (fp != NULL) {
169 rtn = ReadFile(fp);
170 } else if (interactive) {
171 rtn = DoInteractive();
172 } else
173 Usage("no command specified");
174 } else {
175 rtn = DoCommand(ac, av);
176 }
177
178 /* Convert command return code into system exit code */
179 switch (rtn) {
180 case CMDRTN_OK:
181 case CMDRTN_QUIT:
182 rtn = 0;
183 break;
184 case CMDRTN_USAGE:
185 rtn = EX_USAGE;
186 break;
187 case CMDRTN_ERROR:
188 rtn = EX_OSERR;
189 break;
190 }
38 * $Whistle: main.c,v 1.12 1999/11/29 19:17:46 archie Exp $
39 */
40
41#include <sys/param.h>
42#include <sys/socket.h>
43#include <sys/select.h>
44
45#include <ctype.h>
46#include <err.h>
47#include <errno.h>
48#include <limits.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <sysexits.h>
53#include <unistd.h>
54
55#include <netgraph.h>
56
57#include "ngctl.h"
58
59#define PROMPT "+ "
60#define MAX_ARGS 512
61#define WHITESPACE " \t\r\n\v\f"
62#define DUMP_BYTES_PER_LINE 16
63
64/* Internal functions */
65static int ReadFile(FILE *fp);
66static int DoParseCommand(char *line);
67static int DoCommand(int ac, char **av);
68static int DoInteractive(void);
69static const struct ngcmd *FindCommand(const char *string);
70static int MatchCommand(const struct ngcmd *cmd, const char *s);
71static void Usage(const char *msg);
72static int ReadCmd(int ac, char **av);
73static int HelpCmd(int ac, char **av);
74static int QuitCmd(int ac, char **av);
75
76/* List of commands */
77static const struct ngcmd *const cmds[] = {
78 &config_cmd,
79 &connect_cmd,
80 &debug_cmd,
81 &dot_cmd,
82 &help_cmd,
83 &list_cmd,
84 &mkpeer_cmd,
85 &msg_cmd,
86 &name_cmd,
87 &read_cmd,
88 &rmhook_cmd,
89 &show_cmd,
90 &shutdown_cmd,
91 &status_cmd,
92 &types_cmd,
93 &write_cmd,
94 &quit_cmd,
95 NULL
96};
97
98/* Commands defined in this file */
99const struct ngcmd read_cmd = {
100 ReadCmd,
101 "read <filename>",
102 "Read and execute commands from a file",
103 NULL,
104 { "source", "." }
105};
106const struct ngcmd help_cmd = {
107 HelpCmd,
108 "help [command]",
109 "Show command summary or get more help on a specific command",
110 NULL,
111 { "?" }
112};
113const struct ngcmd quit_cmd = {
114 QuitCmd,
115 "quit",
116 "Exit program",
117 NULL,
118 { "exit" }
119};
120
121/* Our control and data sockets */
122int csock, dsock;
123
124/*
125 * main()
126 */
127int
128main(int ac, char *av[])
129{
130 char name[NG_NODESIZ];
131 int interactive = isatty(0) && isatty(1);
132 FILE *fp = NULL;
133 int ch, rtn = 0;
134
135 /* Set default node name */
136 snprintf(name, sizeof(name), "ngctl%d", getpid());
137
138 /* Parse command line */
139 while ((ch = getopt(ac, av, "df:n:")) != EOF) {
140 switch (ch) {
141 case 'd':
142 NgSetDebug(NgSetDebug(-1) + 1);
143 break;
144 case 'f':
145 if (strcmp(optarg, "-") == 0)
146 fp = stdin;
147 else if ((fp = fopen(optarg, "r")) == NULL)
148 err(EX_NOINPUT, "%s", optarg);
149 break;
150 case 'n':
151 snprintf(name, sizeof(name), "%s", optarg);
152 break;
153 case '?':
154 default:
155 Usage((char *)NULL);
156 break;
157 }
158 }
159 ac -= optind;
160 av += optind;
161
162 /* Create a new socket node */
163 if (NgMkSockNode(name, &csock, &dsock) < 0)
164 err(EX_OSERR, "can't create node");
165
166 /* Do commands as requested */
167 if (ac == 0) {
168 if (fp != NULL) {
169 rtn = ReadFile(fp);
170 } else if (interactive) {
171 rtn = DoInteractive();
172 } else
173 Usage("no command specified");
174 } else {
175 rtn = DoCommand(ac, av);
176 }
177
178 /* Convert command return code into system exit code */
179 switch (rtn) {
180 case CMDRTN_OK:
181 case CMDRTN_QUIT:
182 rtn = 0;
183 break;
184 case CMDRTN_USAGE:
185 rtn = EX_USAGE;
186 break;
187 case CMDRTN_ERROR:
188 rtn = EX_OSERR;
189 break;
190 }
191 return(rtn);
191 return (rtn);
192}
193
194/*
195 * Process commands from a file
196 */
197static int
198ReadFile(FILE *fp)
199{
200 char line[LINE_MAX];
201 int num, rtn;
202
203 for (num = 1; fgets(line, sizeof(line), fp) != NULL; num++) {
204 if (*line == '#')
205 continue;
206 if ((rtn = DoParseCommand(line)) != 0) {
207 warnx("line %d: error in file", num);
192}
193
194/*
195 * Process commands from a file
196 */
197static int
198ReadFile(FILE *fp)
199{
200 char line[LINE_MAX];
201 int num, rtn;
202
203 for (num = 1; fgets(line, sizeof(line), fp) != NULL; num++) {
204 if (*line == '#')
205 continue;
206 if ((rtn = DoParseCommand(line)) != 0) {
207 warnx("line %d: error in file", num);
208 return(rtn);
208 return (rtn);
209 }
210 }
209 }
210 }
211 return(CMDRTN_OK);
211 return (CMDRTN_OK);
212}
213
214/*
215 * Interactive mode
216 */
217static int
218DoInteractive(void)
219{
220 const int maxfd = MAX(csock, dsock) + 1;
221
222 (*help_cmd.func)(0, NULL);
223 while (1) {
224 struct timeval tv;
225 fd_set rfds;
226
227 /* See if any data or control messages are arriving */
228 FD_ZERO(&rfds);
229 FD_SET(csock, &rfds);
230 FD_SET(dsock, &rfds);
231 memset(&tv, 0, sizeof(tv));
232 if (select(maxfd, &rfds, NULL, NULL, &tv) <= 0) {
233
234 /* Issue prompt and wait for anything to happen */
235 printf("%s", PROMPT);
236 fflush(stdout);
237 FD_ZERO(&rfds);
238 FD_SET(0, &rfds);
239 FD_SET(csock, &rfds);
240 FD_SET(dsock, &rfds);
241 if (select(maxfd, &rfds, NULL, NULL, NULL) < 0)
242 err(EX_OSERR, "select");
243
244 /* If not user input, print a newline first */
245 if (!FD_ISSET(0, &rfds))
246 printf("\n");
247 }
248
249 /* Display any incoming control message */
250 if (FD_ISSET(csock, &rfds))
251 MsgRead();
252
253 /* Display any incoming data packet */
254 if (FD_ISSET(dsock, &rfds)) {
255 u_char *buf;
256 char hook[NG_HOOKSIZ];
257 int rl;
258
259 /* Read packet from socket */
260 if ((rl = NgAllocRecvData(dsock, &buf, hook)) < 0)
261 err(EX_OSERR, "reading hook \"%s\"", hook);
262 if (rl == 0)
263 errx(EX_OSERR, "EOF from hook \"%s\"?", hook);
264
265 /* Write packet to stdout */
266 printf("Rec'd data packet on hook \"%s\":\n", hook);
267 DumpAscii(buf, rl);
268 free(buf);
269 }
270
271 /* Get any user input */
272 if (FD_ISSET(0, &rfds)) {
273 char buf[LINE_MAX];
274
275 if (fgets(buf, sizeof(buf), stdin) == NULL) {
276 printf("\n");
277 break;
278 }
279 if (DoParseCommand(buf) == CMDRTN_QUIT)
280 break;
281 }
282 }
212}
213
214/*
215 * Interactive mode
216 */
217static int
218DoInteractive(void)
219{
220 const int maxfd = MAX(csock, dsock) + 1;
221
222 (*help_cmd.func)(0, NULL);
223 while (1) {
224 struct timeval tv;
225 fd_set rfds;
226
227 /* See if any data or control messages are arriving */
228 FD_ZERO(&rfds);
229 FD_SET(csock, &rfds);
230 FD_SET(dsock, &rfds);
231 memset(&tv, 0, sizeof(tv));
232 if (select(maxfd, &rfds, NULL, NULL, &tv) <= 0) {
233
234 /* Issue prompt and wait for anything to happen */
235 printf("%s", PROMPT);
236 fflush(stdout);
237 FD_ZERO(&rfds);
238 FD_SET(0, &rfds);
239 FD_SET(csock, &rfds);
240 FD_SET(dsock, &rfds);
241 if (select(maxfd, &rfds, NULL, NULL, NULL) < 0)
242 err(EX_OSERR, "select");
243
244 /* If not user input, print a newline first */
245 if (!FD_ISSET(0, &rfds))
246 printf("\n");
247 }
248
249 /* Display any incoming control message */
250 if (FD_ISSET(csock, &rfds))
251 MsgRead();
252
253 /* Display any incoming data packet */
254 if (FD_ISSET(dsock, &rfds)) {
255 u_char *buf;
256 char hook[NG_HOOKSIZ];
257 int rl;
258
259 /* Read packet from socket */
260 if ((rl = NgAllocRecvData(dsock, &buf, hook)) < 0)
261 err(EX_OSERR, "reading hook \"%s\"", hook);
262 if (rl == 0)
263 errx(EX_OSERR, "EOF from hook \"%s\"?", hook);
264
265 /* Write packet to stdout */
266 printf("Rec'd data packet on hook \"%s\":\n", hook);
267 DumpAscii(buf, rl);
268 free(buf);
269 }
270
271 /* Get any user input */
272 if (FD_ISSET(0, &rfds)) {
273 char buf[LINE_MAX];
274
275 if (fgets(buf, sizeof(buf), stdin) == NULL) {
276 printf("\n");
277 break;
278 }
279 if (DoParseCommand(buf) == CMDRTN_QUIT)
280 break;
281 }
282 }
283 return(CMDRTN_QUIT);
283 return (CMDRTN_QUIT);
284}
285
286/*
287 * Parse a command line and execute the command
288 */
289static int
290DoParseCommand(char *line)
291{
292 char *av[MAX_ARGS];
293 int ac;
294
295 /* Parse line */
296 for (ac = 0, av[0] = strtok(line, WHITESPACE);
297 ac < MAX_ARGS - 1 && av[ac];
298 av[++ac] = strtok(NULL, WHITESPACE));
299
300 /* Do command */
284}
285
286/*
287 * Parse a command line and execute the command
288 */
289static int
290DoParseCommand(char *line)
291{
292 char *av[MAX_ARGS];
293 int ac;
294
295 /* Parse line */
296 for (ac = 0, av[0] = strtok(line, WHITESPACE);
297 ac < MAX_ARGS - 1 && av[ac];
298 av[++ac] = strtok(NULL, WHITESPACE));
299
300 /* Do command */
301 return(DoCommand(ac, av));
301 return (DoCommand(ac, av));
302}
303
304/*
305 * Execute the command
306 */
307static int
308DoCommand(int ac, char **av)
309{
310 const struct ngcmd *cmd;
311 int rtn;
312
313 if (ac == 0 || *av[0] == 0)
302}
303
304/*
305 * Execute the command
306 */
307static int
308DoCommand(int ac, char **av)
309{
310 const struct ngcmd *cmd;
311 int rtn;
312
313 if (ac == 0 || *av[0] == 0)
314 return(CMDRTN_OK);
314 return (CMDRTN_OK);
315 if ((cmd = FindCommand(av[0])) == NULL)
315 if ((cmd = FindCommand(av[0])) == NULL)
316 return(CMDRTN_ERROR);
316 return (CMDRTN_ERROR);
317 if ((rtn = (*cmd->func)(ac, av)) == CMDRTN_USAGE)
318 warnx("usage: %s", cmd->cmd);
317 if ((rtn = (*cmd->func)(ac, av)) == CMDRTN_USAGE)
318 warnx("usage: %s", cmd->cmd);
319 return(rtn);
319 return (rtn);
320}
321
322/*
323 * Find a command
324 */
325static const struct ngcmd *
326FindCommand(const char *string)
327{
328 int k, found = -1;
329
330 for (k = 0; cmds[k] != NULL; k++) {
331 if (MatchCommand(cmds[k], string)) {
332 if (found != -1) {
333 warnx("\"%s\": ambiguous command", string);
320}
321
322/*
323 * Find a command
324 */
325static const struct ngcmd *
326FindCommand(const char *string)
327{
328 int k, found = -1;
329
330 for (k = 0; cmds[k] != NULL; k++) {
331 if (MatchCommand(cmds[k], string)) {
332 if (found != -1) {
333 warnx("\"%s\": ambiguous command", string);
334 return(NULL);
334 return (NULL);
335 }
336 found = k;
337 }
338 }
339 if (found == -1) {
340 warnx("\"%s\": unknown command", string);
335 }
336 found = k;
337 }
338 }
339 if (found == -1) {
340 warnx("\"%s\": unknown command", string);
341 return(NULL);
341 return (NULL);
342 }
342 }
343 return(cmds[found]);
343 return (cmds[found]);
344}
345
346/*
347 * See if string matches a prefix of "cmd" (or an alias) case insensitively
348 */
349static int
350MatchCommand(const struct ngcmd *cmd, const char *s)
351{
352 int a;
353
354 /* Try to match command, ignoring the usage stuff */
355 if (strlen(s) <= strcspn(cmd->cmd, WHITESPACE)) {
356 if (strncasecmp(s, cmd->cmd, strlen(s)) == 0)
357 return (1);
358 }
359
360 /* Try to match aliases */
361 for (a = 0; a < MAX_CMD_ALIAS && cmd->aliases[a] != NULL; a++) {
362 if (strlen(cmd->aliases[a]) >= strlen(s)) {
363 if (strncasecmp(s, cmd->aliases[a], strlen(s)) == 0)
364 return (1);
365 }
366 }
367
368 /* No match */
369 return (0);
370}
371
372/*
373 * ReadCmd()
374 */
375static int
376ReadCmd(int ac, char **av)
377{
378 FILE *fp;
379 int rtn;
380
381 /* Open file */
382 switch (ac) {
383 case 2:
384 if ((fp = fopen(av[1], "r")) == NULL) {
385 warn("%s", av[1]);
344}
345
346/*
347 * See if string matches a prefix of "cmd" (or an alias) case insensitively
348 */
349static int
350MatchCommand(const struct ngcmd *cmd, const char *s)
351{
352 int a;
353
354 /* Try to match command, ignoring the usage stuff */
355 if (strlen(s) <= strcspn(cmd->cmd, WHITESPACE)) {
356 if (strncasecmp(s, cmd->cmd, strlen(s)) == 0)
357 return (1);
358 }
359
360 /* Try to match aliases */
361 for (a = 0; a < MAX_CMD_ALIAS && cmd->aliases[a] != NULL; a++) {
362 if (strlen(cmd->aliases[a]) >= strlen(s)) {
363 if (strncasecmp(s, cmd->aliases[a], strlen(s)) == 0)
364 return (1);
365 }
366 }
367
368 /* No match */
369 return (0);
370}
371
372/*
373 * ReadCmd()
374 */
375static int
376ReadCmd(int ac, char **av)
377{
378 FILE *fp;
379 int rtn;
380
381 /* Open file */
382 switch (ac) {
383 case 2:
384 if ((fp = fopen(av[1], "r")) == NULL) {
385 warn("%s", av[1]);
386 return(CMDRTN_ERROR);
386 return (CMDRTN_ERROR);
387 }
388 break;
389 default:
387 }
388 break;
389 default:
390 return(CMDRTN_USAGE);
390 return (CMDRTN_USAGE);
391 }
392
393 /* Process it */
394 rtn = ReadFile(fp);
395 fclose(fp);
391 }
392
393 /* Process it */
394 rtn = ReadFile(fp);
395 fclose(fp);
396 return(rtn);
396 return (rtn);
397}
398
399/*
400 * HelpCmd()
401 */
402static int
403HelpCmd(int ac, char **av)
404{
405 const struct ngcmd *cmd;
406 int k;
407
408 switch (ac) {
409 case 0:
410 case 1:
411 /* Show all commands */
412 printf("Available commands:\n");
413 for (k = 0; cmds[k] != NULL; k++) {
414 char *s, buf[100];
415
416 cmd = cmds[k];
417 snprintf(buf, sizeof(buf), "%s", cmd->cmd);
418 for (s = buf; *s != '\0' && !isspace(*s); s++);
419 *s = '\0';
420 printf(" %-10s %s\n", buf, cmd->desc);
421 }
397}
398
399/*
400 * HelpCmd()
401 */
402static int
403HelpCmd(int ac, char **av)
404{
405 const struct ngcmd *cmd;
406 int k;
407
408 switch (ac) {
409 case 0:
410 case 1:
411 /* Show all commands */
412 printf("Available commands:\n");
413 for (k = 0; cmds[k] != NULL; k++) {
414 char *s, buf[100];
415
416 cmd = cmds[k];
417 snprintf(buf, sizeof(buf), "%s", cmd->cmd);
418 for (s = buf; *s != '\0' && !isspace(*s); s++);
419 *s = '\0';
420 printf(" %-10s %s\n", buf, cmd->desc);
421 }
422 return(CMDRTN_OK);
422 return (CMDRTN_OK);
423 default:
424 /* Show help on a specific command */
425 if ((cmd = FindCommand(av[1])) != NULL) {
426 printf("usage: %s\n", cmd->cmd);
427 if (cmd->aliases[0] != NULL) {
428 int a = 0;
429
430 printf("Aliases: ");
431 while (1) {
432 printf("%s", cmd->aliases[a++]);
433 if (a == MAX_CMD_ALIAS
434 || cmd->aliases[a] == NULL) {
435 printf("\n");
436 break;
437 }
438 printf(", ");
439 }
440 }
441 printf("Summary: %s\n", cmd->desc);
442 if (cmd->help != NULL) {
443 const char *s;
444 char buf[65];
445 int tot, len, done;
446
447 printf("Description:\n");
448 for (s = cmd->help; *s != '\0'; s += len) {
449 while (isspace(*s))
450 s++;
451 tot = snprintf(buf,
452 sizeof(buf), "%s", s);
453 len = strlen(buf);
454 done = len == tot;
455 if (!done) {
456 while (len > 0
457 && !isspace(buf[len-1]))
458 buf[--len] = '\0';
459 }
460 printf(" %s\n", buf);
461 }
462 }
463 }
464 }
423 default:
424 /* Show help on a specific command */
425 if ((cmd = FindCommand(av[1])) != NULL) {
426 printf("usage: %s\n", cmd->cmd);
427 if (cmd->aliases[0] != NULL) {
428 int a = 0;
429
430 printf("Aliases: ");
431 while (1) {
432 printf("%s", cmd->aliases[a++]);
433 if (a == MAX_CMD_ALIAS
434 || cmd->aliases[a] == NULL) {
435 printf("\n");
436 break;
437 }
438 printf(", ");
439 }
440 }
441 printf("Summary: %s\n", cmd->desc);
442 if (cmd->help != NULL) {
443 const char *s;
444 char buf[65];
445 int tot, len, done;
446
447 printf("Description:\n");
448 for (s = cmd->help; *s != '\0'; s += len) {
449 while (isspace(*s))
450 s++;
451 tot = snprintf(buf,
452 sizeof(buf), "%s", s);
453 len = strlen(buf);
454 done = len == tot;
455 if (!done) {
456 while (len > 0
457 && !isspace(buf[len-1]))
458 buf[--len] = '\0';
459 }
460 printf(" %s\n", buf);
461 }
462 }
463 }
464 }
465 return(CMDRTN_OK);
465 return (CMDRTN_OK);
466}
467
468/*
469 * QuitCmd()
470 */
471static int
472QuitCmd(int ac __unused, char **av __unused)
473{
466}
467
468/*
469 * QuitCmd()
470 */
471static int
472QuitCmd(int ac __unused, char **av __unused)
473{
474 return(CMDRTN_QUIT);
474 return (CMDRTN_QUIT);
475}
476
477/*
478 * Dump data in hex and ASCII form
479 */
480void
481DumpAscii(const u_char *buf, int len)
482{
483 char ch, sbuf[100];
484 int k, count;
485
486 for (count = 0; count < len; count += DUMP_BYTES_PER_LINE) {
487 snprintf(sbuf, sizeof(sbuf), "%04x: ", count);
488 for (k = 0; k < DUMP_BYTES_PER_LINE; k++) {
489 if (count + k < len) {
490 snprintf(sbuf + strlen(sbuf),
491 sizeof(sbuf) - strlen(sbuf),
492 "%02x ", buf[count + k]);
493 } else {
494 snprintf(sbuf + strlen(sbuf),
495 sizeof(sbuf) - strlen(sbuf), " ");
496 }
497 }
498 snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " ");
499 for (k = 0; k < DUMP_BYTES_PER_LINE; k++) {
500 if (count + k < len) {
501 ch = isprint(buf[count + k]) ?
502 buf[count + k] : '.';
503 snprintf(sbuf + strlen(sbuf),
504 sizeof(sbuf) - strlen(sbuf), "%c", ch);
505 } else {
506 snprintf(sbuf + strlen(sbuf),
507 sizeof(sbuf) - strlen(sbuf), " ");
508 }
509 }
510 printf("%s\n", sbuf);
511 }
512}
513
514/*
515 * Usage()
516 */
517static void
518Usage(const char *msg)
519{
520 if (msg)
521 warnx("%s", msg);
522 fprintf(stderr,
523 "usage: ngctl [-d] [-f file] [-n name] [command ...]\n");
524 exit(EX_USAGE);
525}
475}
476
477/*
478 * Dump data in hex and ASCII form
479 */
480void
481DumpAscii(const u_char *buf, int len)
482{
483 char ch, sbuf[100];
484 int k, count;
485
486 for (count = 0; count < len; count += DUMP_BYTES_PER_LINE) {
487 snprintf(sbuf, sizeof(sbuf), "%04x: ", count);
488 for (k = 0; k < DUMP_BYTES_PER_LINE; k++) {
489 if (count + k < len) {
490 snprintf(sbuf + strlen(sbuf),
491 sizeof(sbuf) - strlen(sbuf),
492 "%02x ", buf[count + k]);
493 } else {
494 snprintf(sbuf + strlen(sbuf),
495 sizeof(sbuf) - strlen(sbuf), " ");
496 }
497 }
498 snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " ");
499 for (k = 0; k < DUMP_BYTES_PER_LINE; k++) {
500 if (count + k < len) {
501 ch = isprint(buf[count + k]) ?
502 buf[count + k] : '.';
503 snprintf(sbuf + strlen(sbuf),
504 sizeof(sbuf) - strlen(sbuf), "%c", ch);
505 } else {
506 snprintf(sbuf + strlen(sbuf),
507 sizeof(sbuf) - strlen(sbuf), " ");
508 }
509 }
510 printf("%s\n", sbuf);
511 }
512}
513
514/*
515 * Usage()
516 */
517static void
518Usage(const char *msg)
519{
520 if (msg)
521 warnx("%s", msg);
522 fprintf(stderr,
523 "usage: ngctl [-d] [-f file] [-n name] [command ...]\n");
524 exit(EX_USAGE);
525}