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 5b493790cSbasabi * Common Development and Distribution License (the "License"). 6b493790cSbasabi * 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*e9a193fcSJohn.Zolnowsky@Sun.COM * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 2678eb75caSchin /* 2778eb75caSchin * logadm/conf.c -- configuration file module 2878eb75caSchin */ 2978eb75caSchin 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <libintl.h> 327c478bd9Sstevel@tonic-gate #include <fcntl.h> 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/stat.h> 357c478bd9Sstevel@tonic-gate #include <sys/mman.h> 367c478bd9Sstevel@tonic-gate #include <ctype.h> 377c478bd9Sstevel@tonic-gate #include <strings.h> 387c478bd9Sstevel@tonic-gate #include <unistd.h> 397c478bd9Sstevel@tonic-gate #include <stdlib.h> 40*e9a193fcSJohn.Zolnowsky@Sun.COM #include <limits.h> 417c478bd9Sstevel@tonic-gate #include "err.h" 427c478bd9Sstevel@tonic-gate #include "lut.h" 437c478bd9Sstevel@tonic-gate #include "fn.h" 447c478bd9Sstevel@tonic-gate #include "opts.h" 457c478bd9Sstevel@tonic-gate #include "conf.h" 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* forward declarations of functions private to this module */ 48*e9a193fcSJohn.Zolnowsky@Sun.COM static void fillconflist(int lineno, const char *entry, 497c478bd9Sstevel@tonic-gate struct opts *opts, const char *com, int flags); 507c478bd9Sstevel@tonic-gate static void fillargs(char *arg); 517c478bd9Sstevel@tonic-gate static char *nexttok(char **ptrptr); 52*e9a193fcSJohn.Zolnowsky@Sun.COM static void conf_print(FILE *cstream, FILE *tstream); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static const char *Confname; /* name of the confile file */ 557c478bd9Sstevel@tonic-gate static int Conffd = -1; /* file descriptor for config file */ 56*e9a193fcSJohn.Zolnowsky@Sun.COM static char *Confbuf; /* copy of the config file (a la mmap()) */ 57*e9a193fcSJohn.Zolnowsky@Sun.COM static int Conflen; /* length of mmap'd config file area */ 58*e9a193fcSJohn.Zolnowsky@Sun.COM static const char *Timesname; /* name of the timestamps file */ 59*e9a193fcSJohn.Zolnowsky@Sun.COM static int Timesfd = -1; /* file descriptor for timestamps file */ 60*e9a193fcSJohn.Zolnowsky@Sun.COM static char *Timesbuf; /* copy of the timestamps file (a la mmap()) */ 61*e9a193fcSJohn.Zolnowsky@Sun.COM static int Timeslen; /* length of mmap'd timestamps area */ 62*e9a193fcSJohn.Zolnowsky@Sun.COM static int Singlefile; /* Conf and Times in the same file */ 63*e9a193fcSJohn.Zolnowsky@Sun.COM static int Changed; /* what changes need to be written back */ 64*e9a193fcSJohn.Zolnowsky@Sun.COM static int Canchange; /* what changes can be written back */ 65*e9a193fcSJohn.Zolnowsky@Sun.COM static int Changing; /* what changes have been requested */ 66*e9a193fcSJohn.Zolnowsky@Sun.COM #define CHG_NONE 0 67*e9a193fcSJohn.Zolnowsky@Sun.COM #define CHG_TIMES 1 68*e9a193fcSJohn.Zolnowsky@Sun.COM #define CHG_BOTH 3 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * our structured representation of the configuration file 727c478bd9Sstevel@tonic-gate * is made up of a list of these 737c478bd9Sstevel@tonic-gate */ 7478eb75caSchin struct confinfo { 757c478bd9Sstevel@tonic-gate struct confinfo *cf_next; 767c478bd9Sstevel@tonic-gate int cf_lineno; /* line number in file */ 777c478bd9Sstevel@tonic-gate const char *cf_entry; /* name of entry, if line has an entry */ 787c478bd9Sstevel@tonic-gate struct opts *cf_opts; /* parsed rhs of entry */ 797c478bd9Sstevel@tonic-gate const char *cf_com; /* any comment text found */ 807c478bd9Sstevel@tonic-gate int cf_flags; 817c478bd9Sstevel@tonic-gate }; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #define CONFF_DELETED 1 /* entry should be deleted on write back */ 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static struct confinfo *Confinfo; /* the entries in the config file */ 867c478bd9Sstevel@tonic-gate static struct confinfo *Confinfolast; /* end of list */ 877c478bd9Sstevel@tonic-gate static struct lut *Conflut; /* lookup table keyed by entry name */ 887c478bd9Sstevel@tonic-gate static struct fn_list *Confentries; /* list of valid entry names */ 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* allocate & fill in another entry in our list */ 917c478bd9Sstevel@tonic-gate static void 92*e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(int lineno, const char *entry, 937c478bd9Sstevel@tonic-gate struct opts *opts, const char *com, int flags) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate struct confinfo *cp = MALLOC(sizeof (*cp)); 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate cp->cf_next = NULL; 987c478bd9Sstevel@tonic-gate cp->cf_lineno = lineno; 997c478bd9Sstevel@tonic-gate cp->cf_entry = entry; 1007c478bd9Sstevel@tonic-gate cp->cf_opts = opts; 1017c478bd9Sstevel@tonic-gate cp->cf_com = com; 1027c478bd9Sstevel@tonic-gate cp->cf_flags = flags; 103b493790cSbasabi if (entry != NULL) { 1047c478bd9Sstevel@tonic-gate Conflut = lut_add(Conflut, entry, cp); 1057c478bd9Sstevel@tonic-gate fn_list_adds(Confentries, entry); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate if (Confinfo == NULL) 1087c478bd9Sstevel@tonic-gate Confinfo = Confinfolast = cp; 1097c478bd9Sstevel@tonic-gate else { 1107c478bd9Sstevel@tonic-gate Confinfolast->cf_next = cp; 1117c478bd9Sstevel@tonic-gate Confinfolast = cp; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate static char **Args; /* static buffer for args */ 1167c478bd9Sstevel@tonic-gate static int ArgsN; /* size of our static buffer */ 1177c478bd9Sstevel@tonic-gate static int ArgsI; /* index into Cmdargs as we walk table */ 1187c478bd9Sstevel@tonic-gate #define CONF_ARGS_INC 1024 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* callback for lut_walk to build a cmdargs vector */ 1217c478bd9Sstevel@tonic-gate static void 1227c478bd9Sstevel@tonic-gate fillargs(char *arg) 1237c478bd9Sstevel@tonic-gate { 1247c478bd9Sstevel@tonic-gate if (ArgsI >= ArgsN) { 1257c478bd9Sstevel@tonic-gate /* need bigger table */ 1267c478bd9Sstevel@tonic-gate Args = REALLOC(Args, sizeof (char *) * (ArgsN + CONF_ARGS_INC)); 1277c478bd9Sstevel@tonic-gate ArgsN += CONF_ARGS_INC; 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate Args[ArgsI++] = arg; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* isolate and return the next token */ 1337c478bd9Sstevel@tonic-gate static char * 1347c478bd9Sstevel@tonic-gate nexttok(char **ptrptr) 1357c478bd9Sstevel@tonic-gate { 1367c478bd9Sstevel@tonic-gate char *ptr = *ptrptr; 1377c478bd9Sstevel@tonic-gate char *eptr; 1387c478bd9Sstevel@tonic-gate char *quote = NULL; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate while (*ptr && isspace(*ptr)) 1417c478bd9Sstevel@tonic-gate ptr++; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if (*ptr == '"' || *ptr == '\'') 1447c478bd9Sstevel@tonic-gate quote = ptr++; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate for (eptr = ptr; *eptr; eptr++) 1477c478bd9Sstevel@tonic-gate if (quote && *eptr == *quote) { 1487c478bd9Sstevel@tonic-gate /* found end quote */ 1497c478bd9Sstevel@tonic-gate *eptr++ = '\0'; 1507c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1517c478bd9Sstevel@tonic-gate return (ptr); 1527c478bd9Sstevel@tonic-gate } else if (!quote && isspace(*eptr)) { 1537c478bd9Sstevel@tonic-gate /* found end of unquoted area */ 1547c478bd9Sstevel@tonic-gate *eptr++ = '\0'; 1557c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1567c478bd9Sstevel@tonic-gate return (ptr); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 159b493790cSbasabi if (quote != NULL) 1607c478bd9Sstevel@tonic-gate err(EF_FILE|EF_JMP, "Unbalanced %c quote", *quote); 1617c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (ptr == eptr) 1667c478bd9Sstevel@tonic-gate return (NULL); 1677c478bd9Sstevel@tonic-gate else 1687c478bd9Sstevel@tonic-gate return (ptr); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 172*e9a193fcSJohn.Zolnowsky@Sun.COM * scan the memory image of a file 173*e9a193fcSJohn.Zolnowsky@Sun.COM * returns: 0: error, 1: ok, 3: -P option found 1747c478bd9Sstevel@tonic-gate */ 175*e9a193fcSJohn.Zolnowsky@Sun.COM static int 176*e9a193fcSJohn.Zolnowsky@Sun.COM conf_scan(const char *fname, char *buf, int buflen, int timescan, 177*e9a193fcSJohn.Zolnowsky@Sun.COM struct opts *cliopts) 1787c478bd9Sstevel@tonic-gate { 179*e9a193fcSJohn.Zolnowsky@Sun.COM int ret = 1; 1807c478bd9Sstevel@tonic-gate int lineno = 0; 1817c478bd9Sstevel@tonic-gate char *line; 1827c478bd9Sstevel@tonic-gate char *eline; 1837c478bd9Sstevel@tonic-gate char *ebuf; 184*e9a193fcSJohn.Zolnowsky@Sun.COM char *entry, *comment; 1857c478bd9Sstevel@tonic-gate 186*e9a193fcSJohn.Zolnowsky@Sun.COM ebuf = &buf[buflen]; 1877c478bd9Sstevel@tonic-gate 188*e9a193fcSJohn.Zolnowsky@Sun.COM if (buf[buflen - 1] != '\n') 189*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_WARN|EF_FILE, "file %s doesn't end with newline, " 190*e9a193fcSJohn.Zolnowsky@Sun.COM "last line ignored.", fname); 1917c478bd9Sstevel@tonic-gate 192*e9a193fcSJohn.Zolnowsky@Sun.COM for (line = buf; line < ebuf; line = eline) { 193*e9a193fcSJohn.Zolnowsky@Sun.COM char *ap; 194*e9a193fcSJohn.Zolnowsky@Sun.COM struct opts *opts = NULL; 195*e9a193fcSJohn.Zolnowsky@Sun.COM struct confinfo *cp; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate lineno++; 198*e9a193fcSJohn.Zolnowsky@Sun.COM err_fileline(fname, lineno); 1997c478bd9Sstevel@tonic-gate eline = line; 2007c478bd9Sstevel@tonic-gate comment = NULL; 2017c478bd9Sstevel@tonic-gate for (; eline < ebuf; eline++) { 2027c478bd9Sstevel@tonic-gate /* check for continued lines */ 2037c478bd9Sstevel@tonic-gate if (comment == NULL && *eline == '\\' && 2047c478bd9Sstevel@tonic-gate eline + 1 < ebuf && *(eline + 1) == '\n') { 2057c478bd9Sstevel@tonic-gate *eline = ' '; 2067c478bd9Sstevel@tonic-gate *(eline + 1) = ' '; 2077c478bd9Sstevel@tonic-gate lineno++; 208*e9a193fcSJohn.Zolnowsky@Sun.COM err_fileline(fname, lineno); 2097c478bd9Sstevel@tonic-gate continue; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* check for comments */ 2137c478bd9Sstevel@tonic-gate if (comment == NULL && *eline == '#') { 2147c478bd9Sstevel@tonic-gate *eline = '\0'; 2157c478bd9Sstevel@tonic-gate comment = (eline + 1); 2167c478bd9Sstevel@tonic-gate continue; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* check for end of line */ 2207c478bd9Sstevel@tonic-gate if (*eline == '\n') 2217c478bd9Sstevel@tonic-gate break; 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate if (comment >= ebuf) 2247c478bd9Sstevel@tonic-gate comment = NULL; 225*e9a193fcSJohn.Zolnowsky@Sun.COM if (eline >= ebuf) { 226*e9a193fcSJohn.Zolnowsky@Sun.COM /* discard trailing unterminated line */ 227*e9a193fcSJohn.Zolnowsky@Sun.COM continue; 228*e9a193fcSJohn.Zolnowsky@Sun.COM } 2297c478bd9Sstevel@tonic-gate *eline++ = '\0'; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * now we have the entry, if any, at "line" 2337c478bd9Sstevel@tonic-gate * and the comment, if any, at "comment" 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* entry is first token */ 237*e9a193fcSJohn.Zolnowsky@Sun.COM entry = nexttok(&line); 238*e9a193fcSJohn.Zolnowsky@Sun.COM if (entry == NULL) { 239*e9a193fcSJohn.Zolnowsky@Sun.COM /* it's just a comment line */ 240*e9a193fcSJohn.Zolnowsky@Sun.COM if (!timescan) 241*e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(lineno, entry, NULL, comment, 0); 242*e9a193fcSJohn.Zolnowsky@Sun.COM continue; 243*e9a193fcSJohn.Zolnowsky@Sun.COM } 244*e9a193fcSJohn.Zolnowsky@Sun.COM if (strcmp(entry, "logadm-version") == 0) { 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * we somehow opened some future format 2477c478bd9Sstevel@tonic-gate * conffile that we likely don't understand. 2487c478bd9Sstevel@tonic-gate * if the given version is "1" then go on, 2497c478bd9Sstevel@tonic-gate * otherwise someone is mixing versions 2507c478bd9Sstevel@tonic-gate * and we can't help them other than to 2517c478bd9Sstevel@tonic-gate * print an error and exit. 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate if ((entry = nexttok(&line)) != NULL && 2547c478bd9Sstevel@tonic-gate strcmp(entry, "1") != 0) 255*e9a193fcSJohn.Zolnowsky@Sun.COM err(0, "%s version not supported " 256*e9a193fcSJohn.Zolnowsky@Sun.COM "by this version of logadm.", 257*e9a193fcSJohn.Zolnowsky@Sun.COM fname); 258*e9a193fcSJohn.Zolnowsky@Sun.COM continue; 259*e9a193fcSJohn.Zolnowsky@Sun.COM } 2607c478bd9Sstevel@tonic-gate 261*e9a193fcSJohn.Zolnowsky@Sun.COM /* form an argv array */ 2627c478bd9Sstevel@tonic-gate ArgsI = 0; 2637c478bd9Sstevel@tonic-gate while (ap = nexttok(&line)) 2647c478bd9Sstevel@tonic-gate fillargs(ap); 265*e9a193fcSJohn.Zolnowsky@Sun.COM Args[ArgsI] = NULL; 266*e9a193fcSJohn.Zolnowsky@Sun.COM 267*e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BEGIN { 268*e9a193fcSJohn.Zolnowsky@Sun.COM if (SETJMP) { 269*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_FILE, "cannot process invalid entry %s", 270*e9a193fcSJohn.Zolnowsky@Sun.COM entry); 271*e9a193fcSJohn.Zolnowsky@Sun.COM ret = 0; 272*e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BREAK; 2737c478bd9Sstevel@tonic-gate } 274*e9a193fcSJohn.Zolnowsky@Sun.COM 275*e9a193fcSJohn.Zolnowsky@Sun.COM if (timescan) { 276*e9a193fcSJohn.Zolnowsky@Sun.COM /* append to config options */ 277*e9a193fcSJohn.Zolnowsky@Sun.COM cp = lut_lookup(Conflut, entry); 278*e9a193fcSJohn.Zolnowsky@Sun.COM if (cp == NULL) { 279*e9a193fcSJohn.Zolnowsky@Sun.COM /* orphaned entry */ 280*e9a193fcSJohn.Zolnowsky@Sun.COM if (opts_count(cliopts, "v")) 281*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_FILE, "stale timestamp " 282*e9a193fcSJohn.Zolnowsky@Sun.COM "for %s", entry); 283*e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BREAK; 2847c478bd9Sstevel@tonic-gate } 285*e9a193fcSJohn.Zolnowsky@Sun.COM opts = cp->cf_opts; 2867c478bd9Sstevel@tonic-gate } 287*e9a193fcSJohn.Zolnowsky@Sun.COM opts = opts_parse(opts, Args, OPTF_CONF); 288*e9a193fcSJohn.Zolnowsky@Sun.COM if (!timescan) { 289*e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(lineno, entry, opts, comment, 0); 290*e9a193fcSJohn.Zolnowsky@Sun.COM } 291*e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_END } 292*e9a193fcSJohn.Zolnowsky@Sun.COM 293*e9a193fcSJohn.Zolnowsky@Sun.COM if (ret == 1 && opts && opts_optarg(opts, "P") != NULL) 294*e9a193fcSJohn.Zolnowsky@Sun.COM ret = 3; 295*e9a193fcSJohn.Zolnowsky@Sun.COM } 296*e9a193fcSJohn.Zolnowsky@Sun.COM 297*e9a193fcSJohn.Zolnowsky@Sun.COM err_fileline(NULL, 0); 298*e9a193fcSJohn.Zolnowsky@Sun.COM return (ret); 299*e9a193fcSJohn.Zolnowsky@Sun.COM } 300*e9a193fcSJohn.Zolnowsky@Sun.COM 301*e9a193fcSJohn.Zolnowsky@Sun.COM /* 302*e9a193fcSJohn.Zolnowsky@Sun.COM * conf_open -- open the configuration file, lock it if we have write perms 303*e9a193fcSJohn.Zolnowsky@Sun.COM */ 304*e9a193fcSJohn.Zolnowsky@Sun.COM int 305*e9a193fcSJohn.Zolnowsky@Sun.COM conf_open(const char *cfname, const char *tfname, struct opts *cliopts) 306*e9a193fcSJohn.Zolnowsky@Sun.COM { 307*e9a193fcSJohn.Zolnowsky@Sun.COM struct stat stbuf1, stbuf2, stbuf3; 308*e9a193fcSJohn.Zolnowsky@Sun.COM struct flock flock; 309*e9a193fcSJohn.Zolnowsky@Sun.COM int ret; 310*e9a193fcSJohn.Zolnowsky@Sun.COM 311*e9a193fcSJohn.Zolnowsky@Sun.COM Confname = cfname; 312*e9a193fcSJohn.Zolnowsky@Sun.COM Timesname = tfname; 313*e9a193fcSJohn.Zolnowsky@Sun.COM Confentries = fn_list_new(NULL); 314*e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_NONE; 315*e9a193fcSJohn.Zolnowsky@Sun.COM 316*e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_TIMES; 317*e9a193fcSJohn.Zolnowsky@Sun.COM if (opts_count(cliopts, "Vn") != 0) 318*e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_NONE; 319*e9a193fcSJohn.Zolnowsky@Sun.COM else if (opts_count(cliopts, "rw") != 0) 320*e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_BOTH; 321*e9a193fcSJohn.Zolnowsky@Sun.COM 322*e9a193fcSJohn.Zolnowsky@Sun.COM Singlefile = strcmp(Confname, Timesname) == 0; 323*e9a193fcSJohn.Zolnowsky@Sun.COM if (Singlefile && Changing == CHG_TIMES) 324*e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_BOTH; 325*e9a193fcSJohn.Zolnowsky@Sun.COM 326*e9a193fcSJohn.Zolnowsky@Sun.COM /* special case this so we don't even try locking the file */ 327*e9a193fcSJohn.Zolnowsky@Sun.COM if (strcmp(Confname, "/dev/null") == 0) 328*e9a193fcSJohn.Zolnowsky@Sun.COM return (0); 329*e9a193fcSJohn.Zolnowsky@Sun.COM 330*e9a193fcSJohn.Zolnowsky@Sun.COM while (Conffd == -1) { 331*e9a193fcSJohn.Zolnowsky@Sun.COM Canchange = CHG_BOTH; 332*e9a193fcSJohn.Zolnowsky@Sun.COM if ((Conffd = open(Confname, O_RDWR)) < 0) { 333*e9a193fcSJohn.Zolnowsky@Sun.COM if (Changing == CHG_BOTH) 334*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Confname); 335*e9a193fcSJohn.Zolnowsky@Sun.COM Canchange = CHG_TIMES; 336*e9a193fcSJohn.Zolnowsky@Sun.COM if ((Conffd = open(Confname, O_RDONLY)) < 0) 337*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Confname); 338*e9a193fcSJohn.Zolnowsky@Sun.COM } 339*e9a193fcSJohn.Zolnowsky@Sun.COM 340*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_type = (Canchange == CHG_BOTH) ? F_WRLCK : F_RDLCK; 341*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_whence = SEEK_SET; 342*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_start = 0; 343*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_len = 1; 344*e9a193fcSJohn.Zolnowsky@Sun.COM if (fcntl(Conffd, F_SETLKW, &flock) < 0) 345*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "flock on %s", Confname); 346*e9a193fcSJohn.Zolnowsky@Sun.COM 347*e9a193fcSJohn.Zolnowsky@Sun.COM /* wait until after file is locked to get filesize */ 348*e9a193fcSJohn.Zolnowsky@Sun.COM if (fstat(Conffd, &stbuf1) < 0) 349*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "fstat on %s", Confname); 350*e9a193fcSJohn.Zolnowsky@Sun.COM 351*e9a193fcSJohn.Zolnowsky@Sun.COM /* verify that we've got a lock on the active file */ 352*e9a193fcSJohn.Zolnowsky@Sun.COM if (stat(Confname, &stbuf2) < 0 || 353*e9a193fcSJohn.Zolnowsky@Sun.COM !(stbuf2.st_dev == stbuf1.st_dev && 354*e9a193fcSJohn.Zolnowsky@Sun.COM stbuf2.st_ino == stbuf1.st_ino)) { 355*e9a193fcSJohn.Zolnowsky@Sun.COM /* wrong config file, try again */ 356*e9a193fcSJohn.Zolnowsky@Sun.COM (void) close(Conffd); 357*e9a193fcSJohn.Zolnowsky@Sun.COM Conffd = -1; 358*e9a193fcSJohn.Zolnowsky@Sun.COM } 359*e9a193fcSJohn.Zolnowsky@Sun.COM } 360*e9a193fcSJohn.Zolnowsky@Sun.COM 361*e9a193fcSJohn.Zolnowsky@Sun.COM while (!Singlefile && Timesfd == -1) { 362*e9a193fcSJohn.Zolnowsky@Sun.COM if ((Timesfd = open(Timesname, O_CREAT|O_RDWR, 0644)) < 0) { 363*e9a193fcSJohn.Zolnowsky@Sun.COM if (Changing != CHG_NONE) 364*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Timesname); 365*e9a193fcSJohn.Zolnowsky@Sun.COM Canchange = CHG_NONE; 366*e9a193fcSJohn.Zolnowsky@Sun.COM if ((Timesfd = open(Timesname, O_RDONLY)) < 0) 367*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Timesname); 368*e9a193fcSJohn.Zolnowsky@Sun.COM } 369*e9a193fcSJohn.Zolnowsky@Sun.COM 370*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_type = (Canchange != CHG_NONE) ? F_WRLCK : F_RDLCK; 371*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_whence = SEEK_SET; 372*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_start = 0; 373*e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_len = 1; 374*e9a193fcSJohn.Zolnowsky@Sun.COM if (fcntl(Timesfd, F_SETLKW, &flock) < 0) 375*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "flock on %s", Timesname); 376*e9a193fcSJohn.Zolnowsky@Sun.COM 377*e9a193fcSJohn.Zolnowsky@Sun.COM /* wait until after file is locked to get filesize */ 378*e9a193fcSJohn.Zolnowsky@Sun.COM if (fstat(Timesfd, &stbuf2) < 0) 379*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "fstat on %s", Timesname); 380*e9a193fcSJohn.Zolnowsky@Sun.COM 381*e9a193fcSJohn.Zolnowsky@Sun.COM /* verify that we've got a lock on the active file */ 382*e9a193fcSJohn.Zolnowsky@Sun.COM if (stat(Timesname, &stbuf3) < 0 || 383*e9a193fcSJohn.Zolnowsky@Sun.COM !(stbuf2.st_dev == stbuf3.st_dev && 384*e9a193fcSJohn.Zolnowsky@Sun.COM stbuf2.st_ino == stbuf3.st_ino)) { 385*e9a193fcSJohn.Zolnowsky@Sun.COM /* wrong timestamp file, try again */ 386*e9a193fcSJohn.Zolnowsky@Sun.COM (void) close(Timesfd); 387*e9a193fcSJohn.Zolnowsky@Sun.COM Timesfd = -1; 388*e9a193fcSJohn.Zolnowsky@Sun.COM continue; 389*e9a193fcSJohn.Zolnowsky@Sun.COM } 390*e9a193fcSJohn.Zolnowsky@Sun.COM 391*e9a193fcSJohn.Zolnowsky@Sun.COM /* check that Timesname isn't an alias for Confname */ 392*e9a193fcSJohn.Zolnowsky@Sun.COM if (stbuf2.st_dev == stbuf1.st_dev && 393*e9a193fcSJohn.Zolnowsky@Sun.COM stbuf2.st_ino == stbuf1.st_ino) 394*e9a193fcSJohn.Zolnowsky@Sun.COM err(0, "Timestamp file %s can't refer to " 395*e9a193fcSJohn.Zolnowsky@Sun.COM "Configuration file %s", Timesname, Confname); 396*e9a193fcSJohn.Zolnowsky@Sun.COM } 397*e9a193fcSJohn.Zolnowsky@Sun.COM 398*e9a193fcSJohn.Zolnowsky@Sun.COM Conflen = stbuf1.st_size; 399*e9a193fcSJohn.Zolnowsky@Sun.COM Timeslen = stbuf2.st_size; 400*e9a193fcSJohn.Zolnowsky@Sun.COM 401*e9a193fcSJohn.Zolnowsky@Sun.COM if (Conflen == 0) 402*e9a193fcSJohn.Zolnowsky@Sun.COM return (1); /* empty file, don't bother parsing it */ 403*e9a193fcSJohn.Zolnowsky@Sun.COM 404*e9a193fcSJohn.Zolnowsky@Sun.COM if ((Confbuf = (char *)mmap(0, Conflen, 405*e9a193fcSJohn.Zolnowsky@Sun.COM PROT_READ | PROT_WRITE, MAP_PRIVATE, Conffd, 0)) == (char *)-1) 406*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "mmap on %s", Confname); 407*e9a193fcSJohn.Zolnowsky@Sun.COM 408*e9a193fcSJohn.Zolnowsky@Sun.COM ret = conf_scan(Confname, Confbuf, Conflen, 0, cliopts); 409*e9a193fcSJohn.Zolnowsky@Sun.COM if (ret == 3 && !Singlefile && Canchange == CHG_BOTH) { 410*e9a193fcSJohn.Zolnowsky@Sun.COM /* 411*e9a193fcSJohn.Zolnowsky@Sun.COM * arrange to transfer any timestamps 412*e9a193fcSJohn.Zolnowsky@Sun.COM * from conf_file to timestamps_file 413*e9a193fcSJohn.Zolnowsky@Sun.COM */ 414*e9a193fcSJohn.Zolnowsky@Sun.COM Changing = Changed = CHG_BOTH; 415*e9a193fcSJohn.Zolnowsky@Sun.COM } 416*e9a193fcSJohn.Zolnowsky@Sun.COM 417*e9a193fcSJohn.Zolnowsky@Sun.COM if (Timesfd != -1 && Timeslen != 0) { 418*e9a193fcSJohn.Zolnowsky@Sun.COM if ((Timesbuf = (char *)mmap(0, Timeslen, 419*e9a193fcSJohn.Zolnowsky@Sun.COM PROT_READ | PROT_WRITE, MAP_PRIVATE, 420*e9a193fcSJohn.Zolnowsky@Sun.COM Timesfd, 0)) == (char *)-1) 421*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "mmap on %s", Timesname); 422*e9a193fcSJohn.Zolnowsky@Sun.COM ret &= conf_scan(Timesname, Timesbuf, Timeslen, 1, cliopts); 423*e9a193fcSJohn.Zolnowsky@Sun.COM } 424*e9a193fcSJohn.Zolnowsky@Sun.COM 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * possible future enhancement: go through and mark any entries: 4277c478bd9Sstevel@tonic-gate * logfile -P <date> 4287c478bd9Sstevel@tonic-gate * as DELETED if the logfile doesn't exist 4297c478bd9Sstevel@tonic-gate */ 430*e9a193fcSJohn.Zolnowsky@Sun.COM 431*e9a193fcSJohn.Zolnowsky@Sun.COM return (ret); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate * conf_close -- close the configuration file 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate void 4387c478bd9Sstevel@tonic-gate conf_close(struct opts *opts) 4397c478bd9Sstevel@tonic-gate { 440*e9a193fcSJohn.Zolnowsky@Sun.COM char cuname[PATH_MAX], tuname[PATH_MAX]; 441*e9a193fcSJohn.Zolnowsky@Sun.COM int cfd, tfd; 442*e9a193fcSJohn.Zolnowsky@Sun.COM FILE *cfp = NULL, *tfp = NULL; 443*e9a193fcSJohn.Zolnowsky@Sun.COM boolean_t safe_update = B_TRUE; 4447c478bd9Sstevel@tonic-gate 445*e9a193fcSJohn.Zolnowsky@Sun.COM if (Changed == CHG_NONE || opts_count(opts, "n") != 0) { 4467c478bd9Sstevel@tonic-gate if (opts_count(opts, "v")) 447*e9a193fcSJohn.Zolnowsky@Sun.COM (void) out("# %s and %s unchanged\n", 448*e9a193fcSJohn.Zolnowsky@Sun.COM Confname, Timesname); 449*e9a193fcSJohn.Zolnowsky@Sun.COM goto cleanup; 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 452*e9a193fcSJohn.Zolnowsky@Sun.COM if (Debug > 1) { 453*e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(stderr, "conf_close, saving logadm context:\n"); 454*e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(stderr, NULL); 455*e9a193fcSJohn.Zolnowsky@Sun.COM } 456*e9a193fcSJohn.Zolnowsky@Sun.COM 457*e9a193fcSJohn.Zolnowsky@Sun.COM cuname[0] = tuname[0] = '\0'; 458*e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BEGIN { 459*e9a193fcSJohn.Zolnowsky@Sun.COM if (SETJMP) { 460*e9a193fcSJohn.Zolnowsky@Sun.COM safe_update = B_FALSE; 461*e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BREAK; 462*e9a193fcSJohn.Zolnowsky@Sun.COM } 463*e9a193fcSJohn.Zolnowsky@Sun.COM if (Changed == CHG_BOTH) { 464*e9a193fcSJohn.Zolnowsky@Sun.COM if (Canchange != CHG_BOTH) 465*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_JMP, "internal error: attempting " 466*e9a193fcSJohn.Zolnowsky@Sun.COM "to update %s without locking", Confname); 467*e9a193fcSJohn.Zolnowsky@Sun.COM (void) snprintf(cuname, sizeof (cuname), "%sXXXXXX", 468*e9a193fcSJohn.Zolnowsky@Sun.COM Confname); 469*e9a193fcSJohn.Zolnowsky@Sun.COM if ((cfd = mkstemp(cuname)) == -1) 470*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "open %s replacement", 471*e9a193fcSJohn.Zolnowsky@Sun.COM Confname); 472*e9a193fcSJohn.Zolnowsky@Sun.COM if (opts_count(opts, "v")) 473*e9a193fcSJohn.Zolnowsky@Sun.COM (void) out("# writing changes to %s\n", cuname); 474*e9a193fcSJohn.Zolnowsky@Sun.COM if (fchmod(cfd, 0644) == -1) 475*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "chmod %s", cuname); 476*e9a193fcSJohn.Zolnowsky@Sun.COM if ((cfp = fdopen(cfd, "w")) == NULL) 477*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fdopen on %s", cuname); 478*e9a193fcSJohn.Zolnowsky@Sun.COM } else { 479*e9a193fcSJohn.Zolnowsky@Sun.COM /* just toss away the configuration data */ 480*e9a193fcSJohn.Zolnowsky@Sun.COM cfp = fopen("/dev/null", "w"); 481*e9a193fcSJohn.Zolnowsky@Sun.COM } 482*e9a193fcSJohn.Zolnowsky@Sun.COM if (!Singlefile) { 483*e9a193fcSJohn.Zolnowsky@Sun.COM if (Canchange == CHG_NONE) 484*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_JMP, "internal error: attempting " 485*e9a193fcSJohn.Zolnowsky@Sun.COM "to update %s without locking", Timesname); 486*e9a193fcSJohn.Zolnowsky@Sun.COM (void) snprintf(tuname, sizeof (tuname), "%sXXXXXX", 487*e9a193fcSJohn.Zolnowsky@Sun.COM Timesname); 488*e9a193fcSJohn.Zolnowsky@Sun.COM if ((tfd = mkstemp(tuname)) == -1) 489*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "open %s replacement", 490*e9a193fcSJohn.Zolnowsky@Sun.COM Timesname); 491*e9a193fcSJohn.Zolnowsky@Sun.COM if (opts_count(opts, "v")) 492*e9a193fcSJohn.Zolnowsky@Sun.COM (void) out("# writing changes to %s\n", tuname); 493*e9a193fcSJohn.Zolnowsky@Sun.COM if (fchmod(tfd, 0644) == -1) 494*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "chmod %s", tuname); 495*e9a193fcSJohn.Zolnowsky@Sun.COM if ((tfp = fdopen(tfd, "w")) == NULL) 496*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fdopen on %s", tuname); 497*e9a193fcSJohn.Zolnowsky@Sun.COM } 498*e9a193fcSJohn.Zolnowsky@Sun.COM 499*e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(cfp, tfp); 500*e9a193fcSJohn.Zolnowsky@Sun.COM if (fclose(cfp) < 0) 501*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fclose on %s", Confname); 502*e9a193fcSJohn.Zolnowsky@Sun.COM if (tfp != NULL && fclose(tfp) < 0) 503*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fclose on %s", Timesname); 504*e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_END } 505*e9a193fcSJohn.Zolnowsky@Sun.COM 506*e9a193fcSJohn.Zolnowsky@Sun.COM if (!safe_update) { 507*e9a193fcSJohn.Zolnowsky@Sun.COM if (cuname[0] != 0) 508*e9a193fcSJohn.Zolnowsky@Sun.COM (void) unlink(cuname); 509*e9a193fcSJohn.Zolnowsky@Sun.COM if (tuname[0] != 0) 510*e9a193fcSJohn.Zolnowsky@Sun.COM (void) unlink(tuname); 511*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_JMP, "unsafe to update configuration file " 512*e9a193fcSJohn.Zolnowsky@Sun.COM "or timestamps"); 513*e9a193fcSJohn.Zolnowsky@Sun.COM return; 514*e9a193fcSJohn.Zolnowsky@Sun.COM } 515*e9a193fcSJohn.Zolnowsky@Sun.COM 516*e9a193fcSJohn.Zolnowsky@Sun.COM /* rename updated files into place */ 517*e9a193fcSJohn.Zolnowsky@Sun.COM if (cuname[0] != '\0') 518*e9a193fcSJohn.Zolnowsky@Sun.COM if (rename(cuname, Confname) < 0) 519*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "rename %s to %s", cuname, Confname); 520*e9a193fcSJohn.Zolnowsky@Sun.COM if (tuname[0] != '\0') 521*e9a193fcSJohn.Zolnowsky@Sun.COM if (rename(tuname, Timesname) < 0) 522*e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "rename %s to %s", tuname, Timesname); 523*e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_NONE; 524*e9a193fcSJohn.Zolnowsky@Sun.COM 525*e9a193fcSJohn.Zolnowsky@Sun.COM cleanup: 5267c478bd9Sstevel@tonic-gate if (Conffd != -1) { 5277c478bd9Sstevel@tonic-gate (void) close(Conffd); 5287c478bd9Sstevel@tonic-gate Conffd = -1; 5297c478bd9Sstevel@tonic-gate } 530*e9a193fcSJohn.Zolnowsky@Sun.COM if (Timesfd != -1) { 531*e9a193fcSJohn.Zolnowsky@Sun.COM (void) close(Timesfd); 532*e9a193fcSJohn.Zolnowsky@Sun.COM Timesfd = -1; 533*e9a193fcSJohn.Zolnowsky@Sun.COM } 5347c478bd9Sstevel@tonic-gate if (Conflut) { 5357c478bd9Sstevel@tonic-gate lut_free(Conflut, free); 5367c478bd9Sstevel@tonic-gate Conflut = NULL; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate if (Confentries) { 5397c478bd9Sstevel@tonic-gate fn_list_free(Confentries); 5407c478bd9Sstevel@tonic-gate Confentries = NULL; 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * conf_lookup -- lookup an entry in the config file 5467c478bd9Sstevel@tonic-gate */ 547*e9a193fcSJohn.Zolnowsky@Sun.COM void * 5487c478bd9Sstevel@tonic-gate conf_lookup(const char *lhs) 5497c478bd9Sstevel@tonic-gate { 5507c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 5517c478bd9Sstevel@tonic-gate 552*e9a193fcSJohn.Zolnowsky@Sun.COM if (cp != NULL) 5537c478bd9Sstevel@tonic-gate err_fileline(Confname, cp->cf_lineno); 554*e9a193fcSJohn.Zolnowsky@Sun.COM return (cp); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate /* 5587c478bd9Sstevel@tonic-gate * conf_opts -- return the parsed opts for an entry 5597c478bd9Sstevel@tonic-gate */ 5607c478bd9Sstevel@tonic-gate struct opts * 5617c478bd9Sstevel@tonic-gate conf_opts(const char *lhs) 5627c478bd9Sstevel@tonic-gate { 5637c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 5647c478bd9Sstevel@tonic-gate 565*e9a193fcSJohn.Zolnowsky@Sun.COM if (cp != NULL) 5667c478bd9Sstevel@tonic-gate return (cp->cf_opts); 567*e9a193fcSJohn.Zolnowsky@Sun.COM return (opts_parse(NULL, NULL, OPTF_CONF)); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate /* 5717c478bd9Sstevel@tonic-gate * conf_replace -- replace an entry in the config file 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate void 5747c478bd9Sstevel@tonic-gate conf_replace(const char *lhs, struct opts *newopts) 5757c478bd9Sstevel@tonic-gate { 5767c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if (Conffd == -1) 5797c478bd9Sstevel@tonic-gate return; 5807c478bd9Sstevel@tonic-gate 581b493790cSbasabi if (cp != NULL) { 5827c478bd9Sstevel@tonic-gate cp->cf_opts = newopts; 583*e9a193fcSJohn.Zolnowsky@Sun.COM /* cp->cf_args = NULL; */ 5847c478bd9Sstevel@tonic-gate if (newopts == NULL) 5857c478bd9Sstevel@tonic-gate cp->cf_flags |= CONFF_DELETED; 5867c478bd9Sstevel@tonic-gate } else 587*e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(0, lhs, newopts, NULL, 0); 588*e9a193fcSJohn.Zolnowsky@Sun.COM 589*e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_BOTH; 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate /* 5937c478bd9Sstevel@tonic-gate * conf_set -- set options for an entry in the config file 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate void 5967c478bd9Sstevel@tonic-gate conf_set(const char *entry, char *o, const char *optarg) 5977c478bd9Sstevel@tonic-gate { 5987c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, entry); 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (Conffd == -1) 6017c478bd9Sstevel@tonic-gate return; 6027c478bd9Sstevel@tonic-gate 603b493790cSbasabi if (cp != NULL) { 6047c478bd9Sstevel@tonic-gate cp->cf_flags &= ~CONFF_DELETED; 6057c478bd9Sstevel@tonic-gate } else { 606*e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(0, STRDUP(entry), 607*e9a193fcSJohn.Zolnowsky@Sun.COM opts_parse(NULL, NULL, OPTF_CONF), NULL, 0); 6087c478bd9Sstevel@tonic-gate if ((cp = lut_lookup(Conflut, entry)) == NULL) 6097c478bd9Sstevel@tonic-gate err(0, "conf_set internal error"); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate (void) opts_set(cp->cf_opts, o, optarg); 612*e9a193fcSJohn.Zolnowsky@Sun.COM if (strcmp(o, "P") == 0) 613*e9a193fcSJohn.Zolnowsky@Sun.COM Changed |= CHG_TIMES; 614*e9a193fcSJohn.Zolnowsky@Sun.COM else 615*e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_BOTH; 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* 6197c478bd9Sstevel@tonic-gate * conf_entries -- list all the entry names 6207c478bd9Sstevel@tonic-gate */ 6217c478bd9Sstevel@tonic-gate struct fn_list * 6227c478bd9Sstevel@tonic-gate conf_entries(void) 6237c478bd9Sstevel@tonic-gate { 6247c478bd9Sstevel@tonic-gate return (Confentries); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate /* print the config file */ 6287c478bd9Sstevel@tonic-gate static void 629*e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(FILE *cstream, FILE *tstream) 6307c478bd9Sstevel@tonic-gate { 6317c478bd9Sstevel@tonic-gate struct confinfo *cp; 632*e9a193fcSJohn.Zolnowsky@Sun.COM char *exclude_opts = "PFfhnrvVw"; 633*e9a193fcSJohn.Zolnowsky@Sun.COM const char *timestamp; 6347c478bd9Sstevel@tonic-gate 635*e9a193fcSJohn.Zolnowsky@Sun.COM if (tstream == NULL) { 636*e9a193fcSJohn.Zolnowsky@Sun.COM exclude_opts++; /* -P option goes to config file */ 637*e9a193fcSJohn.Zolnowsky@Sun.COM } else { 638*e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(tstream, gettext( 639*e9a193fcSJohn.Zolnowsky@Sun.COM "# This file holds internal data for logadm(1M).\n" 640*e9a193fcSJohn.Zolnowsky@Sun.COM "# Do not edit.\n")); 641*e9a193fcSJohn.Zolnowsky@Sun.COM } 6427c478bd9Sstevel@tonic-gate for (cp = Confinfo; cp; cp = cp->cf_next) { 6437c478bd9Sstevel@tonic-gate if (cp->cf_flags & CONFF_DELETED) 6447c478bd9Sstevel@tonic-gate continue; 6457c478bd9Sstevel@tonic-gate if (cp->cf_entry) { 646*e9a193fcSJohn.Zolnowsky@Sun.COM opts_printword(cp->cf_entry, cstream); 647*e9a193fcSJohn.Zolnowsky@Sun.COM if (cp->cf_opts) 648*e9a193fcSJohn.Zolnowsky@Sun.COM opts_print(cp->cf_opts, cstream, exclude_opts); 649*e9a193fcSJohn.Zolnowsky@Sun.COM /* output timestamps to tstream */ 650*e9a193fcSJohn.Zolnowsky@Sun.COM if (tstream != NULL && (timestamp = 651*e9a193fcSJohn.Zolnowsky@Sun.COM opts_optarg(cp->cf_opts, "P")) != NULL) { 652*e9a193fcSJohn.Zolnowsky@Sun.COM opts_printword(cp->cf_entry, tstream); 653*e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(tstream, " -P "); 654*e9a193fcSJohn.Zolnowsky@Sun.COM opts_printword(timestamp, tstream); 655*e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(tstream, "\n"); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate if (cp->cf_com) { 6597c478bd9Sstevel@tonic-gate if (cp->cf_entry) 660*e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(cstream, " "); 661*e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(cstream, "#%s", cp->cf_com); 6627c478bd9Sstevel@tonic-gate } 663*e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(cstream, "\n"); 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate #ifdef TESTMODULE 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate /* 6707c478bd9Sstevel@tonic-gate * test main for conf module, usage: a.out conffile 6717c478bd9Sstevel@tonic-gate */ 672b493790cSbasabi int 6737c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 6747c478bd9Sstevel@tonic-gate { 675*e9a193fcSJohn.Zolnowsky@Sun.COM struct opts *opts; 676*e9a193fcSJohn.Zolnowsky@Sun.COM 6777c478bd9Sstevel@tonic-gate err_init(argv[0]); 6787c478bd9Sstevel@tonic-gate setbuf(stdout, NULL); 679*e9a193fcSJohn.Zolnowsky@Sun.COM opts_init(Opttable, Opttable_cnt); 680*e9a193fcSJohn.Zolnowsky@Sun.COM 681*e9a193fcSJohn.Zolnowsky@Sun.COM opts = opts_parse(NULL, NULL, 0); 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate if (argc != 2) 6847c478bd9Sstevel@tonic-gate err(EF_RAW, "usage: %s conffile\n", argv[0]); 6857c478bd9Sstevel@tonic-gate 686*e9a193fcSJohn.Zolnowsky@Sun.COM conf_open(argv[1], argv[1], opts); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate printf("conffile <%s>:\n", argv[1]); 689*e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(stdout, NULL); 6907c478bd9Sstevel@tonic-gate 691*e9a193fcSJohn.Zolnowsky@Sun.COM conf_close(opts); 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate err_done(0); 694b493790cSbasabi /* NOTREACHED */ 695b493790cSbasabi return (0); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate #endif /* TESTMODULE */ 699