diff --git a/lib/libc/stdlib/getopt.3 b/lib/libc/stdlib/getopt.3 index d08c06e05cdb..95ff6e6875c4 100644 --- a/lib/libc/stdlib/getopt.3 +++ b/lib/libc/stdlib/getopt.3 @@ -1,5 +1,5 @@ -.\" Copyright (c) 1988, 1991 Regents of the University of California. -.\" All rights reserved. +.\" Copyright (c) 1988, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -29,31 +29,31 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" from: @(#)getopt.3 6.16 (Berkeley) 4/19/91 -.\" $Id: getopt.3,v 1.6 1994/01/10 23:36:44 jtc Exp $ +.\" @(#)getopt.3 8.4 (Berkeley) 4/19/94 .\" -.Dd April 19, 1991 +.Dd April 19, 1994 .Dt GETOPT 3 .Os BSD 4.3 .Sh NAME .Nm getopt -.Nd get option letter from argv +.Nd get option character from command line argument list .Sh SYNOPSIS -.Fd #include +.Fd #include +.Vt extern char *optarg; +.Vt extern int optind; +.Vt extern int optopt; +.Vt extern int opterr; +.Vt extern int optreset; .Ft int .Fn getopt "int argc" "char * const *argv" "const char *optstring" -.Vt extern char *optarg; -.Vt extern int optind; -.Vt extern int opterr; -.Vt extern int optopt; .Sh DESCRIPTION The .Fn getopt -function gets -the next +function incrementally parses a command line argument list +.Fa argv +and returns the next .Em known -option character from -.Fa argv . +option character. An option character is .Em known if it has been specified in the string of accepted option characters, @@ -61,9 +61,18 @@ if it has been specified in the string of accepted option characters, .Pp The option string .Fa optstring -may contain the following characters; letters and -letters followed by a colon to indicate an option argument -is to follow. It does not matter to +may contain the following elements: individual characters, and +characters followed by a colon to indicate an option argument +is to follow. +For example, an option string +.Li "\&""x"" +recognizes an option +.Dq Fl x , +and an option string +.Li "\&""x:"" +recognizes an option and argument +.Dq Fl x Ar argument . +It does not matter to .Fn getopt if a following argument has leading white space. .Pp @@ -78,159 +87,121 @@ contains the index to the next argument for a subsequent call to .Fn getopt . +The variable +.Va optopt +saves the last +.Em known +option character returned by +.Fn getopt . .Pp The variable .Va opterr and .Va optind are both initialized to 1. +The +.Va optind +variable may be set to another value before a set of calls to +.Fn getopt +in order to skip over more or less argv entries. +.Pp In order to use .Fn getopt to evaluate multiple sets of arguments, or to evaluate a single set of arguments multiple times, +the variable +.Va optreset +must be set to 1 before the second and each additional set of calls to +.Fn getopt , +and the variable .Va optind -must be initialized to the number of argv entries to be skipped in each -evaluation. +must be reinitialized. .Pp The .Fn getopt function -returns \-1 -when the argument list is exhausted. -The interpretation of options in the argument list may be canceled +returns an +.Dv EOF +when the argument list is exhausted, or a non-recognized +option is encountered. +The interpretation of options in the argument list may be cancelled by the option .Ql -- (double dash) which causes .Fn getopt -to signal the end of argument processing and return \-1. +to signal the end of argument processing and return an +.Dv EOF . When all options have been processed (i.e., up to the first non-option argument), .Fn getopt -returns \-1. +returns +.Dv EOF . .Sh DIAGNOSTICS -If the +If the .Fn getopt -function encounters an option character that is not contained in -.Fa optstring , -it returns a question mark -.Pq ? -character. -If it detects a missing option argument, it returns a colon -.Pq \: -character if the first character of -.Fa optstring -is a colon, otherwise it returns a question mark. -In either case, a diagnostic message is written to -.Em stderr -unless the application has set +function encounters a character not found in the string +.Va optarg +or detects +a missing option argument it writes an error message and returns +.Ql ? +to the +.Em stderr . +Setting .Va opterr -to zero or the first character of -.Fa optstring -is a colon. -.Sh EXAMPLE -.\" The following example comes from section E.9.7 of the IEEE 1003.2-90 -.\" standard (POSIX.2). -The following code fragment shows how one might process the arguments for -a utility that can take the mutually exclusive options -.Em a -and -.Em b -and the options -.Em f -and -.Em o , -both of which require arguments: +to a zero will disable these error messages. +If +.Va optstring +has a leading +.Ql \&: +then a missing option argument causes a +.Ql \&: +to be returned in addition to suppressing any error messages. .Pp -.Bd -literal -compact -#include - -int -main (argc, argv) - int argc; - char *argv[]; -{ - int c, bflg, aflg, errflg = 0; - char *ifile, *ofile; - extern char *optarg; - extern int optind, optopt; - - . . . - - while ((c = getopt(argc, argv, ":abf:o:")) != -1) { - switch(ch) { - case 'a': - if (bflg) - errflg = 1; - else - aflg = 1; - break; - case 'b': - if (aflg) - errflg = 1; - else - bflg = 1; - break; - case 'f': - ifile = optarg; - break; - case 'o': - ofile = optarg; - break; - case ':': /* -f or -o without option-arg */ - fprintf (stderr, - "Option -%c requires an option-argument\\n", - optopt); - errflg = 1; - break; - case '?': - fprintf (stderr, - "Unrecognized option: -%c\\n", - optopt); - errflg = 1; - break; - } - } - - if (errflg) { - fprintf (stderr, "usage: . . .\\n"); - exit (2); - } - - argc -= optind; - argv += optind; - - . . . - -} -.Ed -.Sh STANDARDS +Option arguments are allowed to begin with +.Dq Li \- ; +this is reasonable but +reduces the amount of error checking possible. +.Sh EXTENSIONS The +.Va optreset +variable was added to make it possible to call the .Fn getopt -function conforms to -.St -p1003.2-92 . +function multiple times. +This is an extension to the +.St -p1003.2 +specification. +.Sh EXAMPLE +.Bd -literal -compact +extern char *optarg; +extern int optind; +int bflag, ch, fd; + +bflag = 0; +while ((ch = getopt(argc, argv, "bf:")) != EOF) + switch(ch) { + case 'b': + bflag = 1; + break; + case 'f': + if ((fd = open(optarg, O_RDONLY, 0)) < 0) { + (void)fprintf(stderr, + "myname: %s: %s\en", optarg, strerror(errno)); + exit(1); + } + break; + case '?': + default: + usage(); +} +argc -= optind; +argv += optind; +.Ed .Sh HISTORY The .Fn getopt function appeared .Bx 4.3 . .Sh BUGS -The -.Fn getopt -function was once specified to return -.Dv EOF -instead of \-1. -This was changed by -.St -p1003.2-92 -to decouple -.Fn getopt -from -.Pa . -.Pp -Option arguments are allowed to begin with -.Dq Li \- ; -this is reasonable but -reduces the amount of error checking possible. -.Pp A single dash .Dq Li - may be specified as an character in @@ -248,7 +219,8 @@ It is provided for backward compatibility .Em only . By default, a single dash causes .Fn getopt -to returns \-1. +to return +.Dv EOF . This is, we believe, compatible with System V. .Pp It is also possible to handle digits as option letters. @@ -260,12 +232,12 @@ as an option. This practice is wrong, and should not be used in any current development. It is provided for backward compatibility .Em only . -The following code fragment works fairly well. +The following code fragment works in most cases. .Bd -literal -offset indent int length; char *p; -while ((c = getopt(argc, argv, "0123456789")) != -1) +while ((c = getopt(argc, argv, "0123456789")) != EOF) switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': diff --git a/lib/libc/stdlib/getopt.c b/lib/libc/stdlib/getopt.c index 30a5f238087f..994d757533e0 100644 --- a/lib/libc/stdlib/getopt.c +++ b/lib/libc/stdlib/getopt.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,93 +32,86 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)getopt.c 4.13 (Berkeley) 2/23/91";*/ -static char *rcsid = "$Id: getopt.c,v 1.5 1993/10/12 21:52:45 jtc Exp $"; +static char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94"; #endif /* LIBC_SCCS and not lint */ #include #include #include -/* - * get option letter from argument vector - */ -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt; /* character checked for validity */ +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ char *optarg; /* argument associated with option */ -#define NOOPT (int)':' /* No option */ #define BADCH (int)'?' +#define BADARG (int)':' #define EMSG "" +/* + * getopt -- + * Parse argc/argv argument vector. + */ int getopt(nargc, nargv, ostr) int nargc; char * const *nargv; const char *ostr; { + extern char *__progname; static char *place = EMSG; /* option letter processing */ - register char *oli; /* option letter list index */ - char *p; + char *oli; /* option letter list index */ - if (!*place) { /* update scanning pointer */ + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; if (optind >= nargc || *(place = nargv[optind]) != '-') { place = EMSG; - return(-1); + return (EOF); } if (place[1] && *++place == '-') { /* found "--" */ ++optind; place = EMSG; - return(-1); + return (EOF); } - } - /* option letter okay? */ + } /* option letter okay? */ if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt))) { /* * if the user didn't specify '-' as an option, - * assume it means -1. + * assume it means EOF. */ if (optopt == (int)'-') - return(-1); + return (EOF); if (!*place) ++optind; - if (opterr && *ostr != ':') { - if (!(p = strrchr(*nargv, '/'))) - p = *nargv; - else - ++p; - (void)fprintf(stderr, "%s: illegal option -- %c\n", - p, optopt); - } - return(BADCH); + if (opterr && *ostr != ':') + (void)fprintf(stderr, + "%s: illegal option -- %c\n", __progname, optopt); + return (BADCH); } - if (*++oli != ':') { /* don't need argument */ optarg = NULL; if (!*place) ++optind; - } else { /* need an argument */ + } + else { /* need an argument */ if (*place) /* no white space */ optarg = place; else if (nargc <= ++optind) { /* no arg */ place = EMSG; - if (opterr && *ostr != ':') { - if (!(p = strrchr(*nargv, '/'))) - p = *nargv; - else - ++p; + if (*ostr == ':') + return (BADARG); + if (opterr) (void)fprintf(stderr, "%s: option requires an argument -- %c\n", - p, optopt); - } - return((*ostr == ':') ? NOOPT : BADCH); + __progname, optopt); + return (BADCH); } else /* white space */ optarg = nargv[optind]; place = EMSG; ++optind; } - return(optopt); /* dump back option letter */ + return (optopt); /* dump back option letter */ }