home *** CD-ROM | disk | FTP | other *** search
- From: John Quarterman (moderator) <ut-sally!std-unix>
-
- Topic: yet more on getopt (command line arguments)
-
- Two more messages, the first a followup to a previous posting, and
- the second public domain sources and man pages for getopt(3) and getopt(1).
- -mod
-
- ----------------------------------------------------------------------
-
- From: ihnp4!utzoo!henry
- Date: 3 Jul 85 18:34:41 CDT (Wed)
- To: ihnp4!ut-sally!std-unix
- Subject: Re: command line arguments
-
- > > A group of bundled options may end with an option that has an argument.
- >
- > This creates confusion in using C-Kermit when you want to send an image
- > file. For example:
- >
- > send -is filename < --- works fine
- > send -si filename < --- bombs the program
-
- The AT&T syntax standard (which getopt does not completely enforce)
- actually forbids both of these usages. Options with arguments are not
- allowed to be bundled, and they must be separated from their arguments
- by a space.
-
- > I would *much* prefer to bundle the flags, then
- > have those with arguments pick them up in the same order as the flags are
- > listed.
-
- The few existing commands that use such a convention, notably tar(1), are
- (in my experience) the worse for it. It's seriously error-prone. I think
- the AT&T people did the right thing.
-
- ------------------------------
-
- Date: Tue, 2 Jul 85 13:07:09 edt
- From: ihnp4!utcs!ian (Ian F. Darwin)
- To: ihnp4!ut-sally!jsq@tzec.UTEXAS.ARPA
- Subject: here is getopt
-
- Here is the source for getopt(3), the function that should be in
- everybody's C program, and getopt(1), a program that uses it to
- make shell programs comprehensible and consistent. There are man
- pages for both. Please send these on to the mod. group. Thanks.
-
- [ I have hacked the following shell script slightly so that
- it doesn't extract directly into system source directories,
- rather into the current directory. It should be assumed that
- this code comes with no warranty from me, Ian Darwin, or anyone
- else as to whether it accurately represents getopt as distributed
- with System V, or any command line standard, or that it works
- at all, or that it will cause no damage when extracted or used. -mod]
-
- #! /bin/sh
- #! To unbundle, sh this file
- echo x - "(/usr/man/man3/getopt.3)" >&2
- echo x - mkdir lib >&2
- mkdir lib >&2
- echo x - lib/getopt.3 >&2
- cat >lib/getopt.3 <<"//SYSIN DD SYSOUT=BD"
- .TH GETOPT 3 local
- .DA 25 March 1982
- .SH NAME
- getopt \- get option letter from argv
- .SH SYNOPSIS
- .ft B
- int getopt(argc, argv, optstring)
- .br
- int argc;
- .br
- char **argv;
- .br
- char *optstring;
- .sp
- extern char *optarg;
- .br
- extern int optind;
- .ft
- .SH DESCRIPTION
- .I Getopt
- returns the next option letter in
- .I argv
- that matches a letter in
- .IR optstring .
- .I Optstring
- is a string of recognized option letters;
- if a letter is followed by a colon, the option is expected to have
- an argument that may or may not be separated from it by white space.
- .I Optarg
- is set to point to the start of the option argument on return from
- .IR getopt .
- .PP
- .I Getopt
- places in
- .I optind
- the
- .I argv
- index of the next argument to be processed.
- Because
- .I optind
- is external, it is normally initialized to zero automatically
- before the first call to
- .IR getopt .
- .PP
- When all options have been processed (i.e., up to the first
- non-option argument),
- .I getopt
- returns
- .BR EOF .
- The special option
- .B \-\-
- may be used to delimit the end of the options;
- .B EOF
- will be returned, and
- .B \-\-
- will be skipped.
- .SH SEE ALSO
- getopt(1)
- .SH DIAGNOSTICS
- .I Getopt
- prints an error message on
- .I stderr
- and returns a question mark
- .RB ( ? )
- when it encounters an option letter not included in
- .IR optstring .
- .SH EXAMPLE
- The following code fragment shows how one might process the arguments
- for a command that can take the mutually exclusive options
- .B a
- and
- .BR b ,
- and the options
- .B f
- and
- .BR o ,
- both of which require arguments:
- .PP
- .RS
- .nf
- main(argc, argv)
- int argc;
- char **argv;
- {
- int c;
- extern int optind;
- extern char *optarg;
- \&.
- \&.
- \&.
- while ((c = getopt(argc, argv, "abf:o:")) != EOF)
- switch (c) {
- case 'a':
- if (bflg)
- errflg++;
- else
- aflg++;
- break;
- case 'b':
- if (aflg)
- errflg++;
- else
- bproc();
- break;
- case 'f':
- ifile = optarg;
- break;
- case 'o':
- ofile = optarg;
- break;
- case '?':
- default:
- errflg++;
- break;
- }
- if (errflg) {
- fprintf(stderr, "Usage: ...");
- exit(2);
- }
- for (; optind < argc; optind++) {
- \&.
- \&.
- \&.
- }
- \&.
- \&.
- \&.
- }
- .RE
- .PP
- A template similar to this can be found in
- .IR /usr/pub/template.c .
- .SH HISTORY
- Written by Henry Spencer, working from a Bell Labs manual page.
- Behavior believed identical to the Bell version.
- .SH BUGS
- It is not obvious how
- `\-'
- standing alone should be treated; this version treats it as
- a non-option argument, which is not always right.
- .PP
- Option arguments are allowed to begin with `\-';
- this is reasonable but reduces the amount of error checking possible.
- .PP
- .I Getopt
- is quite flexible but the obvious price must be paid: there is much
- it could do that it doesn't, like
- checking mutually exclusive options, checking type of
- option arguments, etc.
- //SYSIN DD SYSOUT=BD
- echo x - "(/usr/man/man1/getopt.1)" >&2
- echo x - mkdir bin >&2
- mkdir bin >&2
- echo x - bin/getopt.1 >&2
- cat >bin/getopt.1 <<"//SYSIN DD SYSOUT=BD"
- .TH GETOPT 1 local
- .DA 12 April 1984
- .SH NAME
- getopt \- parse command options
- .SH SYNOPSIS
- .B set \-\- \`getopt
- optstring
- .B $*\`
- .SH DESCRIPTION
- .I Getopt
- is used to break up options in command lines for easy parsing by
- shell procedures, and to check for legal options.
- .I Optstring
- is a string of recognized option letters (see
- .IR getopt (3));
- if a letter is followed by a colon, the option
- is expected to have an argument which may or may not be
- separated from it by white space.
- The special option
- .B \-\-
- is used to delimit the end of the options.
- .I Getopt
- will place
- .B \-\-
- in the arguments at the end of the options,
- or recognize it if used explicitly.
- The shell arguments
- (\fB$1 $2\fR ...) are reset so that each option is
- preceded by a
- .B \-
- and in its own shell argument;
- each option argument is also in its own shell argument.
- .SH EXAMPLE
- The following code fragment shows how one might process the arguments
- for a command that can take the options
- .B a
- and
- .BR b ,
- and the option
- .BR o ,
- which requires an argument.
- .PP
- .RS
- .nf
- set \-\- \`getopt abo: $*\`
- if test $? != 0
- then
- echo 'Usage: ...'
- exit 2
- fi
- for i
- do
- case "$i"
- in
- \-a|\-b)
- flag=$i; shift;;
- \-o)
- oarg=$2; shift; shift;;
- \-\-)
- shift; break;;
- esac
- done
- .fi
- .RE
- .PP
- This code will accept any of the following as equivalent:
- .PP
- .RS
- .nf
- cmd \-aoarg file file
- cmd \-a \-o arg file file
- cmd \-oarg -a file file
- cmd \-a \-oarg \-\- file file
- .RE
- .PP
- A program template similar to this example can be found in
- .IR /usr/pub/template.sh .
- .SH SEE ALSO
- sh(1), getopt(3)
- .SH DIAGNOSTICS
- .I Getopt
- prints an error message on the standard error output when it
- encounters an option letter not included in
- .IR optstring .
- .SH HISTORY
- Written by Henry Spencer, working from a Bell Labs manual page.
- Behavior believed identical to the Bell version.
- .SH BUGS
- Whatever
- .IR getopt (3)
- has.
- .PP
- Arguments containing white space or imbedded shell metacharacters
- generally will not survive intact; this looks easy to fix but isn't.
- .PP
- The error message for an invalid option is identified as coming
- from
- .I getopt
- rather than from the shell procedure containing the invocation
- of
- .IR getopt ;
- this again is hard to fix.
- .PP
- The precise best way to use the
- .I set
- command to set the arguments without disrupting the value(s) of
- shell options varies from one shell version to another.
- //SYSIN DD SYSOUT=BD
- echo x - "(/usr/src/lib/libc/gen/getopt.c)" >&2
- echo x - lib/getopt.c >&2
- cat >lib/getopt.c <<"//SYSIN DD SYSOUT=BD"
- /*
- * getopt - get option letter from argv
- */
-
- #include <stdio.h>
-
- char *optarg; /* Global argument pointer. */
- int optind = 0; /* Global argv index. */
-
- static char *scan = NULL; /* Private scan pointer. */
-
- extern char *index();
-
- int
- getopt(argc, argv, optstring)
- int argc;
- char *argv[];
- char *optstring;
- {
- register char c;
- register char *place;
-
- optarg = NULL;
-
- if (scan == NULL || *scan == '\0') {
- if (optind == 0)
- optind++;
-
- if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
- return(EOF);
- if (strcmp(argv[optind], "--")==0) {
- optind++;
- return(EOF);
- }
-
- scan = argv[optind]+1;
- optind++;
- }
-
- c = *scan++;
- place = index(optstring, c);
-
- if (place == NULL || c == ':') {
- fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
- return('?');
- }
-
- place++;
- if (*place == ':') {
- if (*scan != '\0') {
- optarg = scan;
- scan = NULL;
- } else if (optind < argc) {
- optarg = argv[optind];
- optind++;
- } else {
- fprintf(stderr, "%s: -%c argument missing\n", argv[0], c);
- return('?');
- }
- }
-
- return(c);
- }
- //SYSIN DD SYSOUT=BD
- echo x - "(/usr/src/bin/getopt.c)" >&2
- echo x - bin/getopt.c >&2
- cat >bin/getopt.c <<"//SYSIN DD SYSOUT=BD"
- #include <stdio.h>
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- extern int optind;
- extern char *optarg;
- int c;
- int status = 0;
-
- optind = 2; /* Past the program name and the option letters. */
- while ((c = getopt(argc, argv, argv[1])) != EOF)
- switch (c) {
- case '?':
- status = 1; /* getopt routine gave message */
- break;
- default:
- if (optarg != NULL)
- printf(" -%c %s", c, optarg);
- else
- printf(" -%c", c);
- break;
- }
- printf(" --");
- for (; optind < argc; optind++)
- printf(" %s", argv[optind]);
- printf("\n");
- exit(status);
- }
- //SYSIN DD SYSOUT=BD
- exit 0
-
- ----------------------------------------------------------------------
- --
-
- John Quarterman, jsq@ut-sally.ARPA, {ihnp4,seismo,ctvax}!ut-sally!jsq
-
- Volume-Number: Volume 1, Number 09
-
-