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