#include <stdio.h>
#include <signal.h>
+#include <unistd.h>
#include <setjmp.h>
#include <getopt.h>
#define MAXCOM 32
-int cont = 1;
+int main_loop_continue = 1;
static const struct TreeNode* getSubCom (char **com, int n, int *t)
const struct TreeNode *cur, *next;
- cur = &coms;
+ cur = &commands;
for (i = 0; i < n; i++) {
/* we have reached a terminal command, exit */
if (cur->sub == NULL)
static sigjmp_buf jmpbuf;
static struct termios orig_term;
struct termios current_term;
+static bool batch;
NORET static void handler (int sig)
case SIGINT:
printf("interrupt\n");
- current_term.c_lflag|=ECHO;
+ current_term.c_lflag |= ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
- siglongjmp(jmpbuf, 1);
+ if (!batch)
+ siglongjmp(jmpbuf, 1);
default:
ngadmin_close(nga);
}
+static int pre_login (const struct ether_addr *mac, int retries)
+{
+ const struct swi_attr *sa;
+ int i, n, err;
+
+
+ for (i = 1; retries <= 0 || i <= retries; i++) {
+ /* scan */
+ printf("scan... ");
+ fflush(stdout);
+ err = ngadmin_scan(nga);
+ if (err < 0) {
+ printErrCode(err);
+ return err;
+ }
+
+ /* search switch with requested MAC */
+ sa = ngadmin_getSwitchTab(nga, &n);
+ while (--n >= 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)
{
static const struct option opts[] = {
+ {"batch", no_argument, NULL, 'a'},
{"keep-broadcasting", no_argument, NULL, 'b'},
{"force-interface", no_argument, NULL, 'f'},
- {"global-broadcast", no_argument, NULL, 'g'},
- {"interface", required_argument, NULL, 'i'},
{"help", no_argument, NULL, 'h'},
+ {"interface", required_argument, NULL, 'i'},
+ {"local-broadcast", no_argument, NULL, 'l'},
+ {"mac", required_argument, NULL, 'm'},
+ {"password", required_argument, NULL, 'p'},
+ {"retries", required_argument, NULL, 'r'},
{"timeout", required_argument, NULL, 't'},
{0, 0, 0, 0}
};
char *line, *com[MAXCOM];
- const char *iface = "eth0";
+ const char *iface = "eth0", *password = NULL;
float timeout = 0.f;
- bool kb = false, force = false, global = false;
+ bool kb = false, force = false, global = true;
struct timeval tv;
const struct TreeNode *cur, *next;
- int i, n;
+ struct ether_addr *mac = NULL;
+ int i, n, retries = 3;
tcgetattr(STDIN_FILENO, &orig_term);
current_term = orig_term;
+ batch = false;
opterr = 0;
- while ((n = getopt_long(argc, argv, "bfgi:ht:", opts, NULL)) != -1) {
+ while ((n = getopt_long(argc, argv, "abfhi:lm:p:r:t:", opts, NULL)) != -1) {
switch (n) {
+ case 'a':
+ batch = true;
+ break;
+
case 'b':
kb = true;
break;
force = true;
break;
- case 'g':
- global = true;
- break;
+ case 'h':
+ printf("usage: %s [-a] [-b] [-f] [-g] [-i <interface>] [-m <MAC>] [-p <password>]\n", argv[0]);
+ goto end;
case 'i':
iface = optarg;
break;
- case 'h':
- printf("Usage: %s [-b] [-f] [-g] [-i <interface>]\n", argv[0]);
- goto end;
+ 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]);
+ printf("unknown option: \"%s\"\n", argv[optind - 1]);
goto end;
}
}
argv += optind;
if (argc != 0) {
- printf("Unknown trailing options\n");
+ printf("unknown trailing options\n");
goto end;
}
nga = ngadmin_init(iface);
if (nga == NULL) {
- fprintf(stderr, "Initialization error\n");
+ fprintf(stderr, "initialization error\n");
goto end;
}
}
- if (kb && ngadmin_setKeepBroadcasting(nga, true) != ERR_OK)
+ if (ngadmin_setKeepBroadcasting(nga, kb) != ERR_OK)
goto end;
if (force && ngadmin_forceInterface(nga) != ERR_OK)
goto end;
- if (global && ngadmin_useGlobalBroadcast(nga, true) != ERR_OK)
+ if (ngadmin_useGlobalBroadcast(nga, global) != ERR_OK)
goto end;
- rl_attempted_completion_function = my_completion;
- rl_completion_entry_function = my_generator;
+ /* 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);
- sigsetjmp(jmpbuf, 1);
+ /* 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 (cont) {
- line = readline("> ");
- if (line == NULL)
+ 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);
free(line);
continue;
} else {
- add_history(line);
+ if (!batch)
+ add_history(line);
free(line);
}
cur = getSubCom(com, n, &i);
- if (i < n) { /* commands left unchecked */
- 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 { /* no command left */
- if (cur->sub != NULL) { /* intermediate command */
+ 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);
- printf("\n");
- } 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);
+ 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++) {