7 #include <readline/readline.h>
8 #include <readline/history.h>
20 static const struct TreeNode* getSubCom (char **com, int n, int *t)
23 const struct TreeNode *cur, *next;
27 for (i = 0; i < n; i++) {
28 /* we have reached a terminal command, exit */
32 /* search sub command in sub command array */
33 for (next = cur->sub; next->name != NULL && strcmp(next->name, com[i]) != 0; next++);
35 /* sub command not found, exit */
36 if (next->name == NULL)
39 /* next command is now the current one */
50 static const struct TreeNode *compcur;
53 static char* my_generator (const char* text, int state)
56 static const struct TreeNode *tn;
60 if (compcur == NULL) {
61 /* sub command not found */
63 } else if (state == 0) {
68 if (tn == NULL) /* terminal command */
71 while ((name = tn++->name) != NULL) {
72 if (strncmp(name, text, len) == 0)
81 static char** my_completion (const char *text, int start, int end UNUSED)
83 char **matches = NULL;
84 char *line, *com[MAXCOM];
88 memset(com, 0, MAXCOM * sizeof(char*));
89 line = strdup(rl_line_buffer);
92 n = explode(line, com, MAXCOM);
95 compcur = getSubCom(com, n, &i);
99 matches = rl_completion_matches(text, my_generator);
101 for (i = 0; com[i] != NULL; i++)
109 static struct ngadmin *nga;
110 static sigjmp_buf jmpbuf;
111 static struct termios orig_term;
112 struct termios current_term;
115 NORET static void handler (int sig)
121 printf("interrupt\n");
123 current_term.c_lflag|=ECHO;
124 tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
126 siglongjmp(jmpbuf, 1);
131 tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
138 int main (int argc, char **argv)
140 static const struct option opts[] = {
141 {"keep-broadcasting", no_argument, NULL, 'b'},
142 {"force-interface", no_argument, NULL, 'f'},
143 {"global-broadcast", no_argument, NULL, 'g'},
144 {"interface", required_argument, NULL, 'i'},
145 {"help", no_argument, NULL, 'h'},
146 {"timeout", required_argument, NULL, 't'},
149 char *line, *com[MAXCOM];
150 const char *iface = "eth0";
152 bool kb = false, force = false, global = false;
154 const struct TreeNode *cur, *next;
158 tcgetattr(STDIN_FILENO, &orig_term);
159 current_term = orig_term;
163 while ((n = getopt_long(argc, argv, "bfgi:ht:", opts, NULL)) != -1) {
183 printf("Usage: %s [-b] [-f] [-g] [-i <interface>]\n", argv[0]);
187 timeout = strtof(optarg, NULL);
191 printf("Unknown option: \"%s\"\n", argv[optind - 1]);
200 printf("Unknown trailing options\n");
205 memset(com, 0, MAXCOM * sizeof(char*));
207 nga = ngadmin_init(iface);
209 fprintf(stderr, "Initialization error\n");
215 tv.tv_sec = (int)timeout;
216 tv.tv_usec = (int)((timeout - (float)tv.tv_sec) * 1.e6f);
217 ngadmin_setTimeout(nga, &tv);
221 if (kb && ngadmin_setKeepBroadcasting(nga, true) != ERR_OK)
224 if (force && ngadmin_forceInterface(nga) != ERR_OK)
227 if (global && ngadmin_useGlobalBroadcast(nga, true) != ERR_OK)
230 rl_attempted_completion_function = my_completion;
231 rl_completion_entry_function = my_generator;
233 signal(SIGTERM, handler);
234 signal(SIGINT, handler);
236 sigsetjmp(jmpbuf, 1);
239 line = readline("> ");
242 trim(line, strlen(line));
243 n = explode(line, com, MAXCOM);
253 cur = getSubCom(com, n, &i);
255 if (i < n) { /* commands left unchecked */
256 if (i == 0) { /* root command */
257 printf("unknown command\n");
258 } else if (cur->sub != NULL) { /* intermediate command */
259 printf("unknown %s subcommand\n", com[i - 1]);
260 } else if (!cur->hasArgs) { /* terminal command without arguments */
261 printf("%s as no subcommand and takes no parameter\n", com[i - 1]);
262 } else if (cur->comfunc == NULL) { /* erroneous terminal command without function */
263 printf("terminal command without function\n");
264 } else { /* terminal command with arguments, left "commands" are in fact parameters */
265 cur->comfunc(n - i, (const char**)&com[i], nga);
267 } else { /* no command left */
268 if (cur->sub != NULL) { /* intermediate command */
269 /* print available subcommands */
270 for (next = cur->sub; next->name != NULL; next++)
271 printf("%s ", next->name);
273 } else if (cur->comfunc == NULL) { /* erroneous terminal command without function */
274 printf("terminal command without function\n");
275 } else { /* terminal command without arguments */
276 cur->comfunc(0, NULL, nga);
280 for (i = 0; com[i] != NULL; i++) {