From 87ce949275b6d4ebafc62684e4c4e5f073c9456d Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Sun, 8 Aug 2021 10:41:20 +0200 Subject: [PATCH] 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 Signed-off-by: Alejandro Colomar Signed-off-by: Michael Kerrisk 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x--- #include #include #include #include #include #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); } --- man3/getopt.3 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/man3/getopt.3 b/man3/getopt.3 index ce4c28088..315224c64 100644 --- a/man3/getopt.3 +++ b/man3/getopt.3 @@ -130,7 +130,7 @@ A legitimate option character is any visible one byte .BR ascii (7) character (for which .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 character is followed by a colon, the option requires an argument, so .BR getopt () @@ -166,6 +166,14 @@ If the first character of .B POSIXLY_CORRECT is set, then option processing stops as soon as a nonoption argument is 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 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