1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino * Copyright (c) 1997, 1998
3*86d7f5d3SJohn Marino * Nan Yang Computer Services Limited. All rights reserved.
4*86d7f5d3SJohn Marino *
5*86d7f5d3SJohn Marino * This software is distributed under the so-called ``Berkeley
6*86d7f5d3SJohn Marino * License'':
7*86d7f5d3SJohn Marino *
8*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
9*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
10*86d7f5d3SJohn Marino * are met:
11*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
12*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
13*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
14*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
15*86d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
16*86d7f5d3SJohn Marino * 3. Neither the name of the Company nor the names of its contributors
17*86d7f5d3SJohn Marino * may be used to endorse or promote products derived from this software
18*86d7f5d3SJohn Marino * without specific prior written permission.
19*86d7f5d3SJohn Marino *
20*86d7f5d3SJohn Marino * This software is provided ``as is'', and any express or implied
21*86d7f5d3SJohn Marino * warranties, including, but not limited to, the implied warranties of
22*86d7f5d3SJohn Marino * merchantability and fitness for a particular purpose are disclaimed.
23*86d7f5d3SJohn Marino * In no event shall the company or contributors be liable for any
24*86d7f5d3SJohn Marino * direct, indirect, incidental, special, exemplary, or consequential
25*86d7f5d3SJohn Marino * damages (including, but not limited to, procurement of substitute
26*86d7f5d3SJohn Marino * goods or services; loss of use, data, or profits; or business
27*86d7f5d3SJohn Marino * interruption) however caused and on any theory of liability, whether
28*86d7f5d3SJohn Marino * in contract, strict liability, or tort (including negligence or
29*86d7f5d3SJohn Marino * otherwise) arising in any way out of the use of this software, even if
30*86d7f5d3SJohn Marino * advised of the possibility of such damage.
31*86d7f5d3SJohn Marino *
32*86d7f5d3SJohn Marino * $Id: vinumparser.c,v 1.21 2000/12/20 03:44:13 grog Exp grog $
33*86d7f5d3SJohn Marino * $FreeBSD: src/sys/dev/vinum/vinumparser.c,v 1.20.2.5 2001/05/28 05:56:27 grog Exp $
34*86d7f5d3SJohn Marino * $DragonFly: src/sbin/vinum/vinumparser.c,v 1.8 2007/01/20 19:20:39 dillon Exp $
35*86d7f5d3SJohn Marino */
36*86d7f5d3SJohn Marino
37*86d7f5d3SJohn Marino /*
38*86d7f5d3SJohn Marino * This file contains the parser for the configuration routines. It's used
39*86d7f5d3SJohn Marino * both in the kernel and in the user interface program, thus the separate file.
40*86d7f5d3SJohn Marino */
41*86d7f5d3SJohn Marino
42*86d7f5d3SJohn Marino /*
43*86d7f5d3SJohn Marino * Go through a text and split up into text tokens. These are either non-blank
44*86d7f5d3SJohn Marino * sequences, or any sequence (except \0) enclosed in ' or ". Embedded ' or
45*86d7f5d3SJohn Marino * " characters may be escaped by \, which otherwise has no special meaning.
46*86d7f5d3SJohn Marino *
47*86d7f5d3SJohn Marino * Delimit by following with a \0, and return pointers to the starts at token [].
48*86d7f5d3SJohn Marino * Return the number of tokens found as the return value.
49*86d7f5d3SJohn Marino *
50*86d7f5d3SJohn Marino * This method has the restriction that a closing " or ' must be followed by
51*86d7f5d3SJohn Marino * grey space.
52*86d7f5d3SJohn Marino *
53*86d7f5d3SJohn Marino * Error conditions are end of line before end of quote, or no space after
54*86d7f5d3SJohn Marino * a closing quote. In this case, tokenize() returns -1.
55*86d7f5d3SJohn Marino */
56*86d7f5d3SJohn Marino
57*86d7f5d3SJohn Marino #include <sys/param.h>
58*86d7f5d3SJohn Marino #include <dev/raid/vinum/vinumkw.h>
59*86d7f5d3SJohn Marino #include <ctype.h>
60*86d7f5d3SJohn Marino #include <errno.h>
61*86d7f5d3SJohn Marino #include <fcntl.h>
62*86d7f5d3SJohn Marino #include <string.h>
63*86d7f5d3SJohn Marino #define iswhite isspace /* use the ctype macro */
64*86d7f5d3SJohn Marino
65*86d7f5d3SJohn Marino /* enum keyword is defined in vinumvar.h */
66*86d7f5d3SJohn Marino
67*86d7f5d3SJohn Marino #define keypair(x) { #x, kw_##x } /* create pair "foo", kw_foo */
68*86d7f5d3SJohn Marino #define flagkeypair(x) { "-"#x, kw_##x } /* create pair "-foo", kw_foo */
69*86d7f5d3SJohn Marino #define KEYWORDSET(x) {sizeof (x) / sizeof (struct _keywords), x}
70*86d7f5d3SJohn Marino
71*86d7f5d3SJohn Marino /* Normal keywords. These are all the words that vinum knows. */
72*86d7f5d3SJohn Marino struct _keywords keywords[] =
73*86d7f5d3SJohn Marino {keypair(drive),
74*86d7f5d3SJohn Marino keypair(partition),
75*86d7f5d3SJohn Marino keypair(sd),
76*86d7f5d3SJohn Marino keypair(subdisk),
77*86d7f5d3SJohn Marino keypair(plex),
78*86d7f5d3SJohn Marino keypair(volume),
79*86d7f5d3SJohn Marino keypair(vol),
80*86d7f5d3SJohn Marino keypair(setupstate),
81*86d7f5d3SJohn Marino keypair(readpol),
82*86d7f5d3SJohn Marino keypair(org),
83*86d7f5d3SJohn Marino keypair(name),
84*86d7f5d3SJohn Marino keypair(writethrough),
85*86d7f5d3SJohn Marino keypair(writeback),
86*86d7f5d3SJohn Marino keypair(raw),
87*86d7f5d3SJohn Marino keypair(device),
88*86d7f5d3SJohn Marino keypair(concat),
89*86d7f5d3SJohn Marino keypair(raid4),
90*86d7f5d3SJohn Marino keypair(raid5),
91*86d7f5d3SJohn Marino keypair(striped),
92*86d7f5d3SJohn Marino keypair(plexoffset),
93*86d7f5d3SJohn Marino keypair(driveoffset),
94*86d7f5d3SJohn Marino keypair(length),
95*86d7f5d3SJohn Marino keypair(len),
96*86d7f5d3SJohn Marino keypair(size),
97*86d7f5d3SJohn Marino keypair(state),
98*86d7f5d3SJohn Marino keypair(round),
99*86d7f5d3SJohn Marino keypair(prefer),
100*86d7f5d3SJohn Marino keypair(rename),
101*86d7f5d3SJohn Marino keypair(detached),
102*86d7f5d3SJohn Marino #ifdef VINUMDEBUG
103*86d7f5d3SJohn Marino keypair(debug),
104*86d7f5d3SJohn Marino #endif
105*86d7f5d3SJohn Marino keypair(stripe),
106*86d7f5d3SJohn Marino keypair(mirror),
107*86d7f5d3SJohn Marino keypair(attach),
108*86d7f5d3SJohn Marino keypair(detach),
109*86d7f5d3SJohn Marino keypair(printconfig),
110*86d7f5d3SJohn Marino keypair(saveconfig),
111*86d7f5d3SJohn Marino keypair(replace),
112*86d7f5d3SJohn Marino keypair(create),
113*86d7f5d3SJohn Marino keypair(read),
114*86d7f5d3SJohn Marino keypair(modify),
115*86d7f5d3SJohn Marino keypair(list),
116*86d7f5d3SJohn Marino keypair(l),
117*86d7f5d3SJohn Marino keypair(ld),
118*86d7f5d3SJohn Marino keypair(ls),
119*86d7f5d3SJohn Marino keypair(lp),
120*86d7f5d3SJohn Marino keypair(lv),
121*86d7f5d3SJohn Marino keypair(info),
122*86d7f5d3SJohn Marino keypair(set),
123*86d7f5d3SJohn Marino keypair(rm),
124*86d7f5d3SJohn Marino keypair(mv),
125*86d7f5d3SJohn Marino keypair(move),
126*86d7f5d3SJohn Marino keypair(init),
127*86d7f5d3SJohn Marino keypair(label),
128*86d7f5d3SJohn Marino keypair(resetconfig),
129*86d7f5d3SJohn Marino keypair(start),
130*86d7f5d3SJohn Marino keypair(stop),
131*86d7f5d3SJohn Marino keypair(makedev),
132*86d7f5d3SJohn Marino keypair(help),
133*86d7f5d3SJohn Marino keypair(quit),
134*86d7f5d3SJohn Marino keypair(setdaemon),
135*86d7f5d3SJohn Marino keypair(getdaemon),
136*86d7f5d3SJohn Marino keypair(max),
137*86d7f5d3SJohn Marino keypair(replace),
138*86d7f5d3SJohn Marino keypair(readpol),
139*86d7f5d3SJohn Marino keypair(resetstats),
140*86d7f5d3SJohn Marino keypair(setstate),
141*86d7f5d3SJohn Marino keypair(checkparity),
142*86d7f5d3SJohn Marino keypair(rebuildparity),
143*86d7f5d3SJohn Marino keypair(dumpconfig),
144*86d7f5d3SJohn Marino keypair(retryerrors)
145*86d7f5d3SJohn Marino };
146*86d7f5d3SJohn Marino struct keywordset keyword_set = KEYWORDSET(keywords);
147*86d7f5d3SJohn Marino
148*86d7f5d3SJohn Marino struct _keywords flag_keywords[] =
149*86d7f5d3SJohn Marino {flagkeypair(f),
150*86d7f5d3SJohn Marino flagkeypair(d),
151*86d7f5d3SJohn Marino flagkeypair(v),
152*86d7f5d3SJohn Marino flagkeypair(s),
153*86d7f5d3SJohn Marino flagkeypair(r),
154*86d7f5d3SJohn Marino flagkeypair(w)
155*86d7f5d3SJohn Marino };
156*86d7f5d3SJohn Marino struct keywordset flag_set = KEYWORDSET(flag_keywords);
157*86d7f5d3SJohn Marino
158*86d7f5d3SJohn Marino /*
159*86d7f5d3SJohn Marino * Take a blank separated list of tokens and turn it into a list of
160*86d7f5d3SJohn Marino * individual nul-delimited strings. Build a list of pointers at
161*86d7f5d3SJohn Marino * token, which must have enough space for the tokens. Return the
162*86d7f5d3SJohn Marino * number of tokens, or -1 on error (typically a missing string
163*86d7f5d3SJohn Marino * delimiter).
164*86d7f5d3SJohn Marino */
165*86d7f5d3SJohn Marino int
tokenize(char * cptr,char * token[])166*86d7f5d3SJohn Marino tokenize(char *cptr, char *token[])
167*86d7f5d3SJohn Marino {
168*86d7f5d3SJohn Marino char delim; /* delimiter for searching for the partner */
169*86d7f5d3SJohn Marino int tokennr; /* index of this token */
170*86d7f5d3SJohn Marino tokennr = 0; /* none found yet */
171*86d7f5d3SJohn Marino
172*86d7f5d3SJohn Marino for (;;) {
173*86d7f5d3SJohn Marino while (iswhite(*cptr))
174*86d7f5d3SJohn Marino cptr++; /* skip initial white space */
175*86d7f5d3SJohn Marino if ((*cptr == '\0') || (*cptr == '\n') || (*cptr == '#')) /* end of line */
176*86d7f5d3SJohn Marino return tokennr; /* return number of tokens found */
177*86d7f5d3SJohn Marino delim = *cptr;
178*86d7f5d3SJohn Marino token[tokennr] = cptr; /* point to it */
179*86d7f5d3SJohn Marino tokennr++; /* one more */
180*86d7f5d3SJohn Marino /* XXX this is broken. It leaves superfluous \\ characters in the text */
181*86d7f5d3SJohn Marino if ((delim == '\'') || (delim == '"')) { /* delimitered */
182*86d7f5d3SJohn Marino for (;;) {
183*86d7f5d3SJohn Marino cptr++;
184*86d7f5d3SJohn Marino if ((*cptr == delim) && (cptr[-1] != '\\')) { /* found the partner */
185*86d7f5d3SJohn Marino cptr++; /* move on past */
186*86d7f5d3SJohn Marino if (!iswhite(*cptr)) /* error, no space after closing quote */
187*86d7f5d3SJohn Marino return -1;
188*86d7f5d3SJohn Marino *cptr++ = '\0'; /* delimit */
189*86d7f5d3SJohn Marino } else if ((*cptr == '\0') || (*cptr == '\n')) /* end of line */
190*86d7f5d3SJohn Marino return -1;
191*86d7f5d3SJohn Marino }
192*86d7f5d3SJohn Marino } else { /* not quoted */
193*86d7f5d3SJohn Marino while ((*cptr != '\0') && (!iswhite(*cptr)) && (*cptr != '\n'))
194*86d7f5d3SJohn Marino cptr++;
195*86d7f5d3SJohn Marino if (*cptr != '\0') /* not end of the line, */
196*86d7f5d3SJohn Marino *cptr++ = '\0'; /* delimit and move to the next */
197*86d7f5d3SJohn Marino }
198*86d7f5d3SJohn Marino }
199*86d7f5d3SJohn Marino }
200*86d7f5d3SJohn Marino
201*86d7f5d3SJohn Marino /* Find a keyword and return an index */
202*86d7f5d3SJohn Marino enum keyword
get_keyword(char * name,struct keywordset * keywordset)203*86d7f5d3SJohn Marino get_keyword(char *name, struct keywordset *keywordset)
204*86d7f5d3SJohn Marino {
205*86d7f5d3SJohn Marino int i;
206*86d7f5d3SJohn Marino struct _keywords *keywords = keywordset->k; /* point to the keywords */
207*86d7f5d3SJohn Marino if (name != NULL) { /* parameter exists */
208*86d7f5d3SJohn Marino for (i = 0; i < keywordset->size; i++)
209*86d7f5d3SJohn Marino if (!strcmp(name, keywords[i].name))
210*86d7f5d3SJohn Marino return (enum keyword) keywords[i].keyword;
211*86d7f5d3SJohn Marino }
212*86d7f5d3SJohn Marino return kw_invalid_keyword;
213*86d7f5d3SJohn Marino }
214