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