diff options
Diffstat (limited to 'src/main/options.c')
-rw-r--r-- | src/main/options.c | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/src/main/options.c b/src/main/options.c new file mode 100644 index 0000000..3b180cf --- /dev/null +++ b/src/main/options.c @@ -0,0 +1,272 @@ +/* + * Parse command-line options. + * + * Copyright 2012 Andrew Wood, distributed under the Artistic License 2.0. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "options.h" +#include "library/getopt.h" +#include "pv.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + + +void display_help(void); +void display_version(void); + + +/* + * Free an opts_t object. + */ +void opts_free(opts_t opts) +{ + if (!opts) + return; + if (opts->argv) + free(opts->argv); + free(opts); +} + + +/* + * Parse the given command-line arguments into an opts_t object, handling + * "help", "license" and "version" options internally. + * + * Returns an opts_t, or 0 on error. + * + * Note that the contents of *argv[] (i.e. the command line parameters) + * aren't copied anywhere, just the pointers are copied, so make sure the + * command line data isn't overwritten or argv[1] free()d or whatever. + */ +opts_t opts_parse(int argc, char **argv) +{ +#ifdef HAVE_GETOPT_LONG + struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'V'}, + {"progress", 0, 0, 'p'}, + {"timer", 0, 0, 't'}, + {"eta", 0, 0, 'e'}, + {"rate", 0, 0, 'r'}, + {"average-rate", 0, 0, 'a'}, + {"bytes", 0, 0, 'b'}, + {"force", 0, 0, 'f'}, + {"numeric", 0, 0, 'n'}, + {"quiet", 0, 0, 'q'}, + {"cursor", 0, 0, 'c'}, + {"wait", 0, 0, 'W'}, + {"size", 1, 0, 's'}, + {"line-mode", 0, 0, 'l'}, + {"interval", 1, 0, 'i'}, + {"width", 1, 0, 'w'}, + {"height", 1, 0, 'H'}, + {"name", 1, 0, 'N'}, + {"rate-limit", 1, 0, 'L'}, + {"buffer-size", 1, 0, 'B'}, + {"remote", 1, 0, 'R'}, + {0, 0, 0, 0} + }; + int option_index = 0; +#endif + char *short_options = "hVpterabfnqcWs:li:w:H:N:L:B:R:"; + int c, numopts; + opts_t opts; + + opts = calloc(1, sizeof(*opts)); + if (!opts) { + fprintf(stderr, /* RATS: ignore */ + _("%s: option structure allocation failed (%s)"), + argv[0], strerror(errno)); + fprintf(stderr, "\n"); + return 0; + } + + opts->program_name = argv[0]; + + opts->argc = 0; + opts->argv = calloc(argc + 1, sizeof(char *)); + if (!opts->argv) { + fprintf(stderr, /* RATS: ignore */ + _ + ("%s: option structure argv allocation failed (%s)"), + argv[0], strerror(errno)); + fprintf(stderr, "\n"); + opts_free(opts); + return 0; + } + + numopts = 0; + + opts->interval = 1; + + do { +#ifdef HAVE_GETOPT_LONG + c = getopt_long(argc, argv, /* RATS: ignore */ + short_options, long_options, + &option_index); +#else + c = getopt(argc, argv, short_options); /* RATS: ignore */ +#endif + if (c < 0) + continue; + + /* + * Check that any numeric arguments are of the right type. + */ + switch (c) { + case 's': + case 'w': + case 'H': + case 'L': + case 'B': + case 'R': + if (pv_getnum_check(optarg, 0)) { + fprintf(stderr, "%s: -%c: %s\n", argv[0], + c, _("integer argument expected")); + opts_free(opts); + return 0; + } + break; + case 'i': + if (pv_getnum_check(optarg, 1)) { + fprintf(stderr, "%s: -%c: %s\n", argv[0], + c, _("numeric argument expected")); + opts_free(opts); + return 0; + } + break; + default: + break; + } + + /* + * Parse each command line option. + */ + switch (c) { + case 'h': + display_help(); + opts->do_nothing = 1; + return opts; + break; + case 'V': + display_version(); + opts->do_nothing = 1; + return opts; + break; + case 'p': + opts->progress = 1; + numopts++; + break; + case 't': + opts->timer = 1; + numopts++; + break; + case 'e': + opts->eta = 1; + numopts++; + break; + case 'r': + opts->rate = 1; + numopts++; + break; + case 'a': + opts->average_rate = 1; + numopts++; + break; + case 'b': + opts->bytes = 1; + numopts++; + break; + case 'f': + opts->force = 1; + break; + case 'n': + opts->numeric = 1; + numopts++; + break; + case 'q': + opts->no_op = 1; + numopts++; + break; + case 'c': + opts->cursor = 1; + break; + case 'W': + opts->wait = 1; + break; + case 's': + opts->size = pv_getnum_ll(optarg); + break; + case 'l': + opts->linemode = 1; + break; + case 'i': + opts->interval = pv_getnum_d(optarg); + break; + case 'w': + opts->width = pv_getnum_i(optarg); + break; + case 'H': + opts->height = pv_getnum_i(optarg); + break; + case 'N': + opts->name = optarg; + break; + case 'L': + opts->rate_limit = pv_getnum_ll(optarg); + break; + case 'B': + opts->buffer_size = pv_getnum_ll(optarg); + break; + case 'R': + opts->remote = pv_getnum_i(optarg); + break; + default: +#ifdef HAVE_GETOPT_LONG + fprintf(stderr, /* RATS: ignore (OK) */ + _("Try `%s --help' for more information."), + argv[0]); +#else + fprintf(stderr, /* RATS: ignore (OK) */ + _("Try `%s -h' for more information."), + argv[0]); +#endif + fprintf(stderr, "\n"); + opts_free(opts); + return 0; + break; + } + + } while (c != -1); + + /* + * Default options: -pterb + */ + if (numopts == 0) { + opts->progress = 1; + opts->timer = 1; + opts->eta = 1; + opts->rate = 1; + opts->bytes = 1; + } + + /* + * Store remaining command-line arguments. + */ + while (optind < argc) { + opts->argv[opts->argc++] = argv[optind++]; + } + + opts->exit_status = 0; + + return opts; +} + +/* EOF */ |