1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * Just in case we're not in a build environment, make sure that
30 * TEXT_DOMAIN gets set to something.
31 */
32 #if !defined(TEXT_DOMAIN)
33 #define TEXT_DOMAIN "SYS_TEST"
34 #endif
35
36 #include <meta.h>
37
38 #include <ctype.h>
39
40 /*
41 * free md.tab struct
42 */
43 void
meta_tab_free(md_tab_t * tabp)44 meta_tab_free(
45 md_tab_t *tabp
46 )
47 {
48 size_t line;
49
50 Free(tabp->filename);
51 Free(tabp->data);
52 if (tabp->lines != NULL) {
53 assert(tabp->alloc > 0);
54 for (line = 0; (line < tabp->nlines); ++line) {
55 md_tab_line_t *linep = &tabp->lines[line];
56
57 if (linep->context != NULL)
58 Free(linep->context);
59 if (linep->cname != NULL)
60 Free(linep->cname);
61 if (linep->argv != NULL) {
62 assert(linep->alloc > 0);
63 Free(linep->argv);
64 }
65 }
66 Free(tabp->lines);
67 }
68 Free(tabp);
69 }
70
71 /*
72 * (re)allocate argv array
73 */
74 static void
realloc_argv(md_tab_line_t * linep,size_t argc)75 realloc_argv(
76 md_tab_line_t *linep,
77 size_t argc
78 )
79 {
80 /* allocate in chunks */
81 argc = roundup(argc, TAB_ARG_ALLOC);
82 if (argc < linep->alloc)
83 return;
84
85 /* (re)allocate */
86 if (linep->alloc == 0) {
87 linep->argv = Malloc(argc * sizeof (*linep->argv));
88 } else {
89 assert(linep->argv != NULL);
90 linep->argv =
91 Realloc(linep->argv, (argc * sizeof (*linep->argv)));
92 }
93
94 /* zero out new stuff */
95 (void) memset(&linep->argv[linep->alloc], 0,
96 ((argc - linep->alloc) * sizeof (*linep->argv)));
97
98 /* adjust for new size */
99 linep->alloc = argc;
100 }
101
102 /*
103 * (re)allocate line array
104 */
105 static void
realloc_lines(md_tab_t * tabp,size_t nlines)106 realloc_lines(
107 md_tab_t *tabp,
108 size_t nlines
109 )
110 {
111 /* allocate in chunks */
112 nlines = roundup(nlines, TAB_LINE_ALLOC);
113 if (nlines < tabp->alloc)
114 return;
115
116 /* (re)allocate */
117 if (tabp->alloc == 0) {
118 assert(tabp->lines == NULL);
119 tabp->lines = Malloc(nlines * sizeof (*tabp->lines));
120 } else {
121 assert(tabp->lines != NULL);
122 tabp->lines =
123 Realloc(tabp->lines, (nlines * sizeof (*tabp->lines)));
124 }
125
126 /* zero out new stuff */
127 (void) memset(&tabp->lines[tabp->alloc], 0,
128 ((nlines - tabp->alloc) * sizeof (*tabp->lines)));
129
130 /* adjust for new size */
131 tabp->alloc = nlines;
132 }
133
134 /*
135 * parse up md.tab struct
136 */
137 static void
parse_tab(md_tab_t * tabp,char * metatab_name,md_error_t * ep)138 parse_tab(
139 md_tab_t *tabp,
140 char *metatab_name,
141 md_error_t *ep
142 )
143 {
144 uint_t lineno = 1;
145 char *p = tabp->data;
146 char *e = tabp->data + tabp->total - 1;
147 char *context;
148 size_t len;
149
150 /* we can count on '\n\0' as the last characters */
151 assert(tabp->total >= 2);
152 assert(tabp->data[tabp->total - 2] == '\n');
153 assert(tabp->data[tabp->total - 1] == '\0');
154
155 /* allocate context buffer "file line XXX" */
156 assert(tabp->filename != NULL);
157 len = strlen(tabp->filename) +
158 strlen(dgettext(TEXT_DOMAIN, "%s line %u")) + 20 + 1;
159 context = Malloc(len);
160
161 /* parse lines */
162 while (p < e && *p != '\0') {
163 md_tab_line_t *linep;
164 char *t;
165
166 /* allocate new line */
167 realloc_lines(tabp, (tabp->nlines + 1));
168 linep = &tabp->lines[tabp->nlines];
169 (void) snprintf(context, len,
170 dgettext(TEXT_DOMAIN, "%s line %u"), tabp->filename,
171 lineno);
172
173 /* comments */
174 if (*p == '#') {
175 while (*p != '\n')
176 ++p;
177 }
178
179 /* coalesce \ continuations */
180 t = p;
181 while (*t != '\n') {
182 if ((*t == '\\') && (*(t + 1) == '\n')) {
183 *t++ = ' ';
184 *t = ' ';
185 ++lineno;
186 }
187 ++t;
188 }
189
190 /* leading whitespace */
191 while ((*p != '\n') && (isspace(*p)))
192 ++p;
193
194 /* count lines */
195 if (*p == '\n') {
196 ++p;
197 ++lineno;
198 continue;
199 }
200
201 /* tokenize line */
202 while ((p < e) && (*p != '\n')) {
203 char **argvp;
204
205 /* allocate new token */
206 realloc_argv(linep, (linep->argc + 1));
207 argvp = &linep->argv[linep->argc++];
208
209 /* find end of token */
210 *argvp = p;
211 while ((*p != '\n') && (! isspace(*p)))
212 ++p;
213
214 /* terminate */
215 if (*p == '\n') {
216 *p++ = '\0';
217 ++lineno;
218 break;
219 }
220
221 /* eat white space */
222 *p++ = '\0';
223 while ((p < e) && (*p != '\n') && (isspace(*p)))
224 ++p;
225 }
226 tabp->nlines++;
227
228 /* fill in the rest */
229 assert((linep->argc > 0) && (linep->argv != NULL) &&
230 (linep->argv[0][0] != '\0') &&
231 (! isspace(linep->argv[0][0])));
232 linep->context = Strdup(context);
233 linep->type = meta_get_init_type(linep->argc, linep->argv);
234 linep->cname = meta_canonicalize(NULL, linep->argv[0]);
235 /* if cname is NULL then the meta/hsp name is invalid */
236 if (linep->cname == NULL) {
237 (void) mderror(ep, MDE_SYNTAX, metatab_name);
238 break;
239 }
240 }
241
242 /* cleanup */
243 Free(context);
244 }
245
246 /*
247 * read in md.tab file and return struct
248 */
249 md_tab_t *
meta_tab_parse(char * filename,md_error_t * ep)250 meta_tab_parse(
251 char *filename,
252 md_error_t *ep
253 )
254 {
255 md_tab_t *tabp = NULL;
256 int fd = -1;
257 struct stat statbuf;
258 size_t sofar;
259 char *p;
260
261 /* open tab file */
262 if (filename == NULL)
263 filename = METATAB;
264 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
265 (void) mdsyserror(ep, errno, filename);
266 goto out;
267 }
268 if (fstat(fd, &statbuf) != 0) {
269 (void) mdsyserror(ep, errno, filename);
270 goto out;
271 }
272
273 /* allocate table */
274 tabp = Zalloc(sizeof (*tabp));
275 tabp->filename = Strdup(filename);
276 tabp->total = statbuf.st_size + 2; /* terminating "\n\0" */
277 tabp->data = Malloc(tabp->total);
278
279 /* read in data */
280 sofar = 0;
281 p = tabp->data;
282 while (sofar < statbuf.st_size) {
283 int cnt;
284
285 if ((cnt = read(fd, p, 8192)) < 0) {
286 (void) mdsyserror(ep, errno, filename);
287 goto out;
288 } else if (cnt == 0) {
289 (void) mderror(ep, MDE_SYNTAX, filename);
290 goto out;
291 }
292 sofar += cnt;
293 p += cnt;
294 }
295 tabp->data[tabp->total - 2] = '\n';
296 tabp->data[tabp->total - 1] = '\0';
297
298 /* close file */
299 if (close(fd) != 0) {
300 (void) mdsyserror(ep, errno, filename);
301 fd = -1;
302 goto out;
303 }
304 fd = -1;
305
306 /* parse it up */
307 parse_tab(tabp, filename, ep);
308
309 /* return success if file was correctly parsed */
310 if (mdisok(ep))
311 return (tabp);
312
313 /* cleanup, return error */
314 out:
315 if (fd >= 0)
316 (void) close(fd);
317 if (tabp != NULL)
318 meta_tab_free(tabp);
319 return (NULL);
320 }
321
322 /*
323 * find line in md.tab
324 */
325 md_tab_line_t *
meta_tab_find(mdsetname_t * sp,md_tab_t * tabp,char * name,mdinittypes_t type)326 meta_tab_find(
327 mdsetname_t *sp,
328 md_tab_t *tabp,
329 char *name,
330 mdinittypes_t type
331 )
332 {
333 char *cname = meta_canonicalize(sp, name);
334 size_t line;
335
336 /* if name is not legal meta name then return NULL */
337 if (cname == NULL)
338 return (NULL);
339
340 for (line = 0; (line < tabp->nlines); ++line) {
341 md_tab_line_t *linep = &tabp->lines[line];
342
343 assert((linep->argc > 0) && (linep->argv[0] != NULL));
344 if (((linep->type & type) != 0) &&
345 (strcmp(linep->cname, cname) == 0)) {
346 Free(cname);
347 return (linep);
348 }
349 }
350 Free(cname);
351 return (NULL);
352 }
353