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:
christos 1996-06-04 21:00:09 +00:00
parent ad8b41fa2a
commit 0bc88b2434

View File

@ -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;
}
/*