17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*b493790cSbasabi * Common Development and Distribution License (the "License"). 6*b493790cSbasabi * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2178eb75caSchin 227c478bd9Sstevel@tonic-gate /* 23*b493790cSbasabi * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2478eb75caSchin * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 2978eb75caSchin /* 3078eb75caSchin * logadm/conf.c -- configuration file module 3178eb75caSchin */ 3278eb75caSchin 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <libintl.h> 357c478bd9Sstevel@tonic-gate #include <fcntl.h> 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/mman.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <strings.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include <stdlib.h> 437c478bd9Sstevel@tonic-gate #include "err.h" 447c478bd9Sstevel@tonic-gate #include "lut.h" 457c478bd9Sstevel@tonic-gate #include "fn.h" 467c478bd9Sstevel@tonic-gate #include "opts.h" 477c478bd9Sstevel@tonic-gate #include "conf.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* forward declarations of functions private to this module */ 507c478bd9Sstevel@tonic-gate static void fillconflist(int lineno, const char *entry, char **args, 517c478bd9Sstevel@tonic-gate struct opts *opts, const char *com, int flags); 527c478bd9Sstevel@tonic-gate static void fillargs(char *arg); 537c478bd9Sstevel@tonic-gate static char *nexttok(char **ptrptr); 547c478bd9Sstevel@tonic-gate static void conf_print(FILE *stream); 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate static const char *Confname; /* name of the confile file */ 577c478bd9Sstevel@tonic-gate static char *Confbuf; /* copy of the config file (a la mmap()) */ 587c478bd9Sstevel@tonic-gate static int Conflen; /* length of mmap'd area */ 597c478bd9Sstevel@tonic-gate static int Conffd = -1; /* file descriptor for config file */ 607c478bd9Sstevel@tonic-gate static boolean_t Confchanged; /* true if we need to write changes back */ 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * our structured representation of the configuration file 647c478bd9Sstevel@tonic-gate * is made up of a list of these 657c478bd9Sstevel@tonic-gate */ 6678eb75caSchin struct confinfo { 677c478bd9Sstevel@tonic-gate struct confinfo *cf_next; 687c478bd9Sstevel@tonic-gate int cf_lineno; /* line number in file */ 697c478bd9Sstevel@tonic-gate const char *cf_entry; /* name of entry, if line has an entry */ 707c478bd9Sstevel@tonic-gate char **cf_args; /* raw rhs of entry */ 717c478bd9Sstevel@tonic-gate struct opts *cf_opts; /* parsed rhs of entry */ 727c478bd9Sstevel@tonic-gate const char *cf_com; /* any comment text found */ 737c478bd9Sstevel@tonic-gate int cf_flags; 747c478bd9Sstevel@tonic-gate }; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate #define CONFF_DELETED 1 /* entry should be deleted on write back */ 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static struct confinfo *Confinfo; /* the entries in the config file */ 797c478bd9Sstevel@tonic-gate static struct confinfo *Confinfolast; /* end of list */ 807c478bd9Sstevel@tonic-gate static struct lut *Conflut; /* lookup table keyed by entry name */ 817c478bd9Sstevel@tonic-gate static struct fn_list *Confentries; /* list of valid entry names */ 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* allocate & fill in another entry in our list */ 847c478bd9Sstevel@tonic-gate static void 857c478bd9Sstevel@tonic-gate fillconflist(int lineno, const char *entry, char **args, 867c478bd9Sstevel@tonic-gate struct opts *opts, const char *com, int flags) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate struct confinfo *cp = MALLOC(sizeof (*cp)); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate cp->cf_next = NULL; 917c478bd9Sstevel@tonic-gate cp->cf_lineno = lineno; 927c478bd9Sstevel@tonic-gate cp->cf_entry = entry; 937c478bd9Sstevel@tonic-gate cp->cf_args = args; 947c478bd9Sstevel@tonic-gate cp->cf_opts = opts; 957c478bd9Sstevel@tonic-gate cp->cf_com = com; 967c478bd9Sstevel@tonic-gate cp->cf_flags = flags; 97*b493790cSbasabi if (entry != NULL) { 987c478bd9Sstevel@tonic-gate Conflut = lut_add(Conflut, entry, cp); 997c478bd9Sstevel@tonic-gate fn_list_adds(Confentries, entry); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate if (Confinfo == NULL) 1027c478bd9Sstevel@tonic-gate Confinfo = Confinfolast = cp; 1037c478bd9Sstevel@tonic-gate else { 1047c478bd9Sstevel@tonic-gate Confinfolast->cf_next = cp; 1057c478bd9Sstevel@tonic-gate Confinfolast = cp; 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate static char **Args; /* static buffer for args */ 1107c478bd9Sstevel@tonic-gate static int ArgsN; /* size of our static buffer */ 1117c478bd9Sstevel@tonic-gate static int ArgsI; /* index into Cmdargs as we walk table */ 1127c478bd9Sstevel@tonic-gate #define CONF_ARGS_INC 1024 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* callback for lut_walk to build a cmdargs vector */ 1157c478bd9Sstevel@tonic-gate static void 1167c478bd9Sstevel@tonic-gate fillargs(char *arg) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate if (ArgsI >= ArgsN) { 1197c478bd9Sstevel@tonic-gate /* need bigger table */ 1207c478bd9Sstevel@tonic-gate Args = REALLOC(Args, sizeof (char *) * (ArgsN + CONF_ARGS_INC)); 1217c478bd9Sstevel@tonic-gate ArgsN += CONF_ARGS_INC; 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate Args[ArgsI++] = arg; 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* isolate and return the next token */ 1277c478bd9Sstevel@tonic-gate static char * 1287c478bd9Sstevel@tonic-gate nexttok(char **ptrptr) 1297c478bd9Sstevel@tonic-gate { 1307c478bd9Sstevel@tonic-gate char *ptr = *ptrptr; 1317c478bd9Sstevel@tonic-gate char *eptr; 1327c478bd9Sstevel@tonic-gate char *quote = NULL; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate while (*ptr && isspace(*ptr)) 1357c478bd9Sstevel@tonic-gate ptr++; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate if (*ptr == '"' || *ptr == '\'') 1387c478bd9Sstevel@tonic-gate quote = ptr++; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate for (eptr = ptr; *eptr; eptr++) 1417c478bd9Sstevel@tonic-gate if (quote && *eptr == *quote) { 1427c478bd9Sstevel@tonic-gate /* found end quote */ 1437c478bd9Sstevel@tonic-gate *eptr++ = '\0'; 1447c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1457c478bd9Sstevel@tonic-gate return (ptr); 1467c478bd9Sstevel@tonic-gate } else if (!quote && isspace(*eptr)) { 1477c478bd9Sstevel@tonic-gate /* found end of unquoted area */ 1487c478bd9Sstevel@tonic-gate *eptr++ = '\0'; 1497c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1507c478bd9Sstevel@tonic-gate return (ptr); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 153*b493790cSbasabi if (quote != NULL) 1547c478bd9Sstevel@tonic-gate err(EF_FILE|EF_JMP, "Unbalanced %c quote", *quote); 1557c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate if (ptr == eptr) 1607c478bd9Sstevel@tonic-gate return (NULL); 1617c478bd9Sstevel@tonic-gate else 1627c478bd9Sstevel@tonic-gate return (ptr); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * conf_open -- open the configuration file, lock it if we have write perms 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate void 1697c478bd9Sstevel@tonic-gate conf_open(const char *fname, int needwrite) 1707c478bd9Sstevel@tonic-gate { 1717c478bd9Sstevel@tonic-gate struct stat stbuf; 1727c478bd9Sstevel@tonic-gate int lineno = 0; 1737c478bd9Sstevel@tonic-gate char *line; 1747c478bd9Sstevel@tonic-gate char *eline; 1757c478bd9Sstevel@tonic-gate char *ebuf; 1767c478bd9Sstevel@tonic-gate char *comment; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate Confname = fname; 1797c478bd9Sstevel@tonic-gate Confentries = fn_list_new(NULL); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* special case this so we don't even try locking the file */ 1827c478bd9Sstevel@tonic-gate if (strcmp(Confname, "/dev/null") == 0) 1837c478bd9Sstevel@tonic-gate return; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if ((Conffd = open(Confname, (needwrite) ? O_RDWR : O_RDONLY)) < 0) 1867c478bd9Sstevel@tonic-gate err(EF_SYS, "%s", Confname); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (fstat(Conffd, &stbuf) < 0) 1897c478bd9Sstevel@tonic-gate err(EF_SYS, "fstat on %s", Confname); 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate if (needwrite && lockf(Conffd, F_LOCK, 0) < 0) 1927c478bd9Sstevel@tonic-gate err(EF_SYS, "lockf on %s", Confname); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (stbuf.st_size == 0) 1957c478bd9Sstevel@tonic-gate return; /* empty file, don't bother parsing it */ 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if ((Confbuf = (char *)mmap(0, stbuf.st_size, 1987c478bd9Sstevel@tonic-gate PROT_READ | PROT_WRITE, MAP_PRIVATE, Conffd, 0)) == (char *)-1) 1997c478bd9Sstevel@tonic-gate err(EF_SYS, "mmap on %s", Confname); 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate Conflen = stbuf.st_size; 2027c478bd9Sstevel@tonic-gate Confchanged = B_FALSE; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate ebuf = &Confbuf[Conflen]; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (Confbuf[Conflen - 1] != '\n') 2077c478bd9Sstevel@tonic-gate err(EF_WARN|EF_FILE, "config file doesn't end with " 2087c478bd9Sstevel@tonic-gate "newline, last line ignored."); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate line = Confbuf; 2117c478bd9Sstevel@tonic-gate while (line < ebuf) { 2127c478bd9Sstevel@tonic-gate lineno++; 2137c478bd9Sstevel@tonic-gate err_fileline(Confname, lineno); 2147c478bd9Sstevel@tonic-gate eline = line; 2157c478bd9Sstevel@tonic-gate comment = NULL; 2167c478bd9Sstevel@tonic-gate for (; eline < ebuf; eline++) { 2177c478bd9Sstevel@tonic-gate /* check for continued lines */ 2187c478bd9Sstevel@tonic-gate if (comment == NULL && *eline == '\\' && 2197c478bd9Sstevel@tonic-gate eline + 1 < ebuf && *(eline + 1) == '\n') { 2207c478bd9Sstevel@tonic-gate *eline = ' '; 2217c478bd9Sstevel@tonic-gate *(eline + 1) = ' '; 2227c478bd9Sstevel@tonic-gate lineno++; 2237c478bd9Sstevel@tonic-gate err_fileline(Confname, lineno); 2247c478bd9Sstevel@tonic-gate continue; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* check for comments */ 2287c478bd9Sstevel@tonic-gate if (comment == NULL && *eline == '#') { 2297c478bd9Sstevel@tonic-gate *eline = '\0'; 2307c478bd9Sstevel@tonic-gate comment = (eline + 1); 2317c478bd9Sstevel@tonic-gate continue; 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* check for end of line */ 2357c478bd9Sstevel@tonic-gate if (*eline == '\n') 2367c478bd9Sstevel@tonic-gate break; 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate if (comment >= ebuf) 2397c478bd9Sstevel@tonic-gate comment = NULL; 2407c478bd9Sstevel@tonic-gate if (eline < ebuf) { 2417c478bd9Sstevel@tonic-gate char *entry; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate *eline++ = '\0'; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * now we have the entry, if any, at "line" 2477c478bd9Sstevel@tonic-gate * and the comment, if any, at "comment" 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* entry is first token */ 2517c478bd9Sstevel@tonic-gate if ((entry = nexttok(&line)) != NULL && 2527c478bd9Sstevel@tonic-gate strcmp(entry, "logadm-version") == 0) { 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * we somehow opened some future format 2557c478bd9Sstevel@tonic-gate * conffile that we likely don't understand. 2567c478bd9Sstevel@tonic-gate * if the given version is "1" then go on, 2577c478bd9Sstevel@tonic-gate * otherwise someone is mixing versions 2587c478bd9Sstevel@tonic-gate * and we can't help them other than to 2597c478bd9Sstevel@tonic-gate * print an error and exit. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate if ((entry = nexttok(&line)) != NULL && 2627c478bd9Sstevel@tonic-gate strcmp(entry, "1") != 0) 2637c478bd9Sstevel@tonic-gate err(0, "%s version not " 2647c478bd9Sstevel@tonic-gate "supported by " 2657c478bd9Sstevel@tonic-gate "this version of logadm.", 2667c478bd9Sstevel@tonic-gate Confname); 2677c478bd9Sstevel@tonic-gate } else if (entry) { 2687c478bd9Sstevel@tonic-gate char *ap; 2697c478bd9Sstevel@tonic-gate char **args; 2707c478bd9Sstevel@tonic-gate int i; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate ArgsI = 0; 2737c478bd9Sstevel@tonic-gate while (ap = nexttok(&line)) 2747c478bd9Sstevel@tonic-gate fillargs(ap); 2757c478bd9Sstevel@tonic-gate if (ArgsI == 0) { 2767c478bd9Sstevel@tonic-gate /* short entry allowed */ 2777c478bd9Sstevel@tonic-gate fillconflist(lineno, entry, 2787c478bd9Sstevel@tonic-gate NULL, NULL, comment, 0); 2797c478bd9Sstevel@tonic-gate } else { 2807c478bd9Sstevel@tonic-gate Args[ArgsI++] = NULL; 2817c478bd9Sstevel@tonic-gate args = MALLOC(sizeof (char *) * ArgsI); 2827c478bd9Sstevel@tonic-gate for (i = 0; i < ArgsI; i++) 2837c478bd9Sstevel@tonic-gate args[i] = Args[i]; 2847c478bd9Sstevel@tonic-gate fillconflist(lineno, entry, 2857c478bd9Sstevel@tonic-gate args, NULL, comment, 0); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate } else 2887c478bd9Sstevel@tonic-gate fillconflist(lineno, entry, NULL, NULL, 2897c478bd9Sstevel@tonic-gate comment, 0); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate line = eline; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * possible future enhancement: go through and mark any entries: 2957c478bd9Sstevel@tonic-gate * logfile -P <date> 2967c478bd9Sstevel@tonic-gate * as DELETED if the logfile doesn't exist 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * conf_close -- close the configuration file 3027c478bd9Sstevel@tonic-gate */ 3037c478bd9Sstevel@tonic-gate void 3047c478bd9Sstevel@tonic-gate conf_close(struct opts *opts) 3057c478bd9Sstevel@tonic-gate { 3067c478bd9Sstevel@tonic-gate FILE *fp; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate if (Confchanged && opts_count(opts, "n") == 0 && Conffd != -1) { 3097c478bd9Sstevel@tonic-gate if (opts_count(opts, "v")) 3107c478bd9Sstevel@tonic-gate (void) out("# writing changes to %s\n", Confname); 3117c478bd9Sstevel@tonic-gate if (Debug > 1) { 3127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "conf_close, %s changed to:\n", 3137c478bd9Sstevel@tonic-gate Confname); 3147c478bd9Sstevel@tonic-gate conf_print(stderr); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate if (lseek(Conffd, (off_t)0, SEEK_SET) < 0) 3177c478bd9Sstevel@tonic-gate err(EF_SYS, "lseek on %s", Confname); 3187c478bd9Sstevel@tonic-gate if (ftruncate(Conffd, (off_t)0) < 0) 3197c478bd9Sstevel@tonic-gate err(EF_SYS, "ftruncate on %s", Confname); 3207c478bd9Sstevel@tonic-gate if ((fp = fdopen(Conffd, "w")) == NULL) 3217c478bd9Sstevel@tonic-gate err(EF_SYS, "fdopen on %s", Confname); 3227c478bd9Sstevel@tonic-gate conf_print(fp); 3237c478bd9Sstevel@tonic-gate if (fclose(fp) < 0) 3247c478bd9Sstevel@tonic-gate err(EF_SYS, "fclose on %s", Confname); 3257c478bd9Sstevel@tonic-gate Conffd = -1; 3267c478bd9Sstevel@tonic-gate Confchanged = B_FALSE; 3277c478bd9Sstevel@tonic-gate } else if (opts_count(opts, "v")) { 3287c478bd9Sstevel@tonic-gate (void) out("# %s unchanged\n", Confname); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if (Conffd != -1) { 3327c478bd9Sstevel@tonic-gate (void) close(Conffd); 3337c478bd9Sstevel@tonic-gate Conffd = -1; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate if (Conflut) { 3367c478bd9Sstevel@tonic-gate lut_free(Conflut, free); 3377c478bd9Sstevel@tonic-gate Conflut = NULL; 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate if (Confentries) { 3407c478bd9Sstevel@tonic-gate fn_list_free(Confentries); 3417c478bd9Sstevel@tonic-gate Confentries = NULL; 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* 3467c478bd9Sstevel@tonic-gate * conf_lookup -- lookup an entry in the config file 3477c478bd9Sstevel@tonic-gate */ 3487c478bd9Sstevel@tonic-gate char ** 3497c478bd9Sstevel@tonic-gate conf_lookup(const char *lhs) 3507c478bd9Sstevel@tonic-gate { 3517c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 3527c478bd9Sstevel@tonic-gate 353*b493790cSbasabi if (cp != NULL) { 3547c478bd9Sstevel@tonic-gate err_fileline(Confname, cp->cf_lineno); 3557c478bd9Sstevel@tonic-gate return (cp->cf_args); 3567c478bd9Sstevel@tonic-gate } else 3577c478bd9Sstevel@tonic-gate return (NULL); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* 3617c478bd9Sstevel@tonic-gate * conf_opts -- return the parsed opts for an entry 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate struct opts * 3647c478bd9Sstevel@tonic-gate conf_opts(const char *lhs) 3657c478bd9Sstevel@tonic-gate { 3667c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 3677c478bd9Sstevel@tonic-gate 368*b493790cSbasabi if (cp != NULL) { 3697c478bd9Sstevel@tonic-gate if (cp->cf_opts) 3707c478bd9Sstevel@tonic-gate return (cp->cf_opts); /* already parsed */ 3717c478bd9Sstevel@tonic-gate err_fileline(Confname, cp->cf_lineno); 3727c478bd9Sstevel@tonic-gate cp->cf_opts = opts_parse(cp->cf_args, OPTF_CONF); 3737c478bd9Sstevel@tonic-gate return (cp->cf_opts); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate return (opts_parse(NULL, OPTF_CONF)); 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * conf_replace -- replace an entry in the config file 3807c478bd9Sstevel@tonic-gate */ 3817c478bd9Sstevel@tonic-gate void 3827c478bd9Sstevel@tonic-gate conf_replace(const char *lhs, struct opts *newopts) 3837c478bd9Sstevel@tonic-gate { 3847c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (Conffd == -1) 3877c478bd9Sstevel@tonic-gate return; 3887c478bd9Sstevel@tonic-gate 389*b493790cSbasabi if (cp != NULL) { 3907c478bd9Sstevel@tonic-gate cp->cf_opts = newopts; 3917c478bd9Sstevel@tonic-gate cp->cf_args = NULL; 3927c478bd9Sstevel@tonic-gate if (newopts == NULL) 3937c478bd9Sstevel@tonic-gate cp->cf_flags |= CONFF_DELETED; 3947c478bd9Sstevel@tonic-gate } else 3957c478bd9Sstevel@tonic-gate fillconflist(0, lhs, NULL, newopts, NULL, 0); 3967c478bd9Sstevel@tonic-gate Confchanged = B_TRUE; 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* 4007c478bd9Sstevel@tonic-gate * conf_set -- set options for an entry in the config file 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate void 4037c478bd9Sstevel@tonic-gate conf_set(const char *entry, char *o, const char *optarg) 4047c478bd9Sstevel@tonic-gate { 4057c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, entry); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if (Conffd == -1) 4087c478bd9Sstevel@tonic-gate return; 4097c478bd9Sstevel@tonic-gate 410*b493790cSbasabi if (cp != NULL) { 4117c478bd9Sstevel@tonic-gate if (cp->cf_opts == NULL) 4127c478bd9Sstevel@tonic-gate cp->cf_opts = opts_parse(cp->cf_args, OPTF_CONF); 4137c478bd9Sstevel@tonic-gate cp->cf_flags &= ~CONFF_DELETED; 4147c478bd9Sstevel@tonic-gate } else { 4157c478bd9Sstevel@tonic-gate fillconflist(0, STRDUP(entry), NULL, 4167c478bd9Sstevel@tonic-gate opts_parse(NULL, OPTF_CONF), NULL, 0); 4177c478bd9Sstevel@tonic-gate if ((cp = lut_lookup(Conflut, entry)) == NULL) 4187c478bd9Sstevel@tonic-gate err(0, "conf_set internal error"); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate (void) opts_set(cp->cf_opts, o, optarg); 4217c478bd9Sstevel@tonic-gate Confchanged = B_TRUE; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * conf_entries -- list all the entry names 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate struct fn_list * 4287c478bd9Sstevel@tonic-gate conf_entries(void) 4297c478bd9Sstevel@tonic-gate { 4307c478bd9Sstevel@tonic-gate return (Confentries); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* print the config file */ 4347c478bd9Sstevel@tonic-gate static void 4357c478bd9Sstevel@tonic-gate conf_print(FILE *stream) 4367c478bd9Sstevel@tonic-gate { 4377c478bd9Sstevel@tonic-gate struct confinfo *cp; 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate for (cp = Confinfo; cp; cp = cp->cf_next) { 4407c478bd9Sstevel@tonic-gate if (cp->cf_flags & CONFF_DELETED) 4417c478bd9Sstevel@tonic-gate continue; 4427c478bd9Sstevel@tonic-gate if (cp->cf_entry) { 4437c478bd9Sstevel@tonic-gate char **p; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate opts_printword(cp->cf_entry, stream); 4467c478bd9Sstevel@tonic-gate if (cp->cf_opts) { 4477c478bd9Sstevel@tonic-gate /* existence of opts overrides args */ 4487c478bd9Sstevel@tonic-gate opts_print(cp->cf_opts, stream, "fhnrvVw"); 4497c478bd9Sstevel@tonic-gate } else if (cp->cf_args) { 4507c478bd9Sstevel@tonic-gate for (p = cp->cf_args; *p; p++) { 4517c478bd9Sstevel@tonic-gate (void) fprintf(stream, " "); 4527c478bd9Sstevel@tonic-gate opts_printword(*p, stream); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate if (cp->cf_com) { 4577c478bd9Sstevel@tonic-gate if (cp->cf_entry) 4587c478bd9Sstevel@tonic-gate (void) fprintf(stream, " "); 4597c478bd9Sstevel@tonic-gate (void) fprintf(stream, "#%s", cp->cf_com); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate (void) fprintf(stream, "\n"); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate #ifdef TESTMODULE 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate /* 4687c478bd9Sstevel@tonic-gate * test main for conf module, usage: a.out conffile 4697c478bd9Sstevel@tonic-gate */ 470*b493790cSbasabi int 4717c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 4727c478bd9Sstevel@tonic-gate { 4737c478bd9Sstevel@tonic-gate err_init(argv[0]); 4747c478bd9Sstevel@tonic-gate setbuf(stdout, NULL); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate if (argc != 2) 4777c478bd9Sstevel@tonic-gate err(EF_RAW, "usage: %s conffile\n", argv[0]); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate conf_open(argv[1], 1); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate printf("conffile <%s>:\n", argv[1]); 4827c478bd9Sstevel@tonic-gate conf_print(stdout); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate conf_close(opts_parse(NULL, 0)); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate err_done(0); 487*b493790cSbasabi /* NOTREACHED */ 488*b493790cSbasabi return (0); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate #endif /* TESTMODULE */ 492