getopt.3: Further clarification of optstring

Explain that `optstring` cannot contain a semi-colon (`;`)
character.
[mtk: verified with a small test program; see also posix/getopt.c
in the glibc sources:

    if (temp == NULL || c == ':' || c == ';')
      {
        if (print_errors)
          fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
        d->optopt = c;
        return '?';
      }
]

Also explain that `optstring` can include `+` as an option
character, possibly in addition to that character being used as
the first character in `optstring` to denote `POSIXLY_CORRECT`
behaviour.
[mtk: verified with a small test program.]

Test program below. Example runs:

$ ./a.out -+
opt = 43 (+); optind = 2
Got plus
$ ./a.out -';'
./a.out: invalid option -- ';'
opt = 63 (?); optind = 2; optopt = 59 (;)
Unrecognized option (-;)
Usage: ./a.out [-p arg] [-x]

Signed-off-by: James O. D. Hunt <jamesodhunt@gmail.com>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>

8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---
#include <ctype.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define printable(ch) (isprint((unsigned char) ch) ? ch : '#')

static void             /* Print "usage" message and exit */
usageError(char *progName, char *msg, int opt)
{
    if (msg != NULL && opt != 0)
        fprintf(stderr, "%s (-%c)\n", msg, printable(opt));
    fprintf(stderr, "Usage: %s [-p arg] [-x]\n", progName);
    exit(EXIT_FAILURE);
}

int
main(int argc, char *argv[])
{
    int opt, xfnd;
    char *pstr;

    xfnd = 0;
    pstr = NULL;

    while ((opt = getopt(argc, argv, "p:x+;")) != -1) {
        printf("opt =%3d (%c); optind = %d", opt, printable(opt), optind);
        if (opt == '?' || opt == ':')
            printf("; optopt =%3d (%c)", optopt, printable(optopt));
        printf("\n");

        switch (opt) {
        case 'p': pstr = optarg;                break;
        case 'x': xfnd++;                       break;
        case ';': printf("Got semicolon\n");    break;
        case '+': printf("Got plus\n"); break;
        case ':': usageError(argv[0], "Missing argument", optopt);
        case '?': usageError(argv[0], "Unrecognized option", optopt);
        default:
                  printf("Unexpected case in switch()\n");
                  exit(EXIT_FAILURE);
        }
    }

    if (xfnd != 0)
        printf("-x was specified (count=%d)\n", xfnd);
    if (pstr != NULL)
        printf("-p was specified with the value \"%s\"\n", pstr);
    if (optind < argc)
        printf("First nonoption argument is \"%s\" at argv[%d]\n",
                argv[optind], optind);
    exit(EXIT_SUCCESS);
}
This commit is contained in:
James O. D. Hunt 2021-08-08 10:41:20 +02:00 committed by Michael Kerrisk
parent 71a62d6c3c
commit 87ce949275
1 changed files with 9 additions and 1 deletions

View File

@ -130,7 +130,7 @@ A legitimate option character is any visible one byte
.BR ascii (7) .BR ascii (7)
character (for which character (for which
.BR isgraph (3) .BR isgraph (3)
would return nonzero) that is not \(aq\-\(aq or \(aq:\(aq. would return nonzero) that is not \(aq\-\(aq, \(aq:\(aq or \(aq;\(aq.
If such a If such a
character is followed by a colon, the option requires an argument, so character is followed by a colon, the option requires an argument, so
.BR getopt () .BR getopt ()
@ -166,6 +166,14 @@ If the first character of
.B POSIXLY_CORRECT .B POSIXLY_CORRECT
is set, then option processing stops as soon as a nonoption argument is is set, then option processing stops as soon as a nonoption argument is
encountered. encountered.
If \(aq+\(aq is not the first character of
.IR optstring ,
it is treated as a normal option.
If
.B POSIXLY_CORRECT
behaviour is required in this case
.I optstring
will contain two \(aq+\(aq symbols.
If the first character of \fIoptstring\fP is \(aq\-\(aq, then If the first character of \fIoptstring\fP is \(aq\-\(aq, then
each nonoption \fIargv\fP-element is handled as if it were the argument of each nonoption \fIargv\fP-element is handled as if it were the argument of
an option with character code 1. (This is used by programs that were an option with character code 1. (This is used by programs that were