#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 <unistd.h>
#include <ctype.h>
#include <getopt.h>
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h> /* BSD */
+#endif
#include "closestream.h"
#include "nls.h"
struct getopt_control {
shell_t shell; /* the shell we generate output for */
char *optstr; /* getopt(3) optstring */
+ char *name;
struct option *long_options; /* long options */
int long_options_length; /* length of options array */
int long_options_nr; /* number of used elements in array */
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
* optstr must contain the short options, and longopts the long options.
* Other settings are found in global variables.
*/
-static int generate_output(const struct getopt_control *ctl, char *argv[], int argc)
+static int generate_output(struct getopt_control *ctl, char *argv[], int argc)
{
int exit_code = EXIT_SUCCESS; /* Assume everything will be OK */
int opt;
optind = 0;
while ((opt =
- (getopt_long_fp(argc, argv, ctl->optstr, ctl->long_options, &longindex)))
- != EOF)
+ (getopt_long_fp
+ (argc, argv, ctl->optstr,
+ (const struct option *)ctl->long_options, &longindex)))
+ != EOF) {
if (opt == '?' || opt == ':')
exit_code = GETOPT_EXIT_CODE;
else if (!ctl->quiet_output) {
print_normalized(ctl, optarg ? optarg : "");
}
}
-
+ }
if (!ctl->quiet_output) {
printf(" --");
while (optind < argc)
print_normalized(ctl, argv[optind++]);
printf("\n");
}
+ for (longindex = 0; longindex < ctl->long_options_nr; longindex++)
+ free((char *)ctl->long_options[longindex].name);
+ free(ctl->long_options);
+ free(ctl->optstr);
+ free(ctl->name);
return exit_code;
}
{
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;
}
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;
}
}
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_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);
+ printf(USAGE_HELP_OPTIONS(31));
+ printf(USAGE_MAN_TAIL("getopt(1)"));
+ exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
.shell = BASH,
.quote = 1
};
- char *name = NULL;
int opt;
/* Stop scanning as soon as a non-option argument is found! */
textdomain(PACKAGE);
atexit(close_stdout);
- add_longopt(&ctl, NULL, 0); /* init */
- getopt_long_fp = getopt_long;
-
if (getenv("GETOPT_COMPATIBLE"))
ctl.compatible = 1;
parse_error(_("missing optstring argument"));
}
+ add_longopt(&ctl, NULL, 0); /* init */
+ getopt_long_fp = getopt_long;
+
if (argv[1][0] != '-' || ctl.compatible) {
ctl.quote = 0;
ctl.optstr = xmalloc(strlen(argv[1]) + 1);
getopt_long_fp = getopt_long_only;
break;
case 'h':
- print_help();
+ usage();
case 'o':
free(ctl.optstr);
ctl.optstr = xstrdup(optarg);
add_long_options(&ctl, optarg);
break;
case 'n':
- free(name);
- name = xstrdup(optarg);
+ free(ctl.name);
+ ctl.name = xstrdup(optarg);
break;
case 'q':
ctl.quiet_errors = 1;
ctl.shell = shell_type(optarg);
break;
case 'T':
+ free(ctl.long_options);
return TEST_EXIT_CODE;
case 'u':
ctl.quote = 0;
optind++;
}
}
- if (name)
- argv[optind - 1] = name;
- else
+
+ if (ctl.name) {
+ argv[optind - 1] = ctl.name;
+#if defined (HAVE_SETPROGNAME) && !defined (__linux__)
+ setprogname(ctl.name);
+#endif
+ } else
argv[optind - 1] = argv[0];
return generate_output(&ctl, argv + optind - 1, argc - optind + 1);