5 #include <readline/readline.h>
6 #include <readline/history.h>
22 const struct TreeNode* getSubCom (char **com, int n, int *t) {
25 const struct TreeNode *cur, *next;
31 // we have reached a terminal command, exit
32 if ( cur->sub==NULL ) break;
34 // search sub command in sub command array
35 for (next=cur->sub; next->name!=NULL && strcmp(next->name, com[i])!=0; ++next);
37 // sub command not found, exit
38 if ( next->name==NULL ) {
43 // next command is now the current one
58 const struct TreeNode *compcur;
62 char* my_generator (const char* text, int state) {
65 static const struct TreeNode *tn;
69 if ( compcur==NULL ) { // sub command not found
71 } else if ( state==0 ) {
76 if ( tn==NULL ) { // terminal command
81 while ( (name=tn->name)!=NULL ) {
84 if ( strncmp(name, text, len)==0 ) {
97 char** my_completion (const char *text, int start, int end UNUSED) {
100 char *line, *com[MAXCOM];
105 memset(com, 0, MAXCOM*sizeof(char*));
106 line=strdup(rl_line_buffer);
109 n=explode(line, com, MAXCOM);
112 compcur=getSubCom(com, n, &i);
114 if ( i<n ) compcur=NULL;
115 matches=rl_completion_matches(text, my_generator);
125 int main (int argc, char **argv) {
127 static const struct option opts[]={
128 {"keep-broadcasting", no_argument, NULL, 'b'},
129 {"force-interface", no_argument, NULL, 'f'},
130 {"interface", required_argument, NULL, 'i'},
131 {"help", no_argument, NULL, 'h'},
132 {"timeout", required_argument, NULL, 't'},
135 char *line, *com[MAXCOM];
136 const char *iface="eth0";
138 bool kb=false, force=false;
139 struct ngadmin *nga=NULL;
141 const struct TreeNode *cur, *next;
148 while ( (n=getopt_long(argc, argv, "bfi:ht:", opts, NULL))!=-1 ) {
164 printf("Usage: %s [-b] [-f] [-i <interface>]\n", argv[0]);
168 timeout=strtof(optarg, NULL);
172 printf("Unknown option: \"%s\"\n", argv[optind-1]);
183 printf("Unknown trailing options\n");
188 memset(com, 0, MAXCOM*sizeof(char*));
190 if ( (nga=ngadmin_init(iface))==NULL ) {
191 fprintf(stderr, "Initialization error\n");
197 tv.tv_sec=(int)timeout;
198 tv.tv_usec=(int)((timeout-(float)tv.tv_sec)*1e6f);
199 ngadmin_setTimeout(nga, &tv);
203 if ( kb && ngadmin_setKeepBroadcasting(nga, true)!=ERR_OK ) goto end;
205 if ( force && ngadmin_forceInterface(nga)!=ERR_OK ) goto end;
208 //rl_bind_key('\t', rl_abort); // disable auto completion
209 //rl_bind_key('\t', rl_complete); // enable auto-complete
210 rl_attempted_completion_function=my_completion;
211 rl_completion_entry_function=my_generator;
216 if ( (line=readline("> "))==NULL ) goto end;
217 if ( *line!=0 ) add_history(line);
218 trim(line, strlen(line));
219 n=explode(line, com, MAXCOM);
222 if ( n==0 ) continue;
224 cur=getSubCom(com, n, &i);
226 if ( i<n ) { // commands left unchecked
228 if ( i==0 ) { // root command
229 printf("unknown command\n");
230 } else if ( cur->sub!=NULL ) { // intermediate command
231 printf("unknown %s subcommand\n", com[i-1]);
232 } else if ( !cur->hasArgs ) { // terminal command without arguments
233 printf("%s as no subcommand and takes no parameter\n", com[i-1]);
234 } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
235 printf("terminal command without function\n");
236 } else { // terminal command with arguments, left "commands" are in fact parameters
237 cur->comfunc(n-i, (const char**)&com[i], nga);
240 } else { // no command left
242 if ( cur->sub!=NULL ) { // intermediate command
243 // print available subcommands
244 for (next=cur->sub; next->name!=NULL; ++next) {
245 printf("%s ", next->name);
248 } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
249 printf("terminal command without function\n");
250 } else { // terminal command without arguments
251 cur->comfunc(0, NULL, nga);
257 for (i=0; i<MAXCOM; i++) {
258 if ( com[i]!=NULL ) {