fix getopt handling of ':' modifier for multibyte option characters
authorRich Felker <dalias@aerifal.cx>
Thu, 4 Dec 2014 15:23:33 +0000 (10:23 -0500)
committerRich Felker <dalias@aerifal.cx>
Thu, 4 Dec 2014 15:23:33 +0000 (10:23 -0500)
the previous hard-coded offsets of +1 and +2 contained a hidden
assumption that the option character matched was single-byte, despite
this implementation of getopt attempting to support multibyte option
characters. this patch reworks the matching logic to leave the final
index pointing just past the matched character so that fixed offsets
can be used to check for ':'.

src/misc/getopt.c

index a698c8d48edc5ddac2e1e41cf68eadfec45566d2..52aa7a3a6a664e74869eea34d4939d5f3deefa43 100644 (file)
@@ -58,7 +58,12 @@ int getopt(int argc, char * const argv[], const char *optstring)
        if (optstring[0] == '-')
                optstring++;
 
-       for (i=0; (l = mbtowc(&d, optstring+i, MB_LEN_MAX)) && d!=c; i+=l>0?l:1);
+       i = 0;
+       d = 0;
+       do {
+               l = mbtowc(&d, optstring+i, MB_LEN_MAX);
+               if (l>0) i+=l; else i++;
+       } while (l && d != c);
 
        if (d != c) {
                if (optstring[0] != ':' && opterr) {
@@ -69,8 +74,8 @@ int getopt(int argc, char * const argv[], const char *optstring)
                }
                return '?';
        }
-       if (optstring[i+1] == ':') {
-               if (optstring[i+2] == ':') optarg = 0;
+       if (optstring[i] == ':') {
+               if (optstring[i+1] == ':') optarg = 0;
                else if (optind >= argc) {
                        if (optstring[0] == ':') return ':';
                        if (opterr) {
@@ -81,7 +86,7 @@ int getopt(int argc, char * const argv[], const char *optstring)
                        }
                        return '?';
                }
-               if (optstring[i+2] != ':' || optpos) {
+               if (optstring[i+1] != ':' || optpos) {
                        optarg = argv[optind++] + optpos;
                        optpos = 0;
                }