[BACK]Return to refuse_opt.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / librefuse

Annotation of src/lib/librefuse/refuse_opt.c, Revision 1.3

1.3     ! agc         1: /*     $NetBSD: refuse_opt.c,v 1.2 2007/02/28 21:48:46 agc Exp $       */
1.1       xtraeme     2:
                      3: /*-
                      4:  * Copyright (c) 2007 Juan Romero Pardines.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the company nor the name of the author may be used to
                     16:  *    endorse or promote products derived from this software without
                     17:  *    specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     22:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     24:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     28:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30:
                     31: /*
                     32:  * TODO:
                     33:  *     * -oblah,foo... works, but the options are not enabled.
                     34:  *     * -ofoo=%s (accepts a string) or -ofoo=%u (int) is not
                     35:  *       supported for now.
                     36:  *     * void *data: how is it used? I think it's used to enable
                     37:  *       options or pass values for the matching options.
                     38:  */
                     39:
                     40: #include "defs.h"
                     41: #include "fuse.h"
                     42: #include "fuse_opt.h"
                     43:
                     44: #ifdef FUSE_OPT_DEBUG
1.2       agc        45: #define DPRINTF(x)     do { printf x; } while ( /* CONSTCOND */ 0)
1.1       xtraeme    46: #else
                     47: #define DPRINTF(x)
                     48: #endif
                     49:
                     50: enum {
                     51:        KEY_HELP,
                     52:        KEY_VERBOSE,
                     53:        KEY_VERSION
                     54: };
                     55:
                     56: struct fuse_opt_option {
                     57:        const struct fuse_opt *fop;
                     58:        char *option;
                     59:        int key;
                     60:        void *data;
                     61: };
                     62:
                     63: static int fuse_opt_popt(struct fuse_opt_option *, const struct fuse_opt *);
                     64:
                     65: /*
                     66:  * Public API.
                     67:  *
                     68:  * The following functions always return 0:
                     69:  *
                     70:  * int fuse_opt_add_arg(struct fuse_args *, const char *);
                     71:  * int fuse_opt_add_opt(char **, const char *);
                     72:  * void        fuse_opt_free_args(struct fuse_args *);
                     73:  * int fuse_opt_insert_arg(struct fuse_args *, const char *);
                     74:  *
                     75:  * We implement the next ones:
                     76:  *
                     77:  * int fuse_opt_match(const struct fuse_opt *, const char *);
                     78:  * int fuse_opt_parse(struct fuse_args *, void *,
                     79:  *                    const struct fuse_opt *, fuse_opt_proc_t);
                     80:  *
                     81:  */
                     82:
1.3     ! agc        83: #define ARGS_CHUNK     32
        !            84:
        !            85: static int
        !            86: growargs(struct fuse_args *args, const char *func)
        !            87: {
        !            88:        if (args->allocated == 0) {
        !            89:                NEWARRAY(char *, args->argv, ARGS_CHUNK,
        !            90:                        func, return 0);
        !            91:                args->allocated = ARGS_CHUNK;
        !            92:        } else if (args->argc % ARGS_CHUNK == 0) {
        !            93:                args->allocated += ARGS_CHUNK;
        !            94:                RENEW(char *, args->argv, args->allocated,
        !            95:                        func, return 0);
        !            96:        }
        !            97:        return 1;
        !            98: }
        !            99:
1.1       xtraeme   100: int
                    101: fuse_opt_add_arg(struct fuse_args *args, const char *arg)
                    102: {
                    103:        DPRINTF(("%s: arguments passed: [arg:%s]\n", __func__, arg));
1.3     ! agc       104:        if (!growargs(args, "fuse_opt_add_arg")) {
        !           105:                return 1;
        !           106:        }
        !           107:        args->argv[args->argc++] = strdup(arg);
        !           108:         return 0;
1.1       xtraeme   109: }
                    110:
                    111: void
                    112: fuse_opt_free_args(struct fuse_args *args)
                    113: {
1.3     ! agc       114:        int     i;
        !           115:
        !           116:        for (i = 0 ; i < args->allocated ; i++) {
        !           117:                (void) free(args->argv[i]);
        !           118:        }
        !           119:        if (args->allocated > 0) {
        !           120:                FREE(args->argv);
        !           121:        }
        !           122:        (void) memset(args, 0x0, sizeof(*args));
1.1       xtraeme   123: }
                    124:
                    125: int
                    126: fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
                    127: {
1.3     ! agc       128:        int     i;
        !           129:
        !           130: __fuse_pargs("fuse_opt_insert_arg1", args->argc, args->argv);
        !           131:        if (!growargs(args, "fuse_opt_insert_arg")) {
        !           132:                return 1;
        !           133:        }
        !           134:        for (i = args->argc++ ; i > pos ; --i) {
        !           135:                args->argv[i] = args->argv[i - 1];
        !           136:        }
        !           137:        args->argv[pos] = strdup(arg);
        !           138: __fuse_pargs("fuse_opt_insert_arg2", args->argc, args->argv);
        !           139:        return 0;
1.1       xtraeme   140: }
                    141:
                    142: /* ARGSUSED */
                    143: int fuse_opt_add_opt(char **opts, const char *opt)
                    144: {
                    145:        DPRINTF(("%s: arguments passed: [opts=%s] [opt=%s]\n",
                    146:            __func__, *opts, opt));
1.3     ! agc       147:        return 0;
1.1       xtraeme   148: }
                    149:
                    150: /*
                    151:  * Returns 0 if opt was matched with any option from opts,
                    152:  * otherwise returns 1.
                    153:  */
                    154: int
                    155: fuse_opt_match(const struct fuse_opt *opts, const char *opt)
                    156: {
                    157:        while (opts++) {
                    158:                if (strcmp(opt, opts->templ) == 0)
1.3     ! agc       159:                        return 0;
1.1       xtraeme   160:        }
                    161:
1.3     ! agc       162:        return 1;
1.1       xtraeme   163: }
                    164:
                    165: /*
                    166:  * Returns 0 if foo->option was matched with any option from opts,
                    167:  * and sets the following on match:
                    168:  *
                    169:  *     * foo->key is set to the foo->fop->value if offset == -1.
                    170:  *     * foo->fop points to the matched struct opts.
                    171:  *
                    172:  * otherwise returns 1.
                    173:  */
                    174: static int
                    175: fuse_opt_popt(struct fuse_opt_option *foo, const struct fuse_opt *opts)
                    176: {
                    177:        int i, found = 0;
                    178:        char *match;
                    179:
                    180:        if (!foo->option) {
                    181:                (void)fprintf(stderr, "fuse: missing argument after -o\n");
1.3     ! agc       182:                return 1;
1.1       xtraeme   183:        }
                    184:        /*
                    185:         * iterate over argv and opts to see
                    186:         * if there's a match with any template.
                    187:         */
                    188:        for (match = strtok(foo->option, ",");
                    189:             match; match = strtok(NULL, ",")) {
                    190:
                    191:                DPRINTF(("%s: specified option='%s'\n", __func__, match));
                    192:                found = 0;
                    193:
                    194:                for (i = 0; opts && opts->templ; opts++, i++) {
                    195:
                    196:                        DPRINTF(("%s: opts->templ='%s' opts->offset=%d "
                    197:                            "opts->value=%d\n", __func__, opts->templ,
                    198:                            opts->offset, opts->value));
                    199:
                    200:                        /* option is ok */
                    201:                        if (strcmp(match, opts->templ) == 0) {
                    202:                                DPRINTF(("%s: option matched='%s'\n",
                    203:                                    __func__, match));
                    204:                                found++;
                    205:                                /*
                    206:                                 * our fop pointer now points
                    207:                                 * to the matched struct opts.
                    208:                                 */
                    209:                                foo->fop = opts;
                    210:                                /*
                    211:                                 * assign default key value, necessary for
                    212:                                 * KEY_HELP, KEY_VERSION and KEY_VERBOSE.
                    213:                                 */
                    214:                                if (foo->fop->offset == -1)
                    215:                                        foo->key = foo->fop->value;
                    216:                                /* reset counter */
                    217:                                opts -= i;
                    218:                                break;
                    219:                        }
                    220:                }
                    221:                /* invalid option */
                    222:                if (!found) {
                    223:                        (void)fprintf(stderr, "fuse: '%s' is not a "
                    224:                            "valid option\n", match);
1.3     ! agc       225:                        return 1;
1.1       xtraeme   226:                }
                    227:        }
                    228:
1.3     ! agc       229:        return 0;
1.1       xtraeme   230: }
                    231:
1.2       agc       232: /* ARGSUSED1 */
1.1       xtraeme   233: int
                    234: fuse_opt_parse(struct fuse_args *args, void *data,
                    235:         const struct fuse_opt *opts, fuse_opt_proc_t proc)
                    236: {
                    237:        struct fuse_opt_option foo;
                    238:        char *buf;
1.3     ! agc       239:        int i, rv = 0;
1.1       xtraeme   240:
1.3     ! agc       241:        if (!args || !args->argv || !args->argc || !proc) {
        !           242:                if (__fuse_debug(0)) {
        !           243:                        printf("fuse_opt_parse: null args\n");
        !           244:                }
1.1       xtraeme   245:                return 0;
1.3     ! agc       246:        }
        !           247:
        !           248:        if (__fuse_debug(0)) {
        !           249:                __fuse_pargs("fuse_opt_parse", args->argc, args->argv);
        !           250:        }
1.1       xtraeme   251:
                    252:        if (args->argc == 1)
                    253:                return proc(foo.data, *args->argv, FUSE_OPT_KEY_OPT, args);
                    254:
                    255:        /* the real loop to process the arguments */
                    256:        for (i = 1; i < args->argc; i++) {
                    257:
                    258:                /* assign current argv string */
                    259:                foo.option = buf = args->argv[i];
                    260:
                    261:                /* argvn != -foo... */
                    262:                if (buf[0] != '-') {
                    263:
                    264:                        foo.key = FUSE_OPT_KEY_NONOPT;
1.2       agc       265:                        rv = proc(foo.data, foo.option, foo.key, args);
                    266:                        if (rv != 0)
1.1       xtraeme   267:                                break;
                    268:
                    269:                /* -o was specified... */
                    270:                } else if (buf[0] == '-' && buf[1] == 'o') {
                    271:
                    272:                        /* -oblah,foo... */
                    273:                        if (buf[2]) {
                    274:                                /* skip -o */
                    275:                                foo.option = args->argv[i] + 2;
                    276:                        /* -o blah,foo... */
                    277:                        } else {
                    278:                                /*
                    279:                                 * skip current argv and pass to the
                    280:                                 * next one to parse the options.
                    281:                                 */
                    282:                                ++i;
                    283:                                foo.option = args->argv[i];
                    284:                        }
                    285:
1.2       agc       286:                        rv = fuse_opt_popt(&foo, opts);
                    287:                        if (rv != 0)
1.1       xtraeme   288:                                break;
                    289:
                    290:                /* help/version/verbose argument */
                    291:                } else if (buf[0] == '-' && buf[1] != 'o') {
                    292:                        /*
                    293:                         * check if the argument matches
                    294:                         * with any template in opts.
                    295:                         */
1.2       agc       296:                        rv = fuse_opt_popt(&foo, opts);
                    297:                        if (rv != 0) {
1.1       xtraeme   298:                                break;
                    299:                        } else {
                    300:                                DPRINTF(("%s: foo.fop->templ='%s' "
                    301:                                    "foo.fop->offset: %d "
                    302:                                    "foo.fop->value: %d\n",
                    303:                                    __func__, foo.fop->templ,
                    304:                                    foo.fop->offset, foo.fop->value));
                    305:
                    306:                                /* argument needs to be discarded */
                    307:                                if (foo.key == FUSE_OPT_KEY_DISCARD) {
1.3     ! agc       308:                                        rv = 1;
1.1       xtraeme   309:                                        break;
                    310:                                }
                    311:
                    312:                                /* process help/version argument */
                    313:                                if (foo.key != KEY_VERBOSE &&
                    314:                                    foo.key != FUSE_OPT_KEY_KEEP) {
                    315:                                        rv = proc(foo.data, foo.option,
                    316:                                                  foo.key, args);
                    317:                                        break;
                    318:                                } else {
                    319:                                        /* process verbose argument */
1.2       agc       320:                                        rv = proc(foo.data, foo.option,
                    321:                                                       foo.key, args);
                    322:                                        if (rv != 0)
1.1       xtraeme   323:                                                break;
                    324:                                }
                    325:                        }
                    326:                /* unknown option, how could that happen? */
                    327:                } else {
                    328:                        DPRINTF(("%s: unknown option\n", __func__));
1.3     ! agc       329:                        rv = 1;
1.1       xtraeme   330:                        break;
                    331:                }
                    332:        }
                    333:
                    334:        return rv;
                    335: }

CVSweb <webmaster@jp.NetBSD.org>