The getopt(3) Function

What helps to make UNIX commands consistent in their syntax is that most commands use the library function getopt(3). Its synopsis is as follows:

#include <unistd.h>

extern char *optarg;
extern int optind;    /* initialized to 1 */
extern int optopt;
extern int opterr;    /* initialized to 1 */
extern int optreset;  /* extension to IEEE Std1003.2 "POSIX.2" */

int getopt(int argc, char * const *argv, const char *optstring);

extern void getoptreset(void);            /* SGI IRIX 6.5 only */

The getopt(3) function returns the option letter that is parsed. Alternatively, -1 is returned when the end of the options has been reached. The value ? is returned when an unrecognized option character has been encountered. If the argument optstring begins with a : character, then : is returned when an option expecting an argument does not have one given.

The getopt(3) External Values

Before you can use getopt(3), you need to be aware of how the external values are used by it. The two most important of these variables are the optarg and optind variables.

The optarg External Variable

The optarg external pointer variable is set to point at the argument supplied for the option being processed. However, this is only done for those options that take arguments (this will be expanded upon later). If getopt(3) were processing the option -fproject.tar or -f project.tar, then the variable optarg would point to the C string containing project.tar when getopt(3) is returned.

The optind External Variable

The external variable optind is initially set to the value 1. It is used by getopt(3) to point to the next argv[] value to be processed. This initial value causes getopt(3) to start processing options in argv[1]. When the end of the options is reached on the command line, the value of optind indicates where on the command line the first argument is located. For example, if the following command were to be processed by getopt(3)

$ rm -f core
							

then the optind value after all options are processed would be 2. This indicates that argv[2] has the first command-line argument following the options that were just processed.

The opterr External Variable

The external value opterr is initialized to the value of 1 (indicating true) and is used as input to the getopt(3) function. When it is true and an unrecognized option character is encountered, getopt(3) prints an error message to stderr indicating the unrecognized option. This behavior is suppressed when opterr is set to 0 (false). This is usually necessary when your program will be doing the error reporting itself or when the error message must go somewhere other than stderr.

The optreset External Variable

The FreeBSD platform exposes the external variable optreset. This is an extension to the IEEE Std1003.2 POSIX.2 standard and is not supported by other UNIX platforms. Setting this variable to 1 allows a new scan of options to be processed. This is normally accompanied by resetting the variable optind to 1.

To cause getopt(3) to rescan the command line a second time, the following procedure is used under FreeBSD:

optreset = 1;          /* Restart scan in getopt(3) */
optind = 1;            /* Restart scan with argv[1] */

This pair of assignments readies getopt(3) to start over. SGI's IRIX 6.5, for example, provides a getoptreset(3) function instead:

optind = 1;            /* Restart scan with argv[1] */
getoptreset();         /* Reset getopt(3) to start over */

Although the IRIX 6.5 documentation states that getoptreset(3) "can be used to reset all the internal state of getopt so that it may be used again on a different set of arguments," it might be wise to set optind=1 prior to making the call.

Note

The UNIX systems UnixWare 7, HPUX-11, Solaris 8, and AIX 4.3 do not document a formal way to reset the scanning of a command line.


The getopt(3) Function Call

The getopt(3) function returns an integer value that fits into one of the following categories:

  • The option character just parsed.

  • The character ?, indicating that an unrecognized option character was encountered.

  • The character :, indicating that an option is missing its argument (this is supported only when the argument optstring begins with a colon character).

  • The value -1, indicating that no more options exist (see the Note about EOF).

Note

Prior to the IEEE Std1003.2-1992 (POSIX.2) standard, the macro EOF was documented as the return value from getopt(3) when no more options remain to be processed. Now the standard documents that the value -1 is returned, and the use of the macro EOF in this context is discouraged.


The first argument argc for getopt(3) states how many argument values we have in the second array argv[]. This second argument is an array of C string pointers that point to each command-line argument. The values argc and argv[] are normally taken directly from the main() function interface.

The last argument to getopt(3) is the C string that drives the processing. It tells getopt(3) which options are supported and which options take arguments. This single string determines the whole personality of the command line.

Defining the optstring Argument

To support a few options such as the tar(1) example earlier, the optstring argument would be defined as follows:

int main(int argc,char **argv) {
    static char optstring[] = "cvf:";

Note how a colon (:) character follows the f character in the string optstring. The colon indicates that the option -f requires an argument. Option order is not significant in the optstring. The following would be equally acceptable:

int main(int argc,char **argv) {
    static char optstring[] = "vf:c";

Whenever getopt(3) processes an option, it searches the optstring argument. If the option character is not present in optstring, then it is not a supported option character, and it is treated as an error (a ? is returned). When the option character is found within optstring, the getopt(3) function checks the next immediate character in the optstring. If it finds a colon, then it knows that it must extract an argument to go with this option.

optstring can be begun with a colon character, as shown:

int main(int argc,char **argv) {
    static char optstring[] = ":cvf:";

When the optstring is specified with a leading colon, getopt(3) will return a : character when a valid option was parsed but no argument was found following it. This allows your program to assume some other default for the option argument.

Defining an Option-Processing Loop

Listing 9.1 shows a typical option-processing loop using getopt(3). The options supported in this program are the -c, -v, and -f options that were demonstrated by the earlier example using tar(1).

Code Listing 9.1. getopt.c—A Typical Option-Processing Loop Using getopt(3)
1:   /* getopt.c */
2:  
3:   #include <stdio.h>
4:   #include <unistd.h>
5:  
6:   int
7:   main(int argc,char **argv) {
8:       int rc;
9:       int optch;
10:      static char optstring[] = "cvf:";
11: 
12:      while ( (optch = getopt(argc,argv,optstring)) != -1 )
13:          switch ( optch ) {
14:          case 'c':
15:              puts("-c processed.");
16:              break;
17:          case 'v':
18:              puts("-v processed.");
19:              break;
20:          case 'f':
21:              printf("-f '%s'processed.
",optarg);
22:              break;
23:          default :   /* '?'*/
24:              rc = 1; /* Usage error has occurred */
25:          }
26: 
27:      for ( ; optind < argc; ++optind )
28:          printf("argv[%d] = '%s'
",optind,argv[optind]);
29:
30:      return rc;
31:  }
						

When the program is compiled and run, the output should appear as follows:

$ make getopt
cc -c -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -Wall getopt.c
cc getopt.o -o getopt
$ ./getopt -cvf project.tar project_dir
-c processed.
-v processed.
-f 'project.tar'processed.
argv[3] = 'project_dir'
$

The session output shows how the various case statements in the program were exercised by the options -c, -v, and -f. Notice the use of the external variable optarg for the -f option case (lines 20–22). After all the options were processed, the for loop in lines 27–28 reported the remaining command-line arguments. This was shown to be the single argument project_dir.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.138.14