#define GETOPT_EXIT_CODE 1
#define PARAMETER_EXIT_CODE 2
#define XALLOC_EXIT_CODE 3
+#define CLOSE_EXIT_CODE XALLOC_EXIT_CODE
#define TEST_EXIT_CODE 4
#include <stdio.h>
#include "closestream.h"
#include "nls.h"
+#include "strutils.h"
#include "xalloc.h"
/* NON_OPT is the code that is returned getopt(3) when a non-option is
enum { REALLOC_INCREMENT = 8 };
/* Allow changing which getopt is in use with function pointer. */
-int (*getopt_long_fp) (int argc, char *const *argv, const char *optstr,
- const struct option * longopts, int *longindex);
+static int (*getopt_long_fp) (int argc, char *const *argv, const char *optstr,
+ const struct option * longopts, int *longindex);
/*
* This function 'normalizes' a single argument: it puts single quotes
{
if (message)
warnx("%s", message);
- fprintf(stderr, _("Try `%s --help' for more information.\n"),
- program_invocation_short_name);
- exit(PARAMETER_EXIT_CODE);
+ errtryhelp(PARAMETER_EXIT_CODE);
}
static void add_longopt(struct getopt_control *ctl, const char *name, int has_arg)
{
static int flag;
+ int nr = ctl->long_options_nr;
if (ctl->long_options_nr == ctl->long_options_length) {
ctl->long_options_length += REALLOC_INCREMENT;
- ctl->long_options = xrealloc(ctl->long_options,
- sizeof(struct option) *
- ctl->long_options_length);
+ ctl->long_options = xreallocarray(ctl->long_options,
+ ctl->long_options_length,
+ sizeof(struct option));
}
if (name) {
/* Not for init! */
- ctl->long_options[ctl->long_options_nr].has_arg = has_arg;
- ctl->long_options[ctl->long_options_nr].flag = &flag;
- ctl->long_options[ctl->long_options_nr].val = ctl->long_options_nr;
- ctl->long_options[ctl->long_options_nr].name = xstrdup(name);
+ ctl->long_options[nr].has_arg = has_arg;
+ ctl->long_options[nr].flag = &flag;
+ ctl->long_options[nr].val = ctl->long_options_nr;
+ ctl->long_options[nr].name = xstrdup(name);
+ } else {
+ /* lets use add_longopt(ct, NULL, 0) to terminate the array */
+ ctl->long_options[nr].name = NULL;
+ ctl->long_options[nr].has_arg = 0;
+ ctl->long_options[nr].flag = NULL;
+ ctl->long_options[nr].val = 0;
}
}
+static void add_short_options(struct getopt_control *ctl, char *options)
+{
+ free(ctl->optstr);
+ if (*options != '+' && getenv("POSIXLY_CORRECT"))
+ ctl->optstr = strconcat("+", options);
+ else
+ ctl->optstr = xstrdup(options);
+ if (!ctl->optstr)
+ err_oom();
+}
+
+
/*
* Register several long options. options is a string of long options,
* separated by commas or whitespace. This nukes options!
tokptr = strtok(NULL, ", \t\n");
}
add_longopt(ctl, NULL, 0); /* ensure long_options[] is not full */
- ctl->long_options[ctl->long_options_nr].name = NULL;
- ctl->long_options[ctl->long_options_nr].has_arg = 0;
- ctl->long_options[ctl->long_options_nr].flag = NULL;
- ctl->long_options[ctl->long_options_nr].val = 0;
}
static shell_t shell_type(const char *new_shell)
parse_error(_("unknown shell after -s or --shell argument"));
}
-static void __attribute__ ((__noreturn__)) print_help(void)
+static void __attribute__((__noreturn__)) usage(void)
{
- fputs(USAGE_HEADER, stderr);
- fprintf(stderr, _(
+ fputs(USAGE_HEADER, stdout);
+ printf(_(
" %1$s <optstring> <parameters>\n"
" %1$s [options] [--] <optstring> <parameters>\n"
" %1$s [options] -o|--options <optstring> [options] [--] <parameters>\n"),
program_invocation_short_name);
- fputs(USAGE_SEPARATOR, stderr);
- fputs(_("Parse command options.\n"), stderr);
-
- fputs(USAGE_OPTIONS, stderr);
- fputs(_(" -a, --alternative allow long options starting with single -\n"), stderr);
- fputs(_(" -l, --longoptions <longopts> the long options to be recognized\n"), stderr);
- fputs(_(" -n, --name <progname> the name under which errors are reported\n"), stderr);
- fputs(_(" -o, --options <optstring> the short options to be recognized\n"), stderr);
- fputs(_(" -q, --quiet disable error reporting by getopt(3)\n"), stderr);
- fputs(_(" -Q, --quiet-output no normal output\n"), stderr);
- fputs(_(" -s, --shell <shell> set quoting conventions to those of <shell>\n"), stderr);
- fputs(_(" -T, --test test for getopt(1) version\n"), stderr);
- fputs(_(" -u, --unquoted do not quote the output\n"), stderr);
- fputs(USAGE_SEPARATOR, stderr);
- fputs(USAGE_HELP, stderr);
- fputs(USAGE_VERSION, stderr);
- fprintf(stderr, USAGE_MAN_TAIL("getopt(1)"));
- exit(PARAMETER_EXIT_CODE);
+ fputs(USAGE_SEPARATOR, stdout);
+ fputs(_("Parse command options.\n"), stdout);
+
+ fputs(USAGE_OPTIONS, stdout);
+ fputs(_(" -a, --alternative allow long options starting with single -\n"), stdout);
+ fputs(_(" -l, --longoptions <longopts> the long options to be recognized\n"), stdout);
+ fputs(_(" -n, --name <progname> the name under which errors are reported\n"), stdout);
+ fputs(_(" -o, --options <optstring> the short options to be recognized\n"), stdout);
+ fputs(_(" -q, --quiet disable error reporting by getopt(3)\n"), stdout);
+ fputs(_(" -Q, --quiet-output no normal output\n"), stdout);
+ fputs(_(" -s, --shell <shell> set quoting conventions to those of <shell>\n"), stdout);
+ fputs(_(" -T, --test test for getopt(1) version\n"), stdout);
+ fputs(_(" -u, --unquoted do not quote the output\n"), stdout);
+ fputs(USAGE_SEPARATOR, stdout);
+ fprintf(stdout, USAGE_HELP_OPTIONS(31));
+ fprintf(stdout, USAGE_MAN_TAIL("getopt(1)"));
+ exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
if (getenv("GETOPT_COMPATIBLE"))
ctl.compatible = 1;
*/
printf(" --\n");
return EXIT_SUCCESS;
- } else
- parse_error(_("missing optstring argument"));
+ }
+ parse_error(_("missing optstring argument"));
}
add_longopt(&ctl, NULL, 0); /* init */
case 'a':
getopt_long_fp = getopt_long_only;
break;
- case 'h':
- print_help();
case 'o':
- free(ctl.optstr);
- ctl.optstr = xstrdup(optarg);
+ add_short_options(&ctl, optarg);
break;
case 'l':
add_long_options(&ctl, optarg);
case 'u':
ctl.quote = 0;
break;
+
case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
+ print_version(EXIT_SUCCESS);
case '?':
case ':':
parse_error(NULL);
+ case 'h':
+ usage();
default:
parse_error(_("internal error, contact the author."));
}
if (optind >= argc)
parse_error(_("missing optstring argument"));
else {
- ctl.optstr = xstrdup(argv[optind]);
+ add_short_options(&ctl, argv[optind]);
optind++;
}
}