getopts fixes:
1. OPTIND value was not computed correctly when the argument was part of the option string (i.e. for "l:" "-l 1" was working "-l1" was not). (PR/2505). 2. OPTARG was not being unset in case of errors [in the non POSIX error case]. 3. optvar could be set to random values. 4. Option string starting with a : was not treated specially as POSIX specifies (if the option string starts with a :, then there is no error printed when there are missing option arguments or illegal options, and OPTARG and optvar are being set specially). 5. Implemented getopts "opts" optvar [arg]. The optional argument case was not implemented. To do: - what does Posix say about resetting the getopts state? Bash does it by setting OPTIND=0; is that correct? Should we be doing the same thing? - should we be using getopt(3) for everything internal to the shell? Is that feasible because we might need to handle multiple invocations at once.
This commit is contained in:
parent
ad8b41fa2a
commit
0bc88b2434
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: options.c,v 1.14 1995/05/11 21:29:46 christos Exp $ */
|
||||
/* $NetBSD: options.c,v 1.15 1996/06/04 21:00:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@ -40,7 +40,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: options.c,v 1.14 1995/05/11 21:29:46 christos Exp $";
|
||||
static char rcsid[] = "$NetBSD: options.c,v 1.15 1996/06/04 21:00:09 christos Exp $";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -78,6 +78,7 @@ char *minusc; /* argument to -c option */
|
||||
STATIC void options __P((int));
|
||||
STATIC void minus_o __P((char *, int));
|
||||
STATIC void setoption __P((int, int));
|
||||
STATIC int getopts __P((char *, char *, char **, char ***, char **));
|
||||
|
||||
|
||||
/*
|
||||
@ -363,55 +364,102 @@ getoptscmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register char *p, *q;
|
||||
char c;
|
||||
char s[10];
|
||||
char **optbase;
|
||||
|
||||
if (argc < 3)
|
||||
error("Usage: getopts optstring var [arg]");
|
||||
else if (argc == 3)
|
||||
optbase = shellparam.p;
|
||||
else
|
||||
optbase = &argv[3];
|
||||
|
||||
if (argc != 3)
|
||||
error("Usage: getopts optstring var");
|
||||
if (shellparam.optnext == NULL) {
|
||||
shellparam.optnext = shellparam.p;
|
||||
shellparam.optnext = optbase;
|
||||
shellparam.optptr = NULL;
|
||||
}
|
||||
if ((p = shellparam.optptr) == NULL || *p == '\0') {
|
||||
p = *shellparam.optnext;
|
||||
|
||||
return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
|
||||
&shellparam.optptr);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
getopts(optstr, optvar, optfirst, optnext, optptr)
|
||||
char *optstr;
|
||||
char *optvar;
|
||||
char **optfirst;
|
||||
char ***optnext;
|
||||
char **optptr;
|
||||
{
|
||||
register char *p, *q;
|
||||
char c = '?';
|
||||
int done = 0;
|
||||
int ind = 0;
|
||||
char s[10];
|
||||
|
||||
if ((p = *optptr) == NULL || *p == '\0') {
|
||||
/* Current word is done, advance */
|
||||
p = **optnext;
|
||||
if (p == NULL || *p != '-' || *++p == '\0') {
|
||||
atend:
|
||||
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
|
||||
setvar("OPTIND", s, 0);
|
||||
shellparam.optnext = NULL;
|
||||
return 1;
|
||||
**optnext = NULL;
|
||||
ind = *optnext - optfirst + 1;
|
||||
done = 1;
|
||||
goto out;
|
||||
}
|
||||
shellparam.optnext++;
|
||||
(*optnext)++;
|
||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||
goto atend;
|
||||
}
|
||||
|
||||
c = *p++;
|
||||
for (q = argv[1] ; *q != c ; ) {
|
||||
for (q = optstr; *q != c; ) {
|
||||
if (*q == '\0') {
|
||||
out1fmt("Illegal option -%c\n", c);
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
setvar("OPTARG", s, 0);
|
||||
}
|
||||
else {
|
||||
out1fmt("Illegal option -%c\n", c);
|
||||
unsetvar("OPTARG");
|
||||
}
|
||||
c = '?';
|
||||
goto out;
|
||||
}
|
||||
if (*++q == ':')
|
||||
q++;
|
||||
}
|
||||
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0' && (p = *shellparam.optnext) == NULL) {
|
||||
out1fmt("No arg for -%c option\n", c);
|
||||
c = '?';
|
||||
if (*p == '\0' && (p = **optnext) == NULL) {
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
setvar("OPTARG", s, 0);
|
||||
c = ':';
|
||||
}
|
||||
else {
|
||||
out1fmt("No arg for -%c option\n", c);
|
||||
unsetvar("OPTARG");
|
||||
c = '?';
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
shellparam.optnext++;
|
||||
|
||||
if (p == **optnext)
|
||||
(*optnext)++;
|
||||
ind = *optnext - optfirst + 1;
|
||||
setvar("OPTARG", p, 0);
|
||||
p = NULL;
|
||||
}
|
||||
out:
|
||||
shellparam.optptr = p;
|
||||
*optptr = p;
|
||||
fmtstr(s, sizeof(s), "%d", ind);
|
||||
setvar("OPTIND", s, 0);
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
setvar(argv[2], s, 0);
|
||||
return 0;
|
||||
setvar(optvar, s, 0);
|
||||
return done;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user