getsubopt(3) 文字列中のサブオプション引き数の解釈を行う

書式

#include <stdlib.h>

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

glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):

getsubopt():

_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L

説明

getsubopt() は、 optionp で与えられたカンマ区切りのサブオプション・リストを解析する。 (このようなサブオプション・リストは getopt(3) を使ってコマンドラインを解釈した場合に現れることが多い。 例えば、 mount(8) の -o オプションを見るとよい。) それぞれのサブオプションには対応する値を指定することができる。 サブオプションの名前と対応する値は等号 ('=') で区切られる。 例えば、以下のような文字列を optionp に渡すことができる。

ro,name=xyz

tokens 引き数はトークンへのポインタの配列へのポインタで、 配列は NULL で終端される。 getsubopt() はこのトークンを optionp 内で探す。 それぞれのトークンは、NULL 終端された 1文字以上の文字列で、 他のトークンと区別できる必要がある。 また、等号とカンマを含んではならない。

getsubopt() は呼び出されるたびに、 optionp 中の次の未処理のサブオプションの情報を返す。 サブオプション内に等号があった場合、最初の等号は そのサブオプションの名前と値の区切りと解釈される。 区切りから次のカンマ (最後のサブオプションの場合、文字列の末尾) までが、サブオプションの値となる。 サブオプションの名前が tokens 内の名前と一致し、値を表す文字列が見つかった場合、 getsubopt() は *valuep を値を表す文字列のアドレスに設定する。 optionp 中の最初のカンマはヌルバイトで上書きされる。そのため、 *valuep はそのサブオプションの「値の文字列」そのものとなる。

サブオプションが認識されたが、値を表す文字列が見つからなかった場合、 *valuep は NULL に設定される。

getsubopt() が返る時、 optionp は次のサブオプションを指している。 ちょうど最後のサブオプションが処理された場合は、 文字列末尾のヌルバイト ('\0') を指している。

返り値

optionp 内でサブオプションが見つかった場合、 getsubopt() は最初のサブオプションにマッチする tokens の要素の添字を返す。 見つからなかった場合、-1 を返す。この場合、 *valuepname[=value] の文字列全体となる。

*optionp は変更されるので、 getsubopt() を呼び出す前の最初のサブオプションは getsubopt() を呼び出し後のサブオプションと必ずしも同じとは限らない。

属性

マルチスレッディング (pthreads(7) 参照)

関数 getsubopt() はスレッドセーフである。

準拠

POSIX.1-2001.

注意

getsubopt() は、文字列 *optionp 中に見つけたカンマを上書きするので、文字列 *optionp は書き込み可能でなければならず、 文字列定数にすることはできない。

以下のプログラムは "-o" オプションに続いてサブオプションがあることを 期待している。

#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 'o':
            subopts = optarg;
            while (*subopts != '\0' && !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 '%s'\n", token[NAME_OPT]);
                    errfnd = 1;
                    continue;
                }
                name = value;
                break;
            default:
                fprintf(stderr, "No match found "
                        "for token: /%s/\n", value);
                errfnd = 1;
                break;
            }
        }
        if (readwrite && readonly) {
            fprintf(stderr, "Only one of '%s' and '%s' can be "
                    "specified\n", token[RO_OPT], token[RW_OPT]);
            errfnd = 1;
        }
        break;
        default:
            errfnd = 1;
        }
    }
    if (errfnd || argc == 1) {
        fprintf(stderr, "\nUsage: %s -o <suboptstring>\n", argv[0]);
        fprintf(stderr, "suboptions are 'ro', 'rw', "
                "and 'name=<value>'\n");
        exit(EXIT_FAILURE);
    }
    /* Remainder of program... */
    exit(EXIT_SUCCESS);
}

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。