Part of the processing environment of every process are the values passed to the process in the function main . These values can be from the command line or may be passed to a child process from the parent via an exec system call. These values are stored in a ragged character array referenced by a character pointer array that, by tradition, is called argv . The number of elements in the argv array is stored as an integer value, which (again by tradition) is referenced by the identifier argc . Program 2.5, which displays command line values, takes advantage of the fact that in newer ANSI standard versions of Linux, the last element of the argv array (i.e., argv[argc] ) is guaranteed to be a NULL pointer. However, in most programming situations, especially when backward compatibility is a concern, it is best to use the value in argc as a limit when stepping through argv . If we run the program as p2.5 and place some arbitrary values on the command line, we obtain the output shown in Figure 2.17.
Program 2.5 Displaying command line arguments.
File : p2.5.cxx /* Displaying the contents of argv[ ] (the command line) */ #include + using namespace std; int main(int argc, char *argv[ ]){ for ( ; *argv; ++argv ) cout << *argv << endl; 10 return 0; }
Figure 2.17 Output of Program 2.5.
linux$ p2.5 This is a test. p2.5 This is a test.
We can envision the system as storing these command-line values in argc and argv as shown in Figure 2.18.
Figure 2.18. Storage of command line values.
In this situation (where the system fills the argv array), argc will always be greater than 0, and the first value referenced by argv will be the name of the program that is executing. The system automatically terminates each string with a null character and places a 0 as the last address in the argv array.
In programs, it is a common practice to scan the command line to ascertain its contents (such as when looking for command-line options). At one time programmers wishing to check the contents of the command line for options had to write their own command-line parsing code. However, there is a general-purpose library function called getopt that will do this. [10] The getopt library function is somewhat analogous to the Swiss army knifeit can do many things, but to the uninitiated, upon first exposure, it appears unduly complex (Table 2.22).
[10] If you do shell programming, you should find that your system supports a shell version of this library function called getopt . The shell version uses the library function version to do its parsing.
Table 2.22. Summary of the getopt Library Function.
Include File(s) |
Manual Section |
3 |
||
Summary |
int getopt( int argc, char * const argv[], char *optstring ); extern char *optarg; extern int optind, opterr, optopt; |
|||
Return |
Success |
Failure |
Sets errno |
|
Next option letter |
-1 or ? |
The getopt function requires three arguments. The first is an integer value argc (the number of elements in the second argument). The second argument is a pointer to a pointer to an array of characters strings. Usually this is the array of character strings referenced by argv . The third argument is a pointer to a string of valid option letters (characters) that getopt should recognize. As noted, in most settings the values for argc and argv are the same as those for main 's first and second arguments. However, nothing prevents users from generating these two arguments to getopt on their own.
The format of optstring 's content bears further explanation. If an option letter expects a following argument, the option letter in optstring is followed by a colon . For example, if the option letter s (which, say, stands for size ) is to be followed by an integer size value, the corresponding optstring entry would be s: . On the command line, the user would enter -s 200 to indicate a size of 200. For a command-line option to be processed properly by getopt , it must be preceded with a hyphen(-), while the argument(s) to the option should have no leading hyphen and may or may not be separated by whitespace from the option.
The getopt function returns, as an integer, one of three values:
The external integer optind is initialized by the system to 1 before the first call to getopt . It will contain the index of the next argument in argv that is not an option. By default getopt processes the argument array in a manner that all non-options are placed at the end of the list. A comparison of the value in optind to the value in argc can be used to determine if all items on the command line have been processed. The getopt function has a relative called getopt_long , which is similar in function to getopt but will process long (those with two leading dashes) command-line arguments. Check the manual page on this function for details. A program demonstrating the use of getopt is shown in Program 2.6.
Program 2.6 Using the library function getopt .
File : p2.6.cxx /* Command line using getopt */ #define _GNU_SOURCE + #include #include #include using namespace std; extern char *optarg; 10 extern int optind, opterr, optopt; int main(int argc, char *argv[ ]){ int c; char optstring[] = "abs:"; + opterr = 0; // turn off auto err mesg while ((c = getopt(argc, argv, optstring)) != -1) switch (c) { case 'a': cout << "Found option a "; 20 break; case 'b': cout << "Found option b "; break; case 's': + cout << "Found option s with an argument of: "; cout << atoi(optarg) << endl; // convert to integer break; case '?': cout << "Found an option that was not in optstring. "; 30 cout << "The offending character was " << char(optopt) << endl; } if (optind < argc){ cout << (argcoptind) << " arguments not processed. "; cout << "Left off at: " << argv[optind] << endl; + } return 0; }
A run of the program with some sample command-line options is shown in Figure 2.19.
Figure 2.19 Output of Program 2.6.
linux$ p2.6 -abc -s 34 -b joe -a student Found option a Found option b Found an option that was not in optstring. The offending character was c Found option s with an argument of: 34 Found option b Found option a 2 arguments not processed. Left off at: joe
As the output shows, getopt can process options in groups (e.g., -abc ) or as singletons (e.g., -b ), and is not concerned with the alphabetic order of options. When processing stops, optind can be checked to determine if any command-line options were not part of the specified options.
Programs and Processes
Processing Environment
Using Processes
Primitive Communications
Pipes
Message Queues
Semaphores
Shared Memory
Remote Procedure Calls
Sockets
Threads
Appendix A. Using Linux Manual Pages
Appendix B. UNIX Error Messages
Appendix C. RPC Syntax Diagrams
Appendix D. Profiling Programs