getsubopt()

Parse suboptions from a string

Synopsis:

#include <stdlib.h>

int getsubopt( char** optionp,
               char* const* tokens,
               char** valuep );

Arguments:

optionp
The address of a pointer to the string of options that you want to parse. The function updates this pointer as it parses the options; see below.
tokens
A vector of possible tokens.
valuep
The address of a pointer that the function updates to point to the first character of a value that's associated with an option; see below.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The getsubopt() function parses suboptions in a flag argument that was initially parsed by getopt(). These suboptions are separated by commas and may consist of either a single token or a token-value pair separated by an equal sign. Since commas delimit suboptions in the option string, they aren't allowed to be part of the suboption or the value of a suboption. A command that uses this syntax is mount, which allows the user to specify mount parameters with the -o option as follows:

mount -o rw,hard,bg,wsize=1024 speed:/usr /usr

In this example there are four suboptions: rw, hard, bg, and wsize, the last of which has an associated value of 1024.

The getsubopt() function takes the address of a pointer to the option string, a vector of possible tokens, and the address of a value string pointer. It returns the index of the token that matched the suboption in the input string, or -1 if there was no match. If the option string at optionp contains only one suboption, getsubopt() updates optionp to point to the null character at the end of the string; otherwise, it isolates the suboption by replacing the comma separator with a null character, and updates optionp to point to the start of the next suboption. If the suboption has an associated value, getsubopt() updates valuep to point to the value's first character. Otherwise, it sets valuep to NULL.

The token vector is organized as a series of pointers to null strings. The end of the token vector is identified by a NULL pointer.

When getsubopt() returns, if valuep isn't NULL, the suboption processed included a value. The calling program may use this information to determine if the presence or lack of a value for this suboption is an error.

Additionally, when getsubopt() fails to match the suboption with the tokens in the tokens array, the calling program should decide if this is an error, or if the unrecognized option should be passed to another program.

Returns:

The getsubopt() function returns -1 when the token it's scanning isn't in the tokens vector. The variable addressed by valuep contains a pointer to the first character of the token that wasn't recognized rather than a pointer to a value for that token.

The variable addressed by optionp points to the next option to be parsed, or a null character if there are no more options.

Examples:

The following code fragment shows how to process options to the mount command using getsubopt().

When getsubopt() parses an option input string, it changes any commas to null characters. If the original optarg pointer were passed directly to getsubopt(), these modifications would cause pidin to see a truncated argument list. To avoid this problem, the following example uses strdup() to copy the string and then calls getsubopt() on the copy. Alternatively, you can restore the characters that were replaced with null bytes.

#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char *myopts[] = {
#define READONLY    0
               "ro",
#define READWRITE   1
               "rw",
#define WRITESIZE   2
               "wsize",
#define READSIZE    3
               "rsize",
               NULL};

int main(int argc, char **argv)
{
     int sc, c, errflag;
     char *options, *value;
     extern char *optarg;
     extern int optind;
     .
     .
     .
     while((c = getopt(argc, argv, "abf:o:")) != -1) {
          switch (c) {
          case 'a': /* process a option */
               break;
          case 'b': /* process b option */
               break;
          case 'f':
               ofile = optarg;
               break;
          case '?':
               errflag++;
               break;
          case 'o':
               if ((optarg = strdup(optarg)) == NULL)  {
                   error_no_memory();
                   errflag++;
                    break;
               }
               options = optarg;
               while (*options != '\0') {
                    switch(getsubopt(&options,myopts,&value)) {
                    case READONLY : /* process ro option */
                         break;
                    case READWRITE : /* process rw option */
                         break;

                    case WRITESIZE : /* process wsize option */
                         if (value == NULL) {
                              error_no_arg();
                              errflag++;
                         } else
                              write_size = atoi(value);
                         break;
                    case READSIZE : /* process rsize option */
                         if (value == NULL) {
                              error_no_arg();
                              errflag++;
                         } else
                              read_size = atoi(value);
                         break;
                    default :
                         /* process unknown token */
                         error_bad_token(value);
                         errflag++;
                         break;
                    }
               }
               free(optarg);
               break;
          }
     }
     if (errflag) {
          /* print usage instructions etc. */
     }     
     for (; optind < argc; optind++) {
          /* process remaining arguments */
     }
     ...
}

Classification:

POSIX 1003.1

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes

Caveats:

During parsing, commas in the option input string are changed to null characters.