From 540b603b412fa9cd020cbef23977a17589270ec1 Mon Sep 17 00:00:00 2001 From: josch Date: Wed, 17 Sep 2014 00:12:05 +0200 Subject: [PATCH] Add commandline argument parser - add several commandline options to read username, password and server from the commandline - add help output to the commandline - do not automatically call auth upon start-up because the user might want to run commands like "help" which do not require to be signed in - add -c option which, like for dash and bash allows to receive commands via the commandline instead of standard input --- main.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 123 insertions(+), 11 deletions(-) diff --git a/main.c b/main.c index 0e9065a..b92a23a 100644 --- a/main.c +++ b/main.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include @@ -34,16 +36,105 @@ static void mfshell_run(mfshell_t *mfshell); +static void +mfshell_parse_commands(mfshell_t *mfshell, char *command); + int term_resized = 0; int term_height = 0; int term_width = 0; +void print_help(mfshell_t *mfshell, char *cmd) +{ + fprintf(stderr, "A shell to access a MediaFire account.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: %s [options]\n", cmd); + fprintf(stderr, "\n"); + fprintf(stderr, " -h, --help Print this help\n"); + fprintf(stderr, " -v, --version Print version information\n"); + fprintf(stderr, " -c, --command= Run command CMD and exit\n"); + fprintf(stderr, " -u, --username= Login username\n"); + fprintf(stderr, " -p, --password= Login password\n"); + fprintf(stderr, " -s, --server= Login server\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Username and password are optional. If not given, they\n" + "have to be entered via standard input.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "You should not pass your password as a commandline\n" + "argument as other users with access to the list of\n" + "running processes will then be able to see it.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Use the \"help\" command to print a list of available\n" + "commands in the interactive environment:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " %s -c help\n", cmd); + fprintf(stderr, "\n"); +} + +void parse_argv(mfshell_t *mfshell, int argc, char **argv, char **username, + char **password, char **server, char **command) +{ + static struct option long_options[] = { + {"command", required_argument, 0, 'c'}, + {"username", required_argument, 0, 'u'}, + {"password", required_argument, 0, 'p'}, + {"server", required_argument, 0, 's'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'} + }; + + int c; + for (;;) { + c = getopt_long(argc, argv, "c:u:p:s:hv", long_options, NULL); + if (c == -1) + break; + + switch (c) { + case 'c': + *command = strdup(optarg); + break; + case 'u': + *username = strdup(optarg); + break; + case 'p': + *password = strdup(optarg); + break; + case 's': + *server = strdup(optarg); + break; + case 'h': + print_help(mfshell, argv[0]); + exit(0); + case 'v': + exit(0); + case '?': + exit(1); + break; + default: + fprintf(stderr, "getopt_long returned character code %c\n", c); + } + } + + if (optind < argc) { + // TODO: handle non-option argv elements + fprintf(stderr, "Unexpected positional arguments\n"); + exit(1); + } + + if (*password != NULL && *username == NULL) { + fprintf(stderr, "You cannot pass the password without the username\n"); + exit(1); + } +} + int main(int argc,char **argv) { extern int term_height; extern int term_width; mfshell_t *mfshell; char *server = "www.mediafire.com"; + char *username = NULL; + char *password = NULL; + char *command = NULL; size_t len; int retval; @@ -59,23 +150,41 @@ int main(int argc,char **argv) sig_install_SIGWINCH(); - if(argc > 1) - { - if(argv[1] != NULL) server = argv[1]; - } + parse_argv(mfshell, argc, argv, &username, &password, &server, &command); mfshell = mfshell_create(35860, "2c6dq0gb2sr8rgsue5a347lzpjnaay46yjazjcjg",server); - printf("\n\r"); - mfshell->exec(mfshell, "auth"); - - // begin shell mode - mfshell_run(mfshell); + if (command == NULL) { + // begin shell mode + mfshell_run(mfshell); + } else { + // interpret command + mfshell_parse_commands(mfshell, command); + } return 0; } +static void +mfshell_parse_commands(mfshell_t *mfshell, char *command) +{ + char *next; + int ret; + wordexp_t p; + // FIXME: don't split by semicolon but by unescaped/unquoted semicolon + while ((next = strsep(&command, ";")) != NULL) { + // FIXME: handle non-zero return value of wordexp + ret = wordexp(next, &p, WRDE_SHOWERR | WRDE_UNDEF); + if (p.we_wordc < 1) { + fprintf(stderr, "Need more than zero arguments\n"); + exit(1); + } + mfshell->exec(mfshell, p.we_wordc, p.we_wordv); + wordfree(&p); + } +} + static void mfshell_run(mfshell_t *mfshell) { @@ -88,7 +197,10 @@ mfshell_run(mfshell_t *mfshell) { printf("\n\rmfshell > "); - getline(&cmd,&len,stdin); + retval = getline(&cmd,&len,stdin); + if (retval == -1) { + exit(1); + } string_chomp(cmd); printf("\n\r"); @@ -105,7 +217,7 @@ mfshell_run(mfshell_t *mfshell) continue; } - retval = mfshell->exec(mfshell,cmd); + retval = mfshell->exec_string(mfshell,cmd); free(cmd); cmd = NULL; }