]> git.sur5r.net Git - ngadmin/blob - cli/admin.c
Added the possibility to specify the command timeout.
[ngadmin] / cli / admin.c
1
2 #include <stdio.h>
3
4 #include <getopt.h>
5 #include <readline/readline.h>
6 #include <readline/history.h>
7
8 #include "common.h"
9 #include "commands.h"
10
11
12
13
14 #define MAXCOM  32
15
16
17 int cont=1;
18
19
20
21
22 const struct TreeNode* getSubCom (char **com, int n, int *t) {
23  
24  int i;
25  const struct TreeNode *cur, *next;
26  
27  
28  cur=&coms;
29  for (i=0; i<n; ++i) {
30   
31   // we have reached a terminal command, exit
32   if ( cur->sub==NULL ) break;
33   
34   // search sub command in sub command array
35   for (next=cur->sub; next->name!=NULL && strcmp(next->name, com[i])!=0; ++next);
36   
37   // sub command not found, exit
38   if ( next->name==NULL ) {
39    next=NULL;
40    break;
41   }
42   
43   // next command is now the current one
44   cur=next;
45   
46  }
47  
48  *t=i;
49  
50  
51  return cur;
52  
53 }
54
55
56
57
58 const struct TreeNode *compcur;
59
60
61
62 char* my_generator (const char* text, int state) {
63  
64  static int len;
65  static const struct TreeNode *tn;
66  const char *name;
67  
68  
69  if ( compcur==NULL ) { // sub command not found
70   return NULL;
71  } else if ( state==0 ) {
72   tn=compcur->sub;
73   len=strlen(text);
74  }
75  
76  if ( tn==NULL ) { // terminal command
77   return NULL;
78  }
79  
80  
81  while ( (name=tn->name)!=NULL ) {
82   ++tn;
83   
84   if ( strncmp(name, text, len)==0 ) {
85    return strdup(name);
86   }
87   
88  }
89  
90  
91  return NULL;
92  
93 }
94
95
96
97 char** my_completion (const char *text, int start, int end UNUSED) {
98  
99  char **matches=NULL;
100  char *line, *com[MAXCOM];
101  int i, n;
102  
103  
104  
105  memset(com, 0, MAXCOM*sizeof(char*));
106  line=strdup(rl_line_buffer);
107  line[start]=0;
108  trim(line, start);
109  n=explode(line, com, MAXCOM);
110  free(line);
111  
112  compcur=getSubCom(com, n, &i);
113  
114  if ( i<n ) compcur=NULL;
115  matches=rl_completion_matches(text, my_generator);
116  
117  
118  return matches;
119  
120 }
121
122
123
124
125 int main (int argc, char **argv) {
126  
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'}, 
133   {0, 0, 0, 0}
134  };
135  char *line, *com[MAXCOM];
136  const char *iface="eth0";
137  float timeout=0.f;
138  bool kb=false, force=false;
139  struct ngadmin *nga=NULL;
140  struct timeval tv;
141  const struct TreeNode *cur, *next;
142  int i, n;
143  
144  
145  
146  opterr=0;
147  
148  while ( (n=getopt_long(argc, argv, "bfi:ht:", opts, NULL))!=-1 ) {
149   switch ( n ) {
150    
151    case 'b':
152     kb=true;
153    break;
154    
155    case 'f':
156     force=true;
157    break;
158    
159    case 'i':
160     iface=optarg;
161    break;
162    
163    case 'h':
164     printf("Usage: %s [-b] [-f] [-i <interface>]\n", argv[0]);
165     goto end;
166    
167    case 't':
168     timeout=strtof(optarg, NULL);
169    break;
170    
171    case '?':
172     printf("Unknown option: \"%s\"\n", argv[optind-1]);
173     goto end;
174    
175   }
176  }
177  
178  argc-=optind;
179  argv+=optind;
180  
181  
182  if ( argc!=0 ) {
183   printf("Unknown trailing options\n");
184   goto end;
185  }
186  
187  
188  memset(com, 0, MAXCOM*sizeof(char*));
189  
190  if ( (nga=ngadmin_init(iface))==NULL ) {
191   fprintf(stderr, "Initialization error\n");
192   goto end;
193  }
194  
195  // set timeout
196  if ( timeout>0.f ) {
197   tv.tv_sec=(int)timeout;
198   tv.tv_usec=(int)((timeout-(float)tv.tv_sec)*1e6f);
199   ngadmin_setTimeout(nga, &tv);
200  }
201  
202  
203  if ( kb && ngadmin_setKeepBroadcasting(nga, true)!=ERR_OK ) goto end;
204  
205  if ( force && ngadmin_forceInterface(nga)!=ERR_OK ) goto end;
206  
207  
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;
212  
213  
214  while ( cont ) {
215   
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);
220   free(line);
221   
222   if ( n==0 ) continue;
223   
224   cur=getSubCom(com, n, &i);
225   
226   if ( i<n ) { // commands left unchecked
227    
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);
238    }
239    
240   } else { // no command left
241    
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);
246     }
247     printf("\n");
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); 
252    }
253    
254   }
255   
256   
257   for (i=0; i<MAXCOM; i++) {
258    if ( com[i]!=NULL ) {
259     free(com[i]);
260     com[i]=NULL;
261    }
262   }
263   
264  }
265  
266  
267  end:
268  ngadmin_close(nga);
269  
270  
271  return 0;
272  
273 }
274
275