Some implementations of getopt() expect that argv[0] is always the
program name, and ignore that entry. ipfw2.c code instead skips this entry and starts with options at offset 0, relying on a more tolerant implementation of the library. This change fixes the issue by always passing a program name in the first entry to getopt. The motivation for this change is to remove a potential compatibility issue should we use a different getopt() implementation in the future. No functional changes. Submitted by: Marta Carbone (parts) MFC after: 4 weeks
This commit is contained in:
parent
477f656bb9
commit
c562063980
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=187713
@ -6090,7 +6090,8 @@ show_nat(int ac, char **av)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called with the arguments (excluding program name).
|
* Called with the arguments, including program name because getopt
|
||||||
|
* wants it to be present.
|
||||||
* Returns 0 if successful, 1 if empty command, errx() in case of errors.
|
* Returns 0 if successful, 1 if empty command, errx() in case of errors.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -6102,16 +6103,16 @@ ipfw_main(int oldac, char **oldav)
|
|||||||
int do_acct = 0; /* Show packet/byte count */
|
int do_acct = 0; /* Show packet/byte count */
|
||||||
|
|
||||||
#define WHITESP " \t\f\v\n\r"
|
#define WHITESP " \t\f\v\n\r"
|
||||||
if (oldac == 0)
|
if (oldac < 2)
|
||||||
return 1;
|
return 1; /* need at least one argument */
|
||||||
else if (oldac == 1) {
|
if (oldac == 2) {
|
||||||
/*
|
/*
|
||||||
* If we are called with a single string, try to split it into
|
* If we are called with a single string, try to split it into
|
||||||
* arguments for subsequent parsing.
|
* arguments for subsequent parsing.
|
||||||
* But first, remove spaces after a ',', by copying the string
|
* But first, remove spaces after a ',', by copying the string
|
||||||
* in-place.
|
* in-place.
|
||||||
*/
|
*/
|
||||||
char *arg = oldav[0]; /* The string... */
|
char *arg = oldav[1]; /* The string is the first arg. */
|
||||||
int l = strlen(arg);
|
int l = strlen(arg);
|
||||||
int copy = 0; /* 1 if we need to copy, 0 otherwise */
|
int copy = 0; /* 1 if we need to copy, 0 otherwise */
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -6142,13 +6143,17 @@ ipfw_main(int oldac, char **oldav)
|
|||||||
if (index(WHITESP, arg[i]) != NULL)
|
if (index(WHITESP, arg[i]) != NULL)
|
||||||
ac++;
|
ac++;
|
||||||
|
|
||||||
av = calloc(ac, sizeof(char *));
|
/*
|
||||||
|
* Allocate the argument list, including one entry for
|
||||||
|
* the program name because getopt expects it.
|
||||||
|
*/
|
||||||
|
av = calloc(ac + 1, sizeof(char *));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Second, copy arguments from cmd[] to av[]. For each one,
|
* Second, copy arguments from arg[] to av[]. For each one,
|
||||||
* j is the initial character, i is the one past the end.
|
* j is the initial character, i is the one past the end.
|
||||||
*/
|
*/
|
||||||
for (ac = 0, i = j = 0; i < l; i++)
|
for (ac = 1, i = j = 0; i < l; i++)
|
||||||
if (index(WHITESP, arg[i]) != NULL || i == l-1) {
|
if (index(WHITESP, arg[i]) != NULL || i == l-1) {
|
||||||
if (i == l-1)
|
if (i == l-1)
|
||||||
i++;
|
i++;
|
||||||
@ -6164,7 +6169,7 @@ ipfw_main(int oldac, char **oldav)
|
|||||||
int first, i, l;
|
int first, i, l;
|
||||||
|
|
||||||
av = calloc(oldac, sizeof(char *));
|
av = calloc(oldac, sizeof(char *));
|
||||||
for (first = i = ac = 0, l = 0; i < oldac; i++) {
|
for (first = i = ac = 1, l = 0; i < oldac; i++) {
|
||||||
char *arg = oldav[i];
|
char *arg = oldav[i];
|
||||||
int k = strlen(arg);
|
int k = strlen(arg);
|
||||||
|
|
||||||
@ -6183,6 +6188,7 @@ ipfw_main(int oldac, char **oldav)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
av[0] = strdup(oldav[0]); /* copy progname from the caller */
|
||||||
/* Set the force flag for non-interactive processes */
|
/* Set the force flag for non-interactive processes */
|
||||||
if (!do_force)
|
if (!do_force)
|
||||||
do_force = !isatty(STDIN_FILENO);
|
do_force = !isatty(STDIN_FILENO);
|
||||||
@ -6191,7 +6197,7 @@ ipfw_main(int oldac, char **oldav)
|
|||||||
save_ac = ac;
|
save_ac = ac;
|
||||||
save_av = av;
|
save_av = av;
|
||||||
|
|
||||||
optind = optreset = 0;
|
optind = optreset = 1; /* restart getopt() */
|
||||||
while ((ch = getopt(ac, av, "abcdefhinNqs:STtv")) != -1)
|
while ((ch = getopt(ac, av, "abcdefhinNqs:STtv")) != -1)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'a':
|
case 'a':
|
||||||
@ -6371,13 +6377,13 @@ ipfw_readfile(int ac, char *av[])
|
|||||||
{
|
{
|
||||||
#define MAX_ARGS 32
|
#define MAX_ARGS 32
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
char *cmd = NULL, *filename = av[ac-1];
|
const char *progname = av[0]; /* original program name */
|
||||||
|
const char *cmd = NULL; /* preprocessor name, if any */
|
||||||
|
const char *filename = av[ac-1]; /* file to read */
|
||||||
int c, lineno=0;
|
int c, lineno=0;
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
pid_t preproc = 0;
|
pid_t preproc = 0;
|
||||||
|
|
||||||
filename = av[ac-1];
|
|
||||||
|
|
||||||
while ((c = getopt(ac, av, "cfNnp:qS")) != -1) {
|
while ((c = getopt(ac, av, "cfNnp:qS")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
@ -6397,18 +6403,28 @@ ipfw_readfile(int ac, char *av[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
cmd = optarg;
|
|
||||||
/*
|
/*
|
||||||
* Skip previous args and delete last one, so we
|
* ipfw -p cmd [args] filename
|
||||||
* pass all but the last argument to the preprocessor
|
*
|
||||||
* via av[optind-1]
|
* We are done with getopt(). All arguments
|
||||||
|
* except the filename go to the preprocessor,
|
||||||
|
* so we need to do the following:
|
||||||
|
* - check that a filename is actually present;
|
||||||
|
* - advance av by optind-1 to skip arguments
|
||||||
|
* already processed;
|
||||||
|
* - decrease ac by optind, to remove the args
|
||||||
|
* already processed and the final filename;
|
||||||
|
* - set the last entry in av[] to NULL so
|
||||||
|
* popen() can detect the end of the array;
|
||||||
|
* - set optind=ac to let getopt() terminate.
|
||||||
*/
|
*/
|
||||||
av += optind - 1;
|
if (optind == ac)
|
||||||
ac -= optind - 1;
|
|
||||||
if (ac < 2)
|
|
||||||
errx(EX_USAGE, "no filename argument");
|
errx(EX_USAGE, "no filename argument");
|
||||||
|
cmd = optarg;
|
||||||
av[ac-1] = NULL;
|
av[ac-1] = NULL;
|
||||||
fprintf(stderr, "command is %s\n", av[0]);
|
av += optind - 1;
|
||||||
|
ac -= optind;
|
||||||
|
optind = ac;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
@ -6424,8 +6440,6 @@ ipfw_readfile(int ac, char *av[])
|
|||||||
" summary ``ipfw''");
|
" summary ``ipfw''");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd != NULL)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == NULL && ac != optind + 1) {
|
if (cmd == NULL && ac != optind + 1) {
|
||||||
@ -6474,13 +6488,14 @@ ipfw_readfile(int ac, char *av[])
|
|||||||
|
|
||||||
while (fgets(buf, BUFSIZ, f)) { /* read commands */
|
while (fgets(buf, BUFSIZ, f)) { /* read commands */
|
||||||
char linename[10];
|
char linename[10];
|
||||||
char *args[1];
|
char *args[2];
|
||||||
|
|
||||||
lineno++;
|
lineno++;
|
||||||
sprintf(linename, "Line %d", lineno);
|
sprintf(linename, "Line %d", lineno);
|
||||||
setprogname(linename); /* XXX */
|
setprogname(linename); /* XXX */
|
||||||
args[0] = buf;
|
args[0] = strdup(progname);
|
||||||
ipfw_main(1, args);
|
args[1] = buf;
|
||||||
|
ipfw_main(2, args);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (cmd != NULL) {
|
if (cmd != NULL) {
|
||||||
@ -6510,7 +6525,7 @@ main(int ac, char *av[])
|
|||||||
if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
|
if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
|
||||||
ipfw_readfile(ac, av);
|
ipfw_readfile(ac, av);
|
||||||
else {
|
else {
|
||||||
if (ipfw_main(ac-1, av+1))
|
if (ipfw_main(ac, av))
|
||||||
show_usage();
|
show_usage();
|
||||||
}
|
}
|
||||||
return EX_OK;
|
return EX_OK;
|
||||||
|
Loading…
Reference in New Issue
Block a user