/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * Just in case we're not in a build environment, make sure that * TEXT_DOMAIN gets set to something. */ #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif #include #include /* * free md.tab struct */ void meta_tab_free( md_tab_t *tabp ) { size_t line; Free(tabp->filename); Free(tabp->data); if (tabp->lines != NULL) { assert(tabp->alloc > 0); for (line = 0; (line < tabp->nlines); ++line) { md_tab_line_t *linep = &tabp->lines[line]; if (linep->context != NULL) Free(linep->context); if (linep->cname != NULL) Free(linep->cname); if (linep->argv != NULL) { assert(linep->alloc > 0); Free(linep->argv); } } Free(tabp->lines); } Free(tabp); } /* * (re)allocate argv array */ static void realloc_argv( md_tab_line_t *linep, size_t argc ) { /* allocate in chunks */ argc = roundup(argc, TAB_ARG_ALLOC); if (argc < linep->alloc) return; /* (re)allocate */ if (linep->alloc == 0) { linep->argv = Malloc(argc * sizeof (*linep->argv)); } else { assert(linep->argv != NULL); linep->argv = Realloc(linep->argv, (argc * sizeof (*linep->argv))); } /* zero out new stuff */ (void) memset(&linep->argv[linep->alloc], 0, ((argc - linep->alloc) * sizeof (*linep->argv))); /* adjust for new size */ linep->alloc = argc; } /* * (re)allocate line array */ static void realloc_lines( md_tab_t *tabp, size_t nlines ) { /* allocate in chunks */ nlines = roundup(nlines, TAB_LINE_ALLOC); if (nlines < tabp->alloc) return; /* (re)allocate */ if (tabp->alloc == 0) { assert(tabp->lines == NULL); tabp->lines = Malloc(nlines * sizeof (*tabp->lines)); } else { assert(tabp->lines != NULL); tabp->lines = Realloc(tabp->lines, (nlines * sizeof (*tabp->lines))); } /* zero out new stuff */ (void) memset(&tabp->lines[tabp->alloc], 0, ((nlines - tabp->alloc) * sizeof (*tabp->lines))); /* adjust for new size */ tabp->alloc = nlines; } /* * parse up md.tab struct */ static void parse_tab( md_tab_t *tabp, char *metatab_name, md_error_t *ep ) { uint_t lineno = 1; char *p = tabp->data; char *e = tabp->data + tabp->total - 1; char *context; size_t len; /* we can count on '\n\0' as the last characters */ assert(tabp->total >= 2); assert(tabp->data[tabp->total - 2] == '\n'); assert(tabp->data[tabp->total - 1] == '\0'); /* allocate context buffer "file line XXX" */ assert(tabp->filename != NULL); len = strlen(tabp->filename) + strlen(dgettext(TEXT_DOMAIN, "%s line %u")) + 20 + 1; context = Malloc(len); /* parse lines */ while (p < e && *p != '\0') { md_tab_line_t *linep; char *t; /* allocate new line */ realloc_lines(tabp, (tabp->nlines + 1)); linep = &tabp->lines[tabp->nlines]; (void) snprintf(context, len, dgettext(TEXT_DOMAIN, "%s line %u"), tabp->filename, lineno); /* comments */ if (*p == '#') { while (*p != '\n') ++p; } /* coalesce \ continuations */ t = p; while (*t != '\n') { if ((*t == '\\') && (*(t + 1) == '\n')) { *t++ = ' '; *t = ' '; ++lineno; } ++t; } /* leading whitespace */ while ((*p != '\n') && (isspace(*p))) ++p; /* count lines */ if (*p == '\n') { ++p; ++lineno; continue; } /* tokenize line */ while ((p < e) && (*p != '\n')) { char **argvp; /* allocate new token */ realloc_argv(linep, (linep->argc + 1)); argvp = &linep->argv[linep->argc++]; /* find end of token */ *argvp = p; while ((*p != '\n') && (! isspace(*p))) ++p; /* terminate */ if (*p == '\n') { *p++ = '\0'; ++lineno; break; } /* eat white space */ *p++ = '\0'; while ((p < e) && (*p != '\n') && (isspace(*p))) ++p; } tabp->nlines++; /* fill in the rest */ assert((linep->argc > 0) && (linep->argv != NULL) && (linep->argv[0][0] != '\0') && (! isspace(linep->argv[0][0]))); linep->context = Strdup(context); linep->type = meta_get_init_type(linep->argc, linep->argv); linep->cname = meta_canonicalize(NULL, linep->argv[0]); /* if cname is NULL then the meta/hsp name is invalid */ if (linep->cname == NULL) { (void) mderror(ep, MDE_SYNTAX, metatab_name); break; } } /* cleanup */ Free(context); } /* * read in md.tab file and return struct */ md_tab_t * meta_tab_parse( char *filename, md_error_t *ep ) { md_tab_t *tabp = NULL; int fd = -1; struct stat statbuf; size_t sofar; char *p; /* open tab file */ if (filename == NULL) filename = METATAB; if ((fd = open(filename, O_RDONLY, 0)) < 0) { (void) mdsyserror(ep, errno, filename); goto out; } if (fstat(fd, &statbuf) != 0) { (void) mdsyserror(ep, errno, filename); goto out; } /* allocate table */ tabp = Zalloc(sizeof (*tabp)); tabp->filename = Strdup(filename); tabp->total = statbuf.st_size + 2; /* terminating "\n\0" */ tabp->data = Malloc(tabp->total); /* read in data */ sofar = 0; p = tabp->data; while (sofar < statbuf.st_size) { int cnt; if ((cnt = read(fd, p, 8192)) < 0) { (void) mdsyserror(ep, errno, filename); goto out; } else if (cnt == 0) { (void) mderror(ep, MDE_SYNTAX, filename); goto out; } sofar += cnt; p += cnt; } tabp->data[tabp->total - 2] = '\n'; tabp->data[tabp->total - 1] = '\0'; /* close file */ if (close(fd) != 0) { (void) mdsyserror(ep, errno, filename); fd = -1; goto out; } fd = -1; /* parse it up */ parse_tab(tabp, filename, ep); /* return success if file was correctly parsed */ if (mdisok(ep)) return (tabp); /* cleanup, return error */ out: if (fd >= 0) (void) close(fd); if (tabp != NULL) meta_tab_free(tabp); return (NULL); } /* * find line in md.tab */ md_tab_line_t * meta_tab_find( mdsetname_t *sp, md_tab_t *tabp, char *name, mdinittypes_t type ) { char *cname = meta_canonicalize(sp, name); size_t line; /* if name is not legal meta name then return NULL */ if (cname == NULL) return (NULL); for (line = 0; (line < tabp->nlines); ++line) { md_tab_line_t *linep = &tabp->lines[line]; assert((linep->argc > 0) && (linep->argv[0] != NULL)); if (((linep->type & type) != 0) && (strcmp(linep->cname, cname) == 0)) { Free(cname); return (linep); } } Free(cname); return (NULL); }