X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=cli%2Fadmin.c;h=f5b691b305fd555e9ec0054fc3f08c401e0918fc;hb=3fbe066f6a8c2eddec9ed3555ddc5b41fd427c90;hp=523a96c188a6430d073ce3752fcafc1f506cc5fe;hpb=192ea617675b35fe37460a0fbb0c1511c0074fe8;p=ngadmin diff --git a/cli/admin.c b/cli/admin.c index 523a96c..f5b691b 100644 --- a/cli/admin.c +++ b/cli/admin.c @@ -1,186 +1,393 @@ #include +#include +#include +#include +#include #include #include -#include "command.h" #include "common.h" +#include "commands.h" +#define MAXCOM 32 -#define MAXCOM 8 - - +int main_loop_continue = 1; +static const struct TreeNode* getSubCom (char **com, int n, int *t) +{ + int i; + const struct TreeNode *cur, *next; + + + cur = &commands; + 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) + break; + + /* next command is now the current one */ + cur = next; + } + + *t = i; + + + return cur; +} -int cont=1; +static const struct TreeNode *compcur; -static const struct TreeNode rootNode={.sub={ - &com_quit, - &com_login, - &com_scan, - &com_ports, - &com_password, - &com_list, - &com_firmware, - &com_name, - NULL -}}; +static 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; + + while ((name = tn++->name) != NULL) { + if (strncmp(name, text, len) == 0) + return strdup(name); + } + + + return NULL; +} -void printErrCode (int err) { - - - 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); - } - - +static char** my_completion (const char *text, int start, int end UNUSED) +{ + char **matches = NULL; + char *line, *com[MAXCOM]; + int i, n; + + + memset(com, 0, MAXCOM * sizeof(char*)); + line = strdup(rl_line_buffer); + line[start] = '\0'; + trim(line, start); + n = explode(line, com, MAXCOM); + free(line); + + compcur = getSubCom(com, n, &i); + + if (i < n) + compcur = NULL; + matches = rl_completion_matches(text, my_generator); + + for (i = 0; com[i] != NULL; i++) + free(com[i]); + + + return matches; } +static struct ngadmin *nga; +static sigjmp_buf jmpbuf; +static struct termios orig_term; +struct termios current_term; +static bool batch; -void displaySwitchTab (const struct swi_attr *sa, int nb) { - - int i=0; - - - if ( nb==0 ) { - printf("no switch found\n"); - return; - } - - - printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\t\t\t\tDHCP\tPorts\tFirmware\n"); - - for (i=0; i= 0) { + if (memcmp(mac, &sa[n].mac, ETH_ALEN) == 0) + break; + } + + if (n < 0) { + printf("no switch found\n"); + } else { + printf("done\n"); + break; + } + } + + if (n < 0) + return 1; + + /* login */ + printf("login... "); + fflush(stdout); + err = ngadmin_login(nga, n); + if (err < 0) + printErrCode(err); + else + printf("done\n"); + + return err; +} -int main (int argc, char **argv) { - - char *line, *com[MAXCOM]; - struct ngadmin *nga=NULL; - struct timeval tv; - const struct TreeNode *cur, *next, **tab; - int i, n; - - - - if ( argc<2 ) { - printf("Usage: %s \n", argv[0]); - return 1; - } - - memset(com, 0, MAXCOM*sizeof(char*)); - - if ( (nga=ngadmin_init(argv[1]))==NULL ) { - fprintf(stderr, "Initialization error\n"); - goto end; - } - - // set timeout - tv.tv_sec=3; - tv.tv_usec=0; - ngadmin_setTimeout(nga, &tv); - - - rl_bind_key('\t', rl_abort); // disable auto completion - - - while ( cont ) { - - if ( (line=readline("> "))==NULL ) goto end; - trim(line, strlen(line)); - if ( *line!=0 ) add_history(line); - n=explode(line, com, MAXCOM); - free(line); - - - i=0; - for (next=&rootNode; isub; (next=*tab)!=NULL && strcmp(next->name, com[i])!=0; ++tab); - if ( next==NULL ) break; - } - - - if ( ihasArgs ) { // 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]); - } - } - - } else { - - cur=next; - if ( cur->comfunc==NULL ) { - // print available subcommands - for (tab=cur->sub; (next=*tab)!=NULL; ++tab) { - printf("%s ", next->name); - } - printf("\n"); - - } else { // terminal command - - cur->comfunc(cur, 0, NULL, nga); - - } - } - - /* - if ( n==0 ) { - // nothing: do nothing - - } else if ( strcmp(com[0], "timeout")==0 ) { - // - - } - */ - - for (i=0; i] [-m ] [-p ]\n", argv[0]); + goto end; + + case 'i': + iface = optarg; + break; + + case 'l': + global = false; + break; + + case 'm': + mac = ether_aton(optarg); + if (mac == NULL) { + printf("invalid MAC\n"); + goto end; + } + break; + + case 'p': + password = optarg; + break; + + case 'r': + retries = strtol(optarg, NULL, 0); + break; + + 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*)); + + nga = ngadmin_init(iface); + if (nga == NULL) { + fprintf(stderr, "initialization error\n"); + goto end; + } + + /* set timeout */ + if (timeout > 0.f) { + tv.tv_sec = (int)timeout; + tv.tv_usec = (int)((timeout - (float)tv.tv_sec) * 1.e6f); + ngadmin_setTimeout(nga, &tv); + } + + + if (ngadmin_setKeepBroadcasting(nga, kb) != ERR_OK) + goto end; + + if (force && ngadmin_forceInterface(nga) != ERR_OK) + goto end; + + if (ngadmin_useGlobalBroadcast(nga, global) != ERR_OK) + goto end; + + /* non-TTY inputs are automatically set to batch mode */ + if (!isatty(STDIN_FILENO)) + batch = true; + + if (password != NULL) + ngadmin_setPassword(nga, password); + + signal(SIGTERM, handler); + signal(SIGINT, handler); + + /* automatic scan & login when switch MAC is specified on the command line */ + if (mac != NULL && pre_login(mac, retries) != 0) + goto end; + + if (batch) { + /* in batch mode, we must be logged to continue */ + if (ngadmin_getCurrentSwitch(nga) == NULL) { + printf("must be logged\n"); + goto end; + } + } else { + /* initialize readline functions */ + rl_attempted_completion_function = my_completion; + rl_completion_entry_function = my_generator; + + sigsetjmp(jmpbuf, 1); + } + + while (main_loop_continue) { + /* read user input */ + line = NULL; + n = 0; + if (batch) + n = getline(&line, (size_t*)&i, stdin); + else + line = readline("> "); + if (n < 0 || line == NULL) + goto end; + + /* split string into words */ + trim(line, strlen(line)); + n = explode(line, com, MAXCOM); + + if (n == 0) { + free(line); + continue; + } else { + if (!batch) + add_history(line); + free(line); + } + + cur = getSubCom(com, n, &i); + + if (cur->sub != NULL) { + /* not terminal command */ + if (i == 0) { + /* root command */ + printf("unknown command: %s\n", com[i]); + } else if (i < n) { + /* intermediate command, remaining string */ + printf("unknown %s subcommand: %s\n", com[i - 1], com[i]); + } else { + /* intermediate command, no remaining string */ + /* print available subcommands */ + for (next = cur->sub; next->name != NULL; next++) + printf("%s ", next->name); + putchar('\n'); + } + } else if (cur->comfunc == NULL) { + /* erroneous terminal command without function */ + printf("terminal command without function\n"); + } else { + /* execute terminal command */ + cur->comfunc(n - i, (const char**)&com[i], nga); + } + + for (i = 0; com[i] != NULL; i++) { + free(com[i]); + com[i] = NULL; + } + } + +end: + handler(0); }