7 #include <readline/readline.h>
8 #include <readline/history.h>
24 const struct TreeNode* getSubCom (char **com, int n, int *t) {
27 const struct TreeNode *cur, *next;
33 // we have reached a terminal command, exit
34 if ( cur->sub==NULL ) break;
36 // search sub command in sub command array
37 for (next=cur->sub; next->name!=NULL && strcmp(next->name, com[i])!=0; ++next);
39 // sub command not found, exit
40 if ( next->name==NULL ) break;
42 // next command is now the current one
57 const struct TreeNode *compcur;
61 char* my_generator (const char* text, int state) {
64 static const struct TreeNode *tn;
68 if ( compcur==NULL ) { // sub command not found
70 } else if ( state==0 ) {
75 if ( tn==NULL ) { // terminal command
80 while ( (name=tn++->name)!=NULL )
81 if ( strncmp(name, text, len)==0 )
91 char** my_completion (const char *text, int start, int end UNUSED) {
94 char *line, *com[MAXCOM];
98 memset(com, 0, MAXCOM*sizeof(char*));
99 line=strdup(rl_line_buffer);
102 n=explode(line, com, MAXCOM);
105 compcur=getSubCom(com, n, &i);
107 if ( i<n ) compcur=NULL;
108 matches=rl_completion_matches(text, my_generator);
110 for (i=0; com[i]!=NULL; ++i) {
121 static struct ngadmin *nga=NULL;
122 static sigjmp_buf jmpbuf;
123 struct termios orig_term, current_term;
127 NORET static void handler (int sig) {
134 printf("interrupt\n");
136 current_term.c_lflag|=ECHO;
137 tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
139 siglongjmp(jmpbuf, 1);
144 tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
155 int main (int argc, char **argv) {
157 static const struct option opts[]={
158 {"keep-broadcasting", no_argument, NULL, 'b'},
159 {"force-interface", no_argument, NULL, 'f'},
160 {"global-broadcast", no_argument, NULL, 'g'},
161 {"interface", required_argument, NULL, 'i'},
162 {"help", no_argument, NULL, 'h'},
163 {"timeout", required_argument, NULL, 't'},
166 char *line, *com[MAXCOM];
167 const char *iface="eth0";
169 bool kb=false, force=false, global=false;
171 const struct TreeNode *cur, *next;
176 tcgetattr(STDIN_FILENO, &orig_term);
177 current_term=orig_term;
179 current_term.c_lflag&=~ECHOCTL;
180 tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
186 while ( (n=getopt_long(argc, argv, "bfgi:ht:", opts, NULL))!=-1 ) {
206 printf("Usage: %s [-b] [-f] [-g] [-i <interface>]\n", argv[0]);
210 timeout=strtof(optarg, NULL);
214 printf("Unknown option: \"%s\"\n", argv[optind-1]);
225 printf("Unknown trailing options\n");
230 memset(com, 0, MAXCOM*sizeof(char*));
232 if ( (nga=ngadmin_init(iface))==NULL ) {
233 fprintf(stderr, "Initialization error\n");
239 tv.tv_sec=(int)timeout;
240 tv.tv_usec=(int)((timeout-(float)tv.tv_sec)*1.e6f);
241 ngadmin_setTimeout(nga, &tv);
245 if ( kb && ngadmin_setKeepBroadcasting(nga, true)!=ERR_OK ) goto end;
247 if ( force && ngadmin_forceInterface(nga)!=ERR_OK ) goto end;
249 if ( global && ngadmin_useGlobalBroadcast(nga, true)!=ERR_OK ) goto end;
253 //rl_bind_key('\t', rl_abort); // disable auto completion
254 //rl_bind_key('\t', rl_complete); // enable auto-complete
255 rl_attempted_completion_function=my_completion;
256 rl_completion_entry_function=my_generator;
260 signal(SIGTERM, handler);
261 signal(SIGINT, handler);
263 sigsetjmp(jmpbuf, 1);
268 if ( (line=readline("> "))==NULL ) goto end;
269 trim(line, strlen(line));
270 n=explode(line, com, MAXCOM);
280 cur=getSubCom(com, n, &i);
282 if ( i<n ) { // commands left unchecked
284 if ( i==0 ) { // root command
285 printf("unknown command\n");
286 } else if ( cur->sub!=NULL ) { // intermediate command
287 printf("unknown %s subcommand\n", com[i-1]);
288 } else if ( !cur->hasArgs ) { // terminal command without arguments
289 printf("%s as no subcommand and takes no parameter\n", com[i-1]);
290 } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
291 printf("terminal command without function\n");
292 } else { // terminal command with arguments, left "commands" are in fact parameters
293 cur->comfunc(n-i, (const char**)&com[i], nga);
296 } else { // no command left
298 if ( cur->sub!=NULL ) { // intermediate command
299 // print available subcommands
300 for (next=cur->sub; next->name!=NULL; ++next) {
301 printf("%s ", next->name);
304 } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
305 printf("terminal command without function\n");
306 } else { // terminal command without arguments
307 cur->comfunc(0, NULL, nga);
313 for (i=0; com[i]!=NULL; ++i) {