#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;
}
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 ) {