load.c revision 1.2.6.1 1 1.2.6.1 tls /* $NetBSD: load.c,v 1.2.6.1 2014/08/19 23:51:47 tls Exp $ */
2 1.1 kardel
3 1.1 kardel
4 1.2 christos /**
5 1.2 christos * \file load.c
6 1.1 kardel *
7 1.1 kardel * This file contains the routines that deal with processing text strings
8 1.1 kardel * for options, either from a NUL-terminated string passed in or from an
9 1.1 kardel * rc/ini file.
10 1.1 kardel *
11 1.2.6.1 tls * @addtogroup autoopts
12 1.2.6.1 tls * @{
13 1.2.6.1 tls */
14 1.2.6.1 tls /*
15 1.1 kardel * This file is part of AutoOpts, a companion to AutoGen.
16 1.1 kardel * AutoOpts is free software.
17 1.2.6.1 tls * AutoOpts is Copyright (C) 1992-2013 by Bruce Korb - all rights reserved
18 1.1 kardel *
19 1.1 kardel * AutoOpts is available under any one of two licenses. The license
20 1.1 kardel * in use must be one of these two and the choice is under the control
21 1.1 kardel * of the user of the license.
22 1.1 kardel *
23 1.1 kardel * The GNU Lesser General Public License, version 3 or later
24 1.1 kardel * See the files "COPYING.lgplv3" and "COPYING.gplv3"
25 1.1 kardel *
26 1.1 kardel * The Modified Berkeley Software Distribution License
27 1.1 kardel * See the file "COPYING.mbsd"
28 1.1 kardel *
29 1.2.6.1 tls * These files have the following sha256 sums:
30 1.1 kardel *
31 1.2.6.1 tls * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
32 1.2.6.1 tls * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
33 1.2.6.1 tls * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
34 1.1 kardel */
35 1.1 kardel
36 1.1 kardel /* = = = START-STATIC-FORWARD = = = */
37 1.2.6.1 tls static bool
38 1.2.6.1 tls get_realpath(char * buf, size_t b_sz);
39 1.2.6.1 tls
40 1.2.6.1 tls static bool
41 1.2.6.1 tls add_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path);
42 1.2.6.1 tls
43 1.2.6.1 tls static bool
44 1.2.6.1 tls add_env_val(char * buf, int buf_sz, char const * name);
45 1.1 kardel
46 1.2.6.1 tls static char *
47 1.2.6.1 tls assemble_arg_val(char * txt, tOptionLoadMode mode);
48 1.2.6.1 tls
49 1.2.6.1 tls static char *
50 1.2.6.1 tls trim_quotes(char * arg);
51 1.2.6.1 tls
52 1.2.6.1 tls static bool
53 1.2.6.1 tls direction_ok(opt_state_mask_t f, int dir);
54 1.1 kardel /* = = = END-STATIC-FORWARD = = = */
55 1.1 kardel
56 1.2.6.1 tls static bool
57 1.2.6.1 tls get_realpath(char * buf, size_t b_sz)
58 1.2.6.1 tls {
59 1.2.6.1 tls #if defined(HAVE_CANONICALIZE_FILE_NAME)
60 1.2.6.1 tls {
61 1.2.6.1 tls size_t name_len;
62 1.2.6.1 tls
63 1.2.6.1 tls char * pz = canonicalize_file_name(buf);
64 1.2.6.1 tls if (pz == NULL)
65 1.2.6.1 tls return false;
66 1.2.6.1 tls
67 1.2.6.1 tls name_len = strlen(pz);
68 1.2.6.1 tls if (name_len >= (size_t)b_sz) {
69 1.2.6.1 tls free(pz);
70 1.2.6.1 tls return false;
71 1.2.6.1 tls }
72 1.2.6.1 tls
73 1.2.6.1 tls memcpy(buf, pz, name_len + 1);
74 1.2.6.1 tls free(pz);
75 1.2.6.1 tls }
76 1.2.6.1 tls
77 1.2.6.1 tls #elif defined(HAVE_REALPATH)
78 1.2.6.1 tls {
79 1.2.6.1 tls size_t name_len;
80 1.2.6.1 tls char z[PATH_MAX+1];
81 1.2.6.1 tls
82 1.2.6.1 tls if (realpath(buf, z) == NULL)
83 1.2.6.1 tls return false;
84 1.2.6.1 tls
85 1.2.6.1 tls name_len = strlen(z);
86 1.2.6.1 tls if (name_len >= b_sz)
87 1.2.6.1 tls return false;
88 1.2.6.1 tls
89 1.2.6.1 tls memcpy(buf, z, name_len + 1);
90 1.2.6.1 tls }
91 1.2.6.1 tls #endif
92 1.2.6.1 tls return true;
93 1.2.6.1 tls }
94 1.2.6.1 tls
95 1.1 kardel /*=export_func optionMakePath
96 1.1 kardel * private:
97 1.1 kardel *
98 1.1 kardel * what: translate and construct a path
99 1.2.6.1 tls * arg: + char* + p_buf + The result buffer +
100 1.2.6.1 tls * arg: + int + b_sz + The size of this buffer +
101 1.2.6.1 tls * arg: + char const* + fname + The input name +
102 1.2.6.1 tls * arg: + char const* + prg_path + The full path of the current program +
103 1.1 kardel *
104 1.2.6.1 tls * ret-type: bool
105 1.2.6.1 tls * ret-desc: true if the name was handled, otherwise false.
106 1.1 kardel * If the name does not start with ``$'', then it is handled
107 1.1 kardel * simply by copying the input name to the output buffer and
108 1.1 kardel * resolving the name with either
109 1.1 kardel * @code{canonicalize_file_name(3GLIBC)} or @code{realpath(3C)}.
110 1.1 kardel *
111 1.1 kardel * doc:
112 1.1 kardel *
113 1.2 christos * This routine will copy the @code{pzName} input name into the
114 1.2 christos * @code{pzBuf} output buffer, not exceeding @code{bufSize} bytes. If the
115 1.1 kardel * first character of the input name is a @code{'$'} character, then there
116 1.1 kardel * is special handling:
117 1.1 kardel * @*
118 1.1 kardel * @code{$$} is replaced with the directory name of the @code{pzProgPath},
119 1.1 kardel * searching @code{$PATH} if necessary.
120 1.1 kardel * @*
121 1.1 kardel * @code{$@} is replaced with the AutoGen package data installation directory
122 1.1 kardel * (aka @code{pkgdatadir}).
123 1.1 kardel * @*
124 1.1 kardel * @code{$NAME} is replaced by the contents of the @code{NAME} environment
125 1.1 kardel * variable. If not found, the search fails.
126 1.1 kardel *
127 1.1 kardel * Please note: both @code{$$} and @code{$NAME} must be at the start of the
128 1.1 kardel * @code{pzName} string and must either be the entire string or be followed
129 1.1 kardel * by the @code{'/'} (backslash on windows) character.
130 1.1 kardel *
131 1.2.6.1 tls * err: @code{false} is returned if:
132 1.1 kardel * @*
133 1.1 kardel * @bullet{} The input name exceeds @code{bufSize} bytes.
134 1.1 kardel * @*
135 1.1 kardel * @bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string
136 1.1 kardel * and the next character is not '/'.
137 1.1 kardel * @*
138 1.1 kardel * @bullet{} libopts was built without PKGDATADIR defined and @code{$@@}
139 1.1 kardel * was specified.
140 1.1 kardel * @*
141 1.1 kardel * @bullet{} @code{NAME} is not a known environment variable
142 1.1 kardel * @*
143 1.1 kardel * @bullet{} @code{canonicalize_file_name} or @code{realpath} return
144 1.1 kardel * errors (cannot resolve the resulting path).
145 1.1 kardel =*/
146 1.2.6.1 tls bool
147 1.2.6.1 tls optionMakePath(char * p_buf, int b_sz, char const * fname, char const * prg_path)
148 1.1 kardel {
149 1.2.6.1 tls {
150 1.2.6.1 tls size_t len = strlen(fname);
151 1.1 kardel
152 1.2.6.1 tls if (((size_t)b_sz <= len) || (len == 0))
153 1.2.6.1 tls return false;
154 1.2.6.1 tls }
155 1.1 kardel
156 1.1 kardel /*
157 1.1 kardel * IF not an environment variable, just copy the data
158 1.1 kardel */
159 1.2.6.1 tls if (*fname != '$') {
160 1.2.6.1 tls char const * src = fname;
161 1.2.6.1 tls char * dst = p_buf;
162 1.2.6.1 tls int ct = b_sz;
163 1.1 kardel
164 1.1 kardel for (;;) {
165 1.2.6.1 tls if ( (*(dst++) = *(src++)) == NUL)
166 1.1 kardel break;
167 1.1 kardel if (--ct <= 0)
168 1.2.6.1 tls return false;
169 1.1 kardel }
170 1.1 kardel }
171 1.1 kardel
172 1.1 kardel /*
173 1.1 kardel * IF the name starts with "$$", then it must be "$$" or
174 1.1 kardel * it must start with "$$/". In either event, replace the "$$"
175 1.1 kardel * with the path to the executable and append a "/" character.
176 1.1 kardel */
177 1.2.6.1 tls else switch (fname[1]) {
178 1.1 kardel case NUL:
179 1.2.6.1 tls return false;
180 1.1 kardel
181 1.1 kardel case '$':
182 1.2.6.1 tls if (! add_prog_path(p_buf, b_sz, fname, prg_path))
183 1.2.6.1 tls return false;
184 1.1 kardel break;
185 1.1 kardel
186 1.1 kardel case '@':
187 1.2 christos if (program_pkgdatadir[0] == NUL)
188 1.2.6.1 tls return false;
189 1.1 kardel
190 1.2.6.1 tls if (snprintf(p_buf, (size_t)b_sz, "%s%s",
191 1.2.6.1 tls program_pkgdatadir, fname + 2) >= b_sz)
192 1.2.6.1 tls return false;
193 1.1 kardel break;
194 1.1 kardel
195 1.1 kardel default:
196 1.2.6.1 tls if (! add_env_val(p_buf, b_sz, fname))
197 1.2.6.1 tls return false;
198 1.1 kardel }
199 1.1 kardel
200 1.2.6.1 tls return get_realpath(p_buf, b_sz);
201 1.1 kardel }
202 1.1 kardel
203 1.2.6.1 tls /**
204 1.2.6.1 tls * convert a leading "$$" into a path to the executable.
205 1.2.6.1 tls */
206 1.2.6.1 tls static bool
207 1.2.6.1 tls add_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path)
208 1.1 kardel {
209 1.2.6.1 tls char const * path;
210 1.2.6.1 tls char const * pz;
211 1.1 kardel int skip = 2;
212 1.1 kardel
213 1.2.6.1 tls switch (fname[2]) {
214 1.1 kardel case DIRCH:
215 1.1 kardel skip = 3;
216 1.1 kardel case NUL:
217 1.1 kardel break;
218 1.1 kardel default:
219 1.2.6.1 tls return false;
220 1.1 kardel }
221 1.1 kardel
222 1.1 kardel /*
223 1.1 kardel * See if the path is included in the program name.
224 1.1 kardel * If it is, we're done. Otherwise, we have to hunt
225 1.1 kardel * for the program using "pathfind".
226 1.1 kardel */
227 1.2.6.1 tls if (strchr(prg_path, DIRCH) != NULL)
228 1.2.6.1 tls path = prg_path;
229 1.1 kardel else {
230 1.2.6.1 tls path = pathfind(getenv("PATH"), (char*)(intptr_t)prg_path, "rx");
231 1.1 kardel
232 1.2.6.1 tls if (path == NULL)
233 1.2.6.1 tls return false;
234 1.1 kardel }
235 1.1 kardel
236 1.2.6.1 tls pz = strrchr(path, DIRCH);
237 1.1 kardel
238 1.1 kardel /*
239 1.1 kardel * IF we cannot find a directory name separator,
240 1.1 kardel * THEN we do not have a path name to our executable file.
241 1.1 kardel */
242 1.1 kardel if (pz == NULL)
243 1.2.6.1 tls return false;
244 1.1 kardel
245 1.2.6.1 tls fname += skip;
246 1.1 kardel
247 1.1 kardel /*
248 1.1 kardel * Concatenate the file name to the end of the executable path.
249 1.1 kardel * The result may be either a file or a directory.
250 1.1 kardel */
251 1.2.6.1 tls if ((unsigned)(pz - path) + 1 + strlen(fname) >= (unsigned)b_sz)
252 1.2.6.1 tls return false;
253 1.1 kardel
254 1.2.6.1 tls memcpy(buf, path, (size_t)((pz - path)+1));
255 1.2.6.1 tls strcpy(buf + (pz - path) + 1, fname);
256 1.1 kardel
257 1.1 kardel /*
258 1.2.6.1 tls * If the "path" path was gotten from "pathfind()", then it was
259 1.1 kardel * allocated and we need to deallocate it.
260 1.1 kardel */
261 1.2.6.1 tls if (path != prg_path)
262 1.2.6.1 tls AGFREE(path);
263 1.2.6.1 tls return true;
264 1.1 kardel }
265 1.1 kardel
266 1.2.6.1 tls /**
267 1.2.6.1 tls * Add an environment variable value.
268 1.2.6.1 tls */
269 1.2.6.1 tls static bool
270 1.2.6.1 tls add_env_val(char * buf, int buf_sz, char const * name)
271 1.1 kardel {
272 1.2.6.1 tls char * dir_part = buf;
273 1.1 kardel
274 1.1 kardel for (;;) {
275 1.2.6.1 tls int ch = (int)*++name;
276 1.1 kardel if (! IS_VALUE_NAME_CHAR(ch))
277 1.1 kardel break;
278 1.2.6.1 tls *(dir_part++) = (char)ch;
279 1.1 kardel }
280 1.1 kardel
281 1.2.6.1 tls if (dir_part == buf)
282 1.2.6.1 tls return false;
283 1.1 kardel
284 1.2.6.1 tls *dir_part = NUL;
285 1.1 kardel
286 1.2.6.1 tls dir_part = getenv(buf);
287 1.1 kardel
288 1.1 kardel /*
289 1.1 kardel * Environment value not found -- skip the home list entry
290 1.1 kardel */
291 1.2.6.1 tls if (dir_part == NULL)
292 1.2.6.1 tls return false;
293 1.1 kardel
294 1.2.6.1 tls if (strlen(dir_part) + 1 + strlen(name) >= (unsigned)buf_sz)
295 1.2.6.1 tls return false;
296 1.1 kardel
297 1.2.6.1 tls sprintf(buf, "%s%s", dir_part, name);
298 1.2.6.1 tls return true;
299 1.1 kardel }
300 1.1 kardel
301 1.2.6.1 tls /**
302 1.2.6.1 tls * Trim leading and trailing white space.
303 1.2.6.1 tls * If we are cooking the text and the text is quoted, then "cook"
304 1.2.6.1 tls * the string. To cook, the string must be quoted.
305 1.2.6.1 tls *
306 1.2.6.1 tls * @param[in,out] txt the input and output string
307 1.2.6.1 tls * @param[in] mode the handling mode (cooking method)
308 1.2.6.1 tls */
309 1.1 kardel LOCAL void
310 1.2.6.1 tls munge_str(char * txt, tOptionLoadMode mode)
311 1.1 kardel {
312 1.2.6.1 tls char * pzE;
313 1.1 kardel
314 1.1 kardel if (mode == OPTION_LOAD_KEEP)
315 1.1 kardel return;
316 1.1 kardel
317 1.2.6.1 tls if (IS_WHITESPACE_CHAR(*txt)) {
318 1.2.6.1 tls char * src = SPN_WHITESPACE_CHARS(txt+1);
319 1.2.6.1 tls size_t l = strlen(src) + 1;
320 1.2.6.1 tls memmove(txt, src, l);
321 1.2.6.1 tls pzE = txt + l - 1;
322 1.2.6.1 tls
323 1.1 kardel } else
324 1.2.6.1 tls pzE = txt + strlen(txt);
325 1.1 kardel
326 1.2.6.1 tls pzE = SPN_WHITESPACE_BACK(txt, pzE);
327 1.1 kardel *pzE = NUL;
328 1.1 kardel
329 1.1 kardel if (mode == OPTION_LOAD_UNCOOKED)
330 1.1 kardel return;
331 1.1 kardel
332 1.2.6.1 tls switch (*txt) {
333 1.1 kardel default: return;
334 1.1 kardel case '"':
335 1.1 kardel case '\'': break;
336 1.1 kardel }
337 1.1 kardel
338 1.1 kardel switch (pzE[-1]) {
339 1.1 kardel default: return;
340 1.1 kardel case '"':
341 1.1 kardel case '\'': break;
342 1.1 kardel }
343 1.1 kardel
344 1.2.6.1 tls (void)ao_string_cook(txt, NULL);
345 1.1 kardel }
346 1.1 kardel
347 1.2.6.1 tls static char *
348 1.2.6.1 tls assemble_arg_val(char * txt, tOptionLoadMode mode)
349 1.1 kardel {
350 1.2.6.1 tls char * end = strpbrk(txt, ARG_BREAK_STR);
351 1.2.6.1 tls int space_break;
352 1.1 kardel
353 1.1 kardel /*
354 1.1 kardel * Not having an argument to a configurable name is okay.
355 1.1 kardel */
356 1.2.6.1 tls if (end == NULL)
357 1.2.6.1 tls return txt + strlen(txt);
358 1.1 kardel
359 1.1 kardel /*
360 1.1 kardel * If we are keeping all whitespace, then the modevalue starts with the
361 1.1 kardel * character that follows the end of the configurable name, regardless
362 1.1 kardel * of which character caused it.
363 1.1 kardel */
364 1.1 kardel if (mode == OPTION_LOAD_KEEP) {
365 1.2.6.1 tls *(end++) = NUL;
366 1.2.6.1 tls return end;
367 1.1 kardel }
368 1.1 kardel
369 1.1 kardel /*
370 1.1 kardel * If the name ended on a white space character, remember that
371 1.1 kardel * because we'll have to skip over an immediately following ':' or '='
372 1.1 kardel * (and the white space following *that*).
373 1.1 kardel */
374 1.2.6.1 tls space_break = IS_WHITESPACE_CHAR(*end);
375 1.2.6.1 tls *(end++) = NUL;
376 1.1 kardel
377 1.2.6.1 tls end = SPN_WHITESPACE_CHARS(end);
378 1.2.6.1 tls if (space_break && ((*end == ':') || (*end == '=')))
379 1.2.6.1 tls end = SPN_WHITESPACE_CHARS(end+1);
380 1.2.6.1 tls
381 1.2.6.1 tls return end;
382 1.1 kardel }
383 1.1 kardel
384 1.2.6.1 tls static char *
385 1.2.6.1 tls trim_quotes(char * arg)
386 1.2.6.1 tls {
387 1.2.6.1 tls switch (*arg) {
388 1.2.6.1 tls case '"':
389 1.2.6.1 tls case '\'':
390 1.2.6.1 tls ao_string_cook(arg, NULL);
391 1.2.6.1 tls }
392 1.2.6.1 tls return arg;
393 1.2.6.1 tls }
394 1.1 kardel
395 1.2.6.1 tls /**
396 1.2.6.1 tls * See if the option is to be processed in the current scan direction
397 1.2.6.1 tls * (-1 or +1).
398 1.1 kardel */
399 1.2.6.1 tls static bool
400 1.2.6.1 tls direction_ok(opt_state_mask_t f, int dir)
401 1.1 kardel {
402 1.2.6.1 tls if (dir == 0)
403 1.2.6.1 tls return true;
404 1.1 kardel
405 1.2.6.1 tls switch (f & (OPTST_IMM|OPTST_DISABLE_IMM)) {
406 1.1 kardel case 0:
407 1.1 kardel /*
408 1.1 kardel * The selected option has no immediate action.
409 1.1 kardel * THEREFORE, if the direction is PRESETTING
410 1.1 kardel * THEN we skip this option.
411 1.1 kardel */
412 1.2.6.1 tls if (PRESETTING(dir))
413 1.2.6.1 tls return false;
414 1.1 kardel break;
415 1.1 kardel
416 1.1 kardel case OPTST_IMM:
417 1.2.6.1 tls if (PRESETTING(dir)) {
418 1.1 kardel /*
419 1.1 kardel * We are in the presetting direction with an option we handle
420 1.1 kardel * immediately for enablement, but normally for disablement.
421 1.1 kardel * Therefore, skip if disabled.
422 1.1 kardel */
423 1.2.6.1 tls if ((f & OPTST_DISABLED) == 0)
424 1.2.6.1 tls return false;
425 1.1 kardel } else {
426 1.1 kardel /*
427 1.1 kardel * We are in the processing direction with an option we handle
428 1.1 kardel * immediately for enablement, but normally for disablement.
429 1.1 kardel * Therefore, skip if NOT disabled.
430 1.1 kardel */
431 1.2.6.1 tls if ((f & OPTST_DISABLED) != 0)
432 1.2.6.1 tls return false;
433 1.1 kardel }
434 1.1 kardel break;
435 1.1 kardel
436 1.1 kardel case OPTST_DISABLE_IMM:
437 1.2.6.1 tls if (PRESETTING(dir)) {
438 1.1 kardel /*
439 1.1 kardel * We are in the presetting direction with an option we handle
440 1.1 kardel * immediately for disablement, but normally for disablement.
441 1.1 kardel * Therefore, skip if NOT disabled.
442 1.1 kardel */
443 1.2.6.1 tls if ((f & OPTST_DISABLED) != 0)
444 1.2.6.1 tls return false;
445 1.1 kardel } else {
446 1.1 kardel /*
447 1.1 kardel * We are in the processing direction with an option we handle
448 1.1 kardel * immediately for disablement, but normally for disablement.
449 1.1 kardel * Therefore, skip if disabled.
450 1.1 kardel */
451 1.2.6.1 tls if ((f & OPTST_DISABLED) == 0)
452 1.2.6.1 tls return false;
453 1.1 kardel }
454 1.1 kardel break;
455 1.1 kardel
456 1.1 kardel case OPTST_IMM|OPTST_DISABLE_IMM:
457 1.1 kardel /*
458 1.1 kardel * The selected option is always for immediate action.
459 1.1 kardel * THEREFORE, if the direction is PROCESSING
460 1.1 kardel * THEN we skip this option.
461 1.1 kardel */
462 1.2.6.1 tls if (PROCESSING(dir))
463 1.2.6.1 tls return false;
464 1.1 kardel break;
465 1.1 kardel }
466 1.2.6.1 tls return true;
467 1.2.6.1 tls }
468 1.2.6.1 tls
469 1.2.6.1 tls /**
470 1.2.6.1 tls * Load an option from a block of text. The text must start with the
471 1.2.6.1 tls * configurable/option name and be followed by its associated value.
472 1.2.6.1 tls * That value may be processed in any of several ways. See "tOptionLoadMode"
473 1.2.6.1 tls * in autoopts.h.
474 1.2.6.1 tls *
475 1.2.6.1 tls * @param[in,out] opts program options descriptor
476 1.2.6.1 tls * @param[in,out] opt_state option processing state
477 1.2.6.1 tls * @param[in,out] line source line with long option name in it
478 1.2.6.1 tls * @param[in] direction current processing direction (preset or not)
479 1.2.6.1 tls * @param[in] load_mode option loading mode (OPTION_LOAD_*)
480 1.2.6.1 tls */
481 1.2.6.1 tls LOCAL void
482 1.2.6.1 tls load_opt_line(tOptions * opts, tOptState * opt_state, char * line,
483 1.2.6.1 tls tDirection direction, tOptionLoadMode load_mode )
484 1.2.6.1 tls {
485 1.2.6.1 tls /*
486 1.2.6.1 tls * When parsing a stored line, we only look at the characters after
487 1.2.6.1 tls * a hyphen. Long names must always be at least two characters and
488 1.2.6.1 tls * short options are always exactly one character long.
489 1.2.6.1 tls */
490 1.2.6.1 tls line = SPN_LOAD_LINE_SKIP_CHARS(line);
491 1.2.6.1 tls
492 1.2.6.1 tls {
493 1.2.6.1 tls char * arg = assemble_arg_val(line, load_mode);
494 1.2.6.1 tls
495 1.2.6.1 tls if (IS_OPTION_NAME_CHAR(line[1])) {
496 1.2.6.1 tls
497 1.2.6.1 tls if (! SUCCESSFUL(opt_find_long(opts, line, opt_state)))
498 1.2.6.1 tls return;
499 1.2.6.1 tls
500 1.2.6.1 tls } else if (! SUCCESSFUL(opt_find_short(opts, *line, opt_state)))
501 1.2.6.1 tls return;
502 1.2.6.1 tls
503 1.2.6.1 tls if ((! CALLED(direction)) && (opt_state->flags & OPTST_NO_INIT))
504 1.2.6.1 tls return;
505 1.2.6.1 tls
506 1.2.6.1 tls opt_state->pzOptArg = trim_quotes(arg);
507 1.2.6.1 tls }
508 1.2.6.1 tls
509 1.2.6.1 tls if (! direction_ok(opt_state->flags, direction))
510 1.2.6.1 tls return;
511 1.1 kardel
512 1.1 kardel /*
513 1.1 kardel * Fix up the args.
514 1.1 kardel */
515 1.2.6.1 tls if (OPTST_GET_ARGTYPE(opt_state->pOD->fOptState) == OPARG_TYPE_NONE) {
516 1.2.6.1 tls if (*opt_state->pzOptArg != NUL)
517 1.1 kardel return;
518 1.2.6.1 tls opt_state->pzOptArg = NULL;
519 1.1 kardel
520 1.2.6.1 tls } else if (opt_state->pOD->fOptState & OPTST_ARG_OPTIONAL) {
521 1.2.6.1 tls if (*opt_state->pzOptArg == NUL)
522 1.2.6.1 tls opt_state->pzOptArg = NULL;
523 1.1 kardel else {
524 1.2.6.1 tls AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg");
525 1.2.6.1 tls opt_state->flags |= OPTST_ALLOC_ARG;
526 1.1 kardel }
527 1.1 kardel
528 1.1 kardel } else {
529 1.2.6.1 tls if (*opt_state->pzOptArg == NUL)
530 1.2.6.1 tls opt_state->pzOptArg = zNil;
531 1.1 kardel else {
532 1.2.6.1 tls AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg");
533 1.2.6.1 tls opt_state->flags |= OPTST_ALLOC_ARG;
534 1.1 kardel }
535 1.1 kardel }
536 1.1 kardel
537 1.1 kardel {
538 1.1 kardel tOptionLoadMode sv = option_load_mode;
539 1.1 kardel option_load_mode = load_mode;
540 1.2.6.1 tls handle_opt(opts, opt_state);
541 1.1 kardel option_load_mode = sv;
542 1.1 kardel }
543 1.1 kardel }
544 1.1 kardel
545 1.1 kardel /*=export_func optionLoadLine
546 1.1 kardel *
547 1.1 kardel * what: process a string for an option name and value
548 1.1 kardel *
549 1.2.6.1 tls * arg: tOptions*, opts, program options descriptor
550 1.2.6.1 tls * arg: char const*, line, NUL-terminated text
551 1.1 kardel *
552 1.1 kardel * doc:
553 1.1 kardel *
554 1.1 kardel * This is a client program callable routine for setting options from, for
555 1.1 kardel * example, the contents of a file that they read in. Only one option may
556 1.1 kardel * appear in the text. It will be treated as a normal (non-preset) option.
557 1.1 kardel *
558 1.1 kardel * When passed a pointer to the option struct and a string, it will find
559 1.1 kardel * the option named by the first token on the string and set the option
560 1.1 kardel * argument to the remainder of the string. The caller must NUL terminate
561 1.2.6.1 tls * the string. The caller need not skip over any introductory hyphens.
562 1.2.6.1 tls * Any embedded new lines will be included in the option
563 1.1 kardel * argument. If the input looks like one or more quoted strings, then the
564 1.1 kardel * input will be "cooked". The "cooking" is identical to the string
565 1.1 kardel * formation used in AutoGen definition files (@pxref{basic expression}),
566 1.1 kardel * except that you may not use backquotes.
567 1.1 kardel *
568 1.1 kardel * err: Invalid options are silently ignored. Invalid option arguments
569 1.1 kardel * will cause a warning to print, but the function should return.
570 1.1 kardel =*/
571 1.1 kardel void
572 1.2.6.1 tls optionLoadLine(tOptions * opts, char const * line)
573 1.1 kardel {
574 1.1 kardel tOptState st = OPTSTATE_INITIALIZER(SET);
575 1.2.6.1 tls char * pz;
576 1.2.6.1 tls proc_state_mask_t sv_flags = opts->fOptSet;
577 1.2.6.1 tls opts->fOptSet &= ~OPTPROC_ERRSTOP;
578 1.2.6.1 tls AGDUPSTR(pz, line, "opt line");
579 1.2.6.1 tls load_opt_line(opts, &st, pz, DIRECTION_CALLED, OPTION_LOAD_COOKED);
580 1.2 christos AGFREE(pz);
581 1.2.6.1 tls opts->fOptSet = sv_flags;
582 1.1 kardel }
583 1.2.6.1 tls /** @}
584 1.2.6.1 tls *
585 1.1 kardel * Local Variables:
586 1.1 kardel * mode: C
587 1.1 kardel * c-file-style: "stroustrup"
588 1.1 kardel * indent-tabs-mode: nil
589 1.1 kardel * End:
590 1.1 kardel * end of autoopts/load.c */
591