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