xref: /minix3/minix/lib/libsys/optset.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 /* This file provides functionality to parse strings of comma-separated
2  * options, each being either a single key name or a key=value pair, where the
3  * value may be enclosed in quotes. A table of optset entries is provided to
4  * determine which options are recognized, how to parse their values, and where
5  * to store those. Unrecognized options are silently ignored; improperly
6  * formatted options are silently set to reasonably acceptable values.
7  *
8  * The entry points into this file are:
9  *   optset_parse	parse the given options string using the given table
10  *
11  * Created:
12  *   May 2009 (D.C. van Moolenbroek)
13  */
14 
15 #include <stdlib.h>
16 #include <string.h>
17 #include <minix/config.h>
18 #include <minix/const.h>
19 #include <minix/optset.h>
20 
21 static void optset_parse_entry(struct optset *entry, char *ptr, int len);
22 
23 /*===========================================================================*
24  *				optset_parse_entry			     *
25  *===========================================================================*/
optset_parse_entry(struct optset * entry,char * ptr,int len)26 static void optset_parse_entry(struct optset *entry, char *ptr, int len)
27 {
28 /* Parse and store the value of a single option.
29  */
30   char *dst;
31   int val;
32 
33   switch (entry->os_type) {
34   case OPT_BOOL:
35 	*((int *) entry->os_ptr) = entry->os_val;
36 
37 	break;
38 
39   case OPT_STRING:
40 	if (len >= entry->os_val)
41 		len = entry->os_val - 1;
42 
43 	dst = (char *) entry->os_ptr;
44 
45 	if (len > 0)
46 		memcpy(dst, ptr, len);
47 	dst[len] = 0;
48 
49 	break;
50 
51   case OPT_INT:
52 	if (len > 0)
53 		val = (int) strtoul(ptr, NULL, entry->os_val);
54 	else
55 		val = 0;
56 
57 	*((int *) entry->os_ptr) = val;
58 
59 	break;
60   }
61 }
62 
63 /*===========================================================================*
64  *				optset_parse				     *
65  *===========================================================================*/
optset_parse(struct optset * table,char * string)66 void optset_parse(struct optset *table, char *string)
67 {
68 /* Parse a string of options, using the provided table of optset entries.
69  */
70   char *p, *kptr, *vptr;
71   int i, klen, vlen;
72 
73   for (p = string; *p; ) {
74 	/* Get the key name for the field. */
75 	for (kptr = p, klen = 0; *p && *p != '=' && *p != ','; p++, klen++);
76 
77 	if (*p == '=') {
78 		/* The field has an associated value. */
79 		vptr = ++p;
80 
81 		/* If the first character after the '=' is a quote character,
82 		 * find a matching quote character followed by either a comma
83 		 * or the terminating null character, and use the string in
84 		 * between. Otherwise, use the string up to the next comma or
85 		 * the terminating null character.
86 		 */
87 		if (*p == '\'' || *p == '"') {
88 			p++;
89 
90 			for (vlen = 0; *p && (*p != *vptr ||
91 				(p[1] && p[1] != ',')); p++, vlen++);
92 
93 			if (*p) p++;
94 			vptr++;
95 		}
96 		else
97 			for (vlen = 0; *p && *p != ','; p++, vlen++);
98 	}
99 	else {
100 		vptr = NULL;
101 		vlen = 0;
102 	}
103 
104 	if (*p == ',') p++;
105 
106 	/* Find a matching entry for this key in the given table. If found,
107 	 * call optset_parse_entry() on it. Silently ignore the option
108 	 * otherwise.
109 	 */
110 	for (i = 0; table[i].os_name != NULL; i++) {
111 		if ((int) strlen(table[i].os_name) == klen &&
112 			!strncasecmp(table[i].os_name, kptr, klen)) {
113 
114 			optset_parse_entry(&table[i], vptr, vlen);
115 
116 			break;
117 		}
118 	}
119   }
120 }
121