| .\" Copyright (C) 2007 Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" and Copyright (C) 2007 Justin Pryzby <pryzbyj@justinpryzby.com> |
| .\" |
| .\" %%%LICENSE_START(PERMISSIVE_MISC) |
| .\" Permission is hereby granted, free of charge, to any person obtaining |
| .\" a copy of this software and associated documentation files (the |
| .\" "Software"), to deal in the Software without restriction, including |
| .\" without limitation the rights to use, copy, modify, merge, publish, |
| .\" distribute, sublicense, and/or sell copies of the Software, and to |
| .\" permit persons to whom the Software is furnished to do so, subject to |
| .\" the following conditions: |
| .\" |
| .\" The above copyright notice and this permission notice shall be |
| .\" included in all copies or substantial portions of the Software. |
| .\" |
| .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| .\" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| .\" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| .\" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| .\" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| .\" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| .\" %%%LICENSE_END |
| .\" |
| .TH GETSUBOPT 3 2019-03-06 "GNU" "Linux Programmer's Manual" |
| .SH NAME |
| getsubopt \- parse suboption arguments from a string |
| .SH SYNOPSIS |
| .B #include <stdlib.h> |
| .PP |
| .BI "int getsubopt(char **"optionp ", char * const *" tokens \ |
| ", char **" valuep ); |
| .PP |
| .in -4n |
| Feature Test Macro Requirements for glibc (see |
| .BR feature_test_macros (7)): |
| .in |
| .PP |
| .BR getsubopt (): |
| .ad l |
| .RS 4 |
| .PD 0 |
| _XOPEN_SOURCE\ >= 500 |
| .\" || _XOPEN_SOURCE\ &&\ _XOPEN_SOURCE_EXTENDED |
| .br |
| || /* Since glibc 2.12: */ _POSIX_C_SOURCE\ >=\ 200809L |
| .PD |
| .RE |
| .ad |
| .SH DESCRIPTION |
| .BR getsubopt () |
| parses the list of comma-separated suboptions provided in |
| .IR optionp . |
| (Such a suboption list is typically produced when |
| .BR getopt (3) |
| is used to parse a command line; |
| see for example the \fI-o\fP option of |
| .BR mount (8).) |
| Each suboption may include an associated value, |
| which is separated from the suboption name by an equal sign. |
| The following is an example of the kind of string |
| that might be passed in |
| .IR optionp : |
| .PP |
| .in +4n |
| .EX |
| .B ro,name=xyz |
| .EE |
| .in |
| .PP |
| The |
| .I tokens |
| argument is a pointer to a NULL-terminated array of pointers to the tokens that |
| .BR getsubopt () |
| will look for in |
| .IR optionp . |
| The tokens should be distinct, null-terminated strings containing at |
| least one character, with no embedded equal signs or commas. |
| .PP |
| Each call to |
| .BR getsubopt () |
| returns information about the next unprocessed suboption in |
| .IR optionp . |
| The first equal sign in a suboption (if any) is interpreted as a |
| separator between the name and the value of that suboption. |
| The value extends to the next comma, |
| or (for the last suboption) to the end of the string. |
| If the name of the suboption matches a known name from |
| .IR tokens , |
| and a value string was found, |
| .BR getsubopt () |
| sets |
| .I *valuep |
| to the address of that string. |
| The first comma in |
| .I optionp |
| is overwritten with a null byte, so |
| .I *valuep |
| is precisely the "value string" for that suboption. |
| .PP |
| If the suboption is recognized, but no value string was found, |
| .I *valuep |
| is set to NULL. |
| .PP |
| When |
| .BR getsubopt () |
| returns, |
| .I optionp |
| points to the next suboption, |
| or to the null byte (\(aq\e0\(aq) at the end of the |
| string if the last suboption was just processed. |
| .SH RETURN VALUE |
| If the first suboption in |
| .I optionp |
| is recognized, |
| .BR getsubopt () |
| returns the index of the matching suboption element in |
| .IR tokens . |
| Otherwise, \-1 is returned and |
| .I *valuep |
| is the entire |
| .IB name [= value ] |
| string. |
| .PP |
| Since |
| .I *optionp |
| is changed, the first suboption before the call to |
| .BR getsubopt () |
| is not (necessarily) the same as the first suboption after |
| .BR getsubopt (). |
| .SH ATTRIBUTES |
| For an explanation of the terms used in this section, see |
| .BR attributes (7). |
| .TS |
| allbox; |
| lb lb lb |
| l l l. |
| Interface Attribute Value |
| T{ |
| .BR getsubopt () |
| T} Thread safety MT-Safe |
| .TE |
| .SH CONFORMING TO |
| POSIX.1-2001, POSIX.1-2008. |
| .SH NOTES |
| .PP |
| Since |
| .BR getsubopt () |
| overwrites any commas it finds in the string |
| .IR *optionp , |
| that string must be writable; it cannot be a string constant. |
| .SH EXAMPLE |
| The following program expects suboptions following a "\-o" option. |
| .PP |
| .EX |
| #define _XOPEN_SOURCE 500 |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <stdio.h> |
| |
| int |
| main(int argc, char **argv) |
| { |
| enum { |
| RO_OPT = 0, |
| RW_OPT, |
| NAME_OPT |
| }; |
| char *const token[] = { |
| [RO_OPT] = "ro", |
| [RW_OPT] = "rw", |
| [NAME_OPT] = "name", |
| NULL |
| }; |
| char *subopts; |
| char *value; |
| int opt; |
| |
| int readonly = 0; |
| int readwrite = 0; |
| char *name = NULL; |
| int errfnd = 0; |
| |
| while ((opt = getopt(argc, argv, "o:")) != \-1) { |
| switch (opt) { |
| case \(aqo\(aq: |
| subopts = optarg; |
| while (*subopts != \(aq\e0\(aq && !errfnd) { |
| |
| switch (getsubopt(&subopts, token, &value)) { |
| case RO_OPT: |
| readonly = 1; |
| break; |
| |
| case RW_OPT: |
| readwrite = 1; |
| break; |
| |
| case NAME_OPT: |
| if (value == NULL) { |
| fprintf(stderr, "Missing value for " |
| "suboption \(aq%s\(aq\en", token[NAME_OPT]); |
| errfnd = 1; |
| continue; |
| } |
| |
| name = value; |
| break; |
| |
| default: |
| fprintf(stderr, "No match found " |
| "for token: /%s/\en", value); |
| errfnd = 1; |
| break; |
| } |
| } |
| if (readwrite && readonly) { |
| fprintf(stderr, "Only one of \(aq%s\(aq and \(aq%s\(aq can be " |
| "specified\en", token[RO_OPT], token[RW_OPT]); |
| errfnd = 1; |
| } |
| break; |
| |
| default: |
| errfnd = 1; |
| } |
| } |
| |
| if (errfnd || argc == 1) { |
| fprintf(stderr, "\enUsage: %s \-o <suboptstring>\en", argv[0]); |
| fprintf(stderr, "suboptions are \(aqro\(aq, \(aqrw\(aq, " |
| "and \(aqname=<value>\(aq\en"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Remainder of program... */ |
| |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .SH SEE ALSO |
| .BR getopt (3) |