]> git.sur5r.net Git - ngadmin/blobdiff - cli/admin.c
Added support for changing VLAN 802.1q and PVID configuration.
[ngadmin] / cli / admin.c
index 523a96c188a6430d073ce3752fcafc1f506cc5fe..9e0aea6ac9478d20664bc58a77b43a85cec62e04 100644 (file)
 
 #include <stdio.h>
 
+#include <getopt.h>
 #include <readline/readline.h>
 #include <readline/history.h>
 
-#include "command.h"
 #include "common.h"
+#include "commands.h"
 
 
 
 
-#define MAXCOM 8
+#define MAXCOM 32
 
 
+int cont=1;
 
 
 
-int cont=1;
+
+const struct TreeNode* getSubCom (char **com, int n, int *t) {
+ int i;
+ const struct TreeNode *cur, *next;
+ cur=&coms;
+ for (i=0; i<n; ++i) {
+  
+  // we have reached a terminal command, exit
+  if ( cur->sub==NULL ) break;
+  
+  // search sub command in sub command array
+  for (next=cur->sub; next->name!=NULL && strcmp(next->name, com[i])!=0; ++next);
+  
+  // sub command not found, exit
+  if ( next->name==NULL ) {
+   next=NULL;
+   break;
+  }
+  
+  // next command is now the current one
+  cur=next;
+  
+ }
+ *t=i;
+ return cur;
+}
+
+
 
 
-static const struct TreeNode rootNode={.sub={
- &com_quit,
- &com_login, 
- &com_scan, 
- &com_ports, 
- &com_password, 
- &com_list, 
- &com_firmware, 
- &com_name, 
- NULL
-}};
+const struct TreeNode *compcur;
 
 
 
-void printErrCode (int err) {
+char* my_generator (const char* text, int state) {
+ static int len;
+ static const struct TreeNode *tn;
+ const char *name;
+ if ( compcur==NULL ) { // sub command not found
+  return NULL;
+ } else if ( state==0 ) {
+  tn=compcur->sub;
+  len=strlen(text);
+ }
+ if ( tn==NULL ) { // terminal command
+  return NULL;
+ }
  
  
- switch ( err ) {
-  case ERR_OK: /*printf("ok\n");*/ break;
-  case ERR_NET: printf("network error\n"); break;
-  case ERR_NOTLOG: printf("no switch selected\n"); break;
-  case ERR_BADPASS: printf("wrong password\n"); break;
-  case ERR_BADID: printf("bad switch id\n"); break;
-  case ERR_INVARG: printf("invalid argument\n"); break;
-  case ERR_TIMEOUT: printf("timeout\n"); break;
-  default: printf("unknown status code (%i)\n", err);
+ while ( (name=tn->name)!=NULL ) {
+  ++tn;
+  
+  if ( strncmp(name, text, len)==0 ) {
+   return strdup(name);
+  }
+  
  }
  
  
+ return NULL;
 }
 
 
 
-void displaySwitchTab (const struct swi_attr *sa, int nb) {
+char** my_completion (const char *text, int start, int end UNUSED) {
  
- int i=0;
+ char **matches=NULL;
+ char *line, *com[MAXCOM];
+ int i, n;
  
  
- if ( nb==0 ) {
-  printf("no switch found\n");
-  return;
- }
  
+ memset(com, 0, MAXCOM*sizeof(char*));
+ line=strdup(rl_line_buffer);
+ line[start]=0;
+ trim(line, start);
+ n=explode(line, com, MAXCOM);
+ free(line);
  
printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\t\t\t\tDHCP\tPorts\tFirmware\n");
compcur=getSubCom(com, n, &i);
  
- for (i=0; i<nb; ++i) {
-  printf("%i\t%s\t%s\t\t%s\t%s/", i, ether_ntoa(&sa[i].mac), sa[i].product, sa[i].name, inet_ntoa(sa[i].nc.ip));
-  printf("%s\t%s\t%i\t%s\n", inet_ntoa(sa[i].nc.netmask), ( sa[i].nc.dhcp ? "Yes" : "No" ), sa[i].ports, sa[i].firmware);
- }
+ if ( i<n ) compcur=NULL;
+ matches=rl_completion_matches(text, my_generator);
  
- printf("\nfound %i switch(es)\n", nb);
  
+ return matches;
  
 }
 
@@ -80,90 +124,135 @@ void displaySwitchTab (const struct swi_attr *sa, int nb) {
 
 int main (int argc, char **argv) {
  
+ static const struct option opts[]={
+  {"keep-broadcasting", no_argument, NULL, 'b'}, 
+  {"force-interface", no_argument, NULL, 'f'}, 
+  {"interface", required_argument, NULL, 'i'}, 
+  {"help", no_argument, NULL, 'h'}, 
+  {"timeout", required_argument, NULL, 't'}, 
+  {0, 0, 0, 0}
+ };
  char *line, *com[MAXCOM];
+ const char *iface="eth0";
+ float timeout=0.f;
+ bool kb=false, force=false;
  struct ngadmin *nga=NULL;
  struct timeval tv;
- const struct TreeNode *cur, *next, **tab;
+ const struct TreeNode *cur, *next;
  int i, n;
  
  
  
- if ( argc<2 ) {
-  printf("Usage: %s <interface>\n", argv[0]);
-  return 1;
+ opterr=0;
+ while ( (n=getopt_long(argc, argv, "bfi:ht:", opts, NULL))!=-1 ) {
+  switch ( n ) {
+   
+   case 'b':
+    kb=true;
+   break;
+   
+   case 'f':
+    force=true;
+   break;
+   
+   case 'i':
+    iface=optarg;
+   break;
+   
+   case 'h':
+    printf("Usage: %s [-b] [-f] [-i <interface>]\n", argv[0]);
+    goto end;
+   
+   case 't':
+    timeout=strtof(optarg, NULL);
+   break;
+   
+   case '?':
+    printf("Unknown option: \"%s\"\n", argv[optind-1]);
+    goto end;
+   
+  }
+ }
+ argc-=optind;
+ argv+=optind;
+ if ( argc!=0 ) {
+  printf("Unknown trailing options\n");
+  goto end;
  }
  
  memset(com, 0, MAXCOM*sizeof(char*));
  
- if ( (nga=ngadmin_init(argv[1]))==NULL ) {
+ if ( (nga=ngadmin_init(iface))==NULL ) {
   fprintf(stderr, "Initialization error\n");
   goto end;
  }
  
  // set timeout
- tv.tv_sec=3;
- tv.tv_usec=0;
- ngadmin_setTimeout(nga, &tv);
+ if ( timeout>0.f ) {
+  tv.tv_sec=(int)timeout;
+  tv.tv_usec=(int)((timeout-(float)tv.tv_sec)*1e6f);
+  ngadmin_setTimeout(nga, &tv);
+ }
  
+ if ( kb && ngadmin_setKeepBroadcasting(nga, true)!=ERR_OK ) goto end;
  
- rl_bind_key('\t', rl_abort); // disable auto completion
+ if ( force && ngadmin_forceInterface(nga)!=ERR_OK ) goto end;
+ //rl_bind_key('\t', rl_abort); // disable auto completion
+ //rl_bind_key('\t', rl_complete); // enable auto-complete
+ rl_attempted_completion_function=my_completion;
+ rl_completion_entry_function=my_generator;
  
  
  while ( cont ) {
   
   if ( (line=readline("> "))==NULL ) goto end;
-  trim(line, strlen(line));
   if ( *line!=0 ) add_history(line);
+  trim(line, strlen(line));
   n=explode(line, com, MAXCOM);
   free(line);
   
+  if ( n==0 ) continue;
   
-  i=0;
-  for (next=&rootNode; i<n; ++i) {
-   cur=next;
-   for (tab=cur->sub; (next=*tab)!=NULL && strcmp(next->name, com[i])!=0; ++tab);
-   if ( next==NULL ) break;
-  }
-  
+  cur=getSubCom(com, n, &i);
   
-  if ( i<n ) { // commands left uncompared
+  if ( i<n ) { // commands left unchecked
    
-   if ( cur->hasArgs ) { // left "commands" are in fact parameters
-    cur->comfunc(cur, n-i, (const char**)&com[i], nga);
-   } else {
-    if ( i==0 ) {
-     printf("unknown command\n");
-    } else {
-     printf("unknown %s subcommand\n", com[i-1]);
-    }
+   if ( i==0 ) { // root command
+    printf("unknown command\n");
+   } else if ( cur->sub!=NULL ) { // intermediate command
+    printf("unknown %s subcommand\n", com[i-1]);
+   } else if ( !cur->hasArgs ) { // terminal command without arguments
+    printf("%s as no subcommand and takes no parameter\n", com[i-1]);
+   } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
+    printf("terminal command without function\n");
+   } else { // terminal command with arguments, left "commands" are in fact parameters
+    cur->comfunc(n-i, (const char**)&com[i], nga);
    }
    
-  } else {
+  } else { // no command left
    
-   cur=next;
-   if ( cur->comfunc==NULL ) {
+   if ( cur->sub!=NULL ) { // intermediate command
     // print available subcommands
-    for (tab=cur->sub; (next=*tab)!=NULL; ++tab) {
+    for (next=cur->sub; next->name!=NULL; ++next) {
      printf("%s ", next->name);
     }
     printf("\n");
-    
-   } else { // terminal command
-   
-    cur->comfunc(cur, 0, NULL, nga);
-    
+   } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
+    printf("terminal command without function\n");
+   } else { // terminal command without arguments
+    cur->comfunc(0, NULL, nga); 
    }
-  }
-  
-  /*
-  if ( n==0 ) {
-   // nothing: do nothing
-   
-  } else if ( strcmp(com[0], "timeout")==0 ) {
-   // 
    
   }
-  */
+  
   
   for (i=0; i<MAXCOM; i++) {
    if ( com[i]!=NULL ) {