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 /* 23e9a193fcSJohn.Zolnowsky@Sun.COM * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 24*34969e74SJerry Jelinek * Copyright 2013, Joyent, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 2778eb75caSchin /* 2878eb75caSchin * logadm/conf.c -- configuration file module 2978eb75caSchin */ 3078eb75caSchin 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <libintl.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <sys/mman.h> 377c478bd9Sstevel@tonic-gate #include <ctype.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <unistd.h> 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 41e9a193fcSJohn.Zolnowsky@Sun.COM #include <limits.h> 427c478bd9Sstevel@tonic-gate #include "err.h" 437c478bd9Sstevel@tonic-gate #include "lut.h" 447c478bd9Sstevel@tonic-gate #include "fn.h" 457c478bd9Sstevel@tonic-gate #include "opts.h" 467c478bd9Sstevel@tonic-gate #include "conf.h" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* forward declarations of functions private to this module */ 49e9a193fcSJohn.Zolnowsky@Sun.COM static void fillconflist(int lineno, const char *entry, 507c478bd9Sstevel@tonic-gate struct opts *opts, const char *com, int flags); 517c478bd9Sstevel@tonic-gate static void fillargs(char *arg); 527c478bd9Sstevel@tonic-gate static char *nexttok(char **ptrptr); 53e9a193fcSJohn.Zolnowsky@Sun.COM static void conf_print(FILE *cstream, FILE *tstream); 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate static const char *Confname; /* name of the confile file */ 567c478bd9Sstevel@tonic-gate static int Conffd = -1; /* file descriptor for config file */ 57e9a193fcSJohn.Zolnowsky@Sun.COM static char *Confbuf; /* copy of the config file (a la mmap()) */ 58e9a193fcSJohn.Zolnowsky@Sun.COM static int Conflen; /* length of mmap'd config file area */ 59e9a193fcSJohn.Zolnowsky@Sun.COM static const char *Timesname; /* name of the timestamps file */ 60e9a193fcSJohn.Zolnowsky@Sun.COM static int Timesfd = -1; /* file descriptor for timestamps file */ 61e9a193fcSJohn.Zolnowsky@Sun.COM static char *Timesbuf; /* copy of the timestamps file (a la mmap()) */ 62e9a193fcSJohn.Zolnowsky@Sun.COM static int Timeslen; /* length of mmap'd timestamps area */ 63e9a193fcSJohn.Zolnowsky@Sun.COM static int Singlefile; /* Conf and Times in the same file */ 64e9a193fcSJohn.Zolnowsky@Sun.COM static int Changed; /* what changes need to be written back */ 65e9a193fcSJohn.Zolnowsky@Sun.COM static int Canchange; /* what changes can be written back */ 66e9a193fcSJohn.Zolnowsky@Sun.COM static int Changing; /* what changes have been requested */ 67e9a193fcSJohn.Zolnowsky@Sun.COM #define CHG_NONE 0 68e9a193fcSJohn.Zolnowsky@Sun.COM #define CHG_TIMES 1 69e9a193fcSJohn.Zolnowsky@Sun.COM #define CHG_BOTH 3 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * our structured representation of the configuration file 737c478bd9Sstevel@tonic-gate * is made up of a list of these 747c478bd9Sstevel@tonic-gate */ 7578eb75caSchin struct confinfo { 767c478bd9Sstevel@tonic-gate struct confinfo *cf_next; 777c478bd9Sstevel@tonic-gate int cf_lineno; /* line number in file */ 787c478bd9Sstevel@tonic-gate const char *cf_entry; /* name of entry, if line has an entry */ 797c478bd9Sstevel@tonic-gate struct opts *cf_opts; /* parsed rhs of entry */ 807c478bd9Sstevel@tonic-gate const char *cf_com; /* any comment text found */ 817c478bd9Sstevel@tonic-gate int cf_flags; 827c478bd9Sstevel@tonic-gate }; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #define CONFF_DELETED 1 /* entry should be deleted on write back */ 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate static struct confinfo *Confinfo; /* the entries in the config file */ 877c478bd9Sstevel@tonic-gate static struct confinfo *Confinfolast; /* end of list */ 887c478bd9Sstevel@tonic-gate static struct lut *Conflut; /* lookup table keyed by entry name */ 897c478bd9Sstevel@tonic-gate static struct fn_list *Confentries; /* list of valid entry names */ 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* allocate & fill in another entry in our list */ 927c478bd9Sstevel@tonic-gate static void 93e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(int lineno, const char *entry, 947c478bd9Sstevel@tonic-gate struct opts *opts, const char *com, int flags) 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate struct confinfo *cp = MALLOC(sizeof (*cp)); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate cp->cf_next = NULL; 997c478bd9Sstevel@tonic-gate cp->cf_lineno = lineno; 1007c478bd9Sstevel@tonic-gate cp->cf_entry = entry; 1017c478bd9Sstevel@tonic-gate cp->cf_opts = opts; 1027c478bd9Sstevel@tonic-gate cp->cf_com = com; 1037c478bd9Sstevel@tonic-gate cp->cf_flags = flags; 104b493790cSbasabi if (entry != NULL) { 1057c478bd9Sstevel@tonic-gate Conflut = lut_add(Conflut, entry, cp); 1067c478bd9Sstevel@tonic-gate fn_list_adds(Confentries, entry); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate if (Confinfo == NULL) 1097c478bd9Sstevel@tonic-gate Confinfo = Confinfolast = cp; 1107c478bd9Sstevel@tonic-gate else { 1117c478bd9Sstevel@tonic-gate Confinfolast->cf_next = cp; 1127c478bd9Sstevel@tonic-gate Confinfolast = cp; 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate static char **Args; /* static buffer for args */ 1177c478bd9Sstevel@tonic-gate static int ArgsN; /* size of our static buffer */ 1187c478bd9Sstevel@tonic-gate static int ArgsI; /* index into Cmdargs as we walk table */ 1197c478bd9Sstevel@tonic-gate #define CONF_ARGS_INC 1024 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* callback for lut_walk to build a cmdargs vector */ 1227c478bd9Sstevel@tonic-gate static void 1237c478bd9Sstevel@tonic-gate fillargs(char *arg) 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate if (ArgsI >= ArgsN) { 1267c478bd9Sstevel@tonic-gate /* need bigger table */ 1277c478bd9Sstevel@tonic-gate Args = REALLOC(Args, sizeof (char *) * (ArgsN + CONF_ARGS_INC)); 1287c478bd9Sstevel@tonic-gate ArgsN += CONF_ARGS_INC; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate Args[ArgsI++] = arg; 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* isolate and return the next token */ 1347c478bd9Sstevel@tonic-gate static char * 1357c478bd9Sstevel@tonic-gate nexttok(char **ptrptr) 1367c478bd9Sstevel@tonic-gate { 1377c478bd9Sstevel@tonic-gate char *ptr = *ptrptr; 1387c478bd9Sstevel@tonic-gate char *eptr; 1397c478bd9Sstevel@tonic-gate char *quote = NULL; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate while (*ptr && isspace(*ptr)) 1427c478bd9Sstevel@tonic-gate ptr++; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate if (*ptr == '"' || *ptr == '\'') 1457c478bd9Sstevel@tonic-gate quote = ptr++; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate for (eptr = ptr; *eptr; eptr++) 1487c478bd9Sstevel@tonic-gate if (quote && *eptr == *quote) { 1497c478bd9Sstevel@tonic-gate /* found end quote */ 1507c478bd9Sstevel@tonic-gate *eptr++ = '\0'; 1517c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1527c478bd9Sstevel@tonic-gate return (ptr); 1537c478bd9Sstevel@tonic-gate } else if (!quote && isspace(*eptr)) { 1547c478bd9Sstevel@tonic-gate /* found end of unquoted area */ 1557c478bd9Sstevel@tonic-gate *eptr++ = '\0'; 1567c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1577c478bd9Sstevel@tonic-gate return (ptr); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 160b493790cSbasabi if (quote != NULL) 1617c478bd9Sstevel@tonic-gate err(EF_FILE|EF_JMP, "Unbalanced %c quote", *quote); 1627c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate *ptrptr = eptr; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate if (ptr == eptr) 1677c478bd9Sstevel@tonic-gate return (NULL); 1687c478bd9Sstevel@tonic-gate else 1697c478bd9Sstevel@tonic-gate return (ptr); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 173e9a193fcSJohn.Zolnowsky@Sun.COM * scan the memory image of a file 174e9a193fcSJohn.Zolnowsky@Sun.COM * returns: 0: error, 1: ok, 3: -P option found 1757c478bd9Sstevel@tonic-gate */ 176e9a193fcSJohn.Zolnowsky@Sun.COM static int 177*34969e74SJerry Jelinek conf_scan(const char *fname, char *buf, int buflen, int timescan) 1787c478bd9Sstevel@tonic-gate { 179e9a193fcSJohn.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; 184e9a193fcSJohn.Zolnowsky@Sun.COM char *entry, *comment; 1857c478bd9Sstevel@tonic-gate 186e9a193fcSJohn.Zolnowsky@Sun.COM ebuf = &buf[buflen]; 1877c478bd9Sstevel@tonic-gate 188e9a193fcSJohn.Zolnowsky@Sun.COM if (buf[buflen - 1] != '\n') 189e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_WARN|EF_FILE, "file %s doesn't end with newline, " 190e9a193fcSJohn.Zolnowsky@Sun.COM "last line ignored.", fname); 1917c478bd9Sstevel@tonic-gate 192e9a193fcSJohn.Zolnowsky@Sun.COM for (line = buf; line < ebuf; line = eline) { 193e9a193fcSJohn.Zolnowsky@Sun.COM char *ap; 194e9a193fcSJohn.Zolnowsky@Sun.COM struct opts *opts = NULL; 195e9a193fcSJohn.Zolnowsky@Sun.COM struct confinfo *cp; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate lineno++; 198e9a193fcSJohn.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++; 208e9a193fcSJohn.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; 225e9a193fcSJohn.Zolnowsky@Sun.COM if (eline >= ebuf) { 226e9a193fcSJohn.Zolnowsky@Sun.COM /* discard trailing unterminated line */ 227e9a193fcSJohn.Zolnowsky@Sun.COM continue; 228e9a193fcSJohn.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 */ 237e9a193fcSJohn.Zolnowsky@Sun.COM entry = nexttok(&line); 238e9a193fcSJohn.Zolnowsky@Sun.COM if (entry == NULL) { 239e9a193fcSJohn.Zolnowsky@Sun.COM /* it's just a comment line */ 240e9a193fcSJohn.Zolnowsky@Sun.COM if (!timescan) 241e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(lineno, entry, NULL, comment, 0); 242e9a193fcSJohn.Zolnowsky@Sun.COM continue; 243e9a193fcSJohn.Zolnowsky@Sun.COM } 244e9a193fcSJohn.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) 255e9a193fcSJohn.Zolnowsky@Sun.COM err(0, "%s version not supported " 256e9a193fcSJohn.Zolnowsky@Sun.COM "by this version of logadm.", 257e9a193fcSJohn.Zolnowsky@Sun.COM fname); 258e9a193fcSJohn.Zolnowsky@Sun.COM continue; 259e9a193fcSJohn.Zolnowsky@Sun.COM } 2607c478bd9Sstevel@tonic-gate 261e9a193fcSJohn.Zolnowsky@Sun.COM /* form an argv array */ 2627c478bd9Sstevel@tonic-gate ArgsI = 0; 2637c478bd9Sstevel@tonic-gate while (ap = nexttok(&line)) 2647c478bd9Sstevel@tonic-gate fillargs(ap); 265e9a193fcSJohn.Zolnowsky@Sun.COM Args[ArgsI] = NULL; 266e9a193fcSJohn.Zolnowsky@Sun.COM 267e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BEGIN { 268e9a193fcSJohn.Zolnowsky@Sun.COM if (SETJMP) { 269e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_FILE, "cannot process invalid entry %s", 270e9a193fcSJohn.Zolnowsky@Sun.COM entry); 271e9a193fcSJohn.Zolnowsky@Sun.COM ret = 0; 272e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BREAK; 2737c478bd9Sstevel@tonic-gate } 274e9a193fcSJohn.Zolnowsky@Sun.COM 275e9a193fcSJohn.Zolnowsky@Sun.COM if (timescan) { 276e9a193fcSJohn.Zolnowsky@Sun.COM /* append to config options */ 277e9a193fcSJohn.Zolnowsky@Sun.COM cp = lut_lookup(Conflut, entry); 278*34969e74SJerry Jelinek if (cp != NULL) { 279e9a193fcSJohn.Zolnowsky@Sun.COM opts = cp->cf_opts; 2807c478bd9Sstevel@tonic-gate } 281*34969e74SJerry Jelinek } 282e9a193fcSJohn.Zolnowsky@Sun.COM opts = opts_parse(opts, Args, OPTF_CONF); 283*34969e74SJerry Jelinek if (!timescan || cp == NULL) { 284*34969e74SJerry Jelinek /* 285*34969e74SJerry Jelinek * If we're not doing timescan, we track this 286*34969e74SJerry Jelinek * entry. If we are doing timescan and have 287*34969e74SJerry Jelinek * what looks like an orphaned entry (cp == 288*34969e74SJerry Jelinek * NULL) then we also have to track. See the 289*34969e74SJerry Jelinek * comment in rotatelog. We need to allow for 290*34969e74SJerry Jelinek * the case where the logname is not the same as 291*34969e74SJerry Jelinek * the log file name. 292*34969e74SJerry Jelinek */ 293e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(lineno, entry, opts, comment, 0); 294e9a193fcSJohn.Zolnowsky@Sun.COM } 295e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_END } 296e9a193fcSJohn.Zolnowsky@Sun.COM 297e9a193fcSJohn.Zolnowsky@Sun.COM if (ret == 1 && opts && opts_optarg(opts, "P") != NULL) 298e9a193fcSJohn.Zolnowsky@Sun.COM ret = 3; 299e9a193fcSJohn.Zolnowsky@Sun.COM } 300e9a193fcSJohn.Zolnowsky@Sun.COM 301e9a193fcSJohn.Zolnowsky@Sun.COM err_fileline(NULL, 0); 302e9a193fcSJohn.Zolnowsky@Sun.COM return (ret); 303e9a193fcSJohn.Zolnowsky@Sun.COM } 304e9a193fcSJohn.Zolnowsky@Sun.COM 305e9a193fcSJohn.Zolnowsky@Sun.COM /* 306e9a193fcSJohn.Zolnowsky@Sun.COM * conf_open -- open the configuration file, lock it if we have write perms 307e9a193fcSJohn.Zolnowsky@Sun.COM */ 308e9a193fcSJohn.Zolnowsky@Sun.COM int 309e9a193fcSJohn.Zolnowsky@Sun.COM conf_open(const char *cfname, const char *tfname, struct opts *cliopts) 310e9a193fcSJohn.Zolnowsky@Sun.COM { 311e9a193fcSJohn.Zolnowsky@Sun.COM struct stat stbuf1, stbuf2, stbuf3; 312e9a193fcSJohn.Zolnowsky@Sun.COM struct flock flock; 313e9a193fcSJohn.Zolnowsky@Sun.COM int ret; 314e9a193fcSJohn.Zolnowsky@Sun.COM 315e9a193fcSJohn.Zolnowsky@Sun.COM Confname = cfname; 316e9a193fcSJohn.Zolnowsky@Sun.COM Timesname = tfname; 317e9a193fcSJohn.Zolnowsky@Sun.COM Confentries = fn_list_new(NULL); 318e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_NONE; 319e9a193fcSJohn.Zolnowsky@Sun.COM 320e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_TIMES; 321e9a193fcSJohn.Zolnowsky@Sun.COM if (opts_count(cliopts, "Vn") != 0) 322e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_NONE; 323e9a193fcSJohn.Zolnowsky@Sun.COM else if (opts_count(cliopts, "rw") != 0) 324e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_BOTH; 325e9a193fcSJohn.Zolnowsky@Sun.COM 326e9a193fcSJohn.Zolnowsky@Sun.COM Singlefile = strcmp(Confname, Timesname) == 0; 327e9a193fcSJohn.Zolnowsky@Sun.COM if (Singlefile && Changing == CHG_TIMES) 328e9a193fcSJohn.Zolnowsky@Sun.COM Changing = CHG_BOTH; 329e9a193fcSJohn.Zolnowsky@Sun.COM 330e9a193fcSJohn.Zolnowsky@Sun.COM /* special case this so we don't even try locking the file */ 331e9a193fcSJohn.Zolnowsky@Sun.COM if (strcmp(Confname, "/dev/null") == 0) 332e9a193fcSJohn.Zolnowsky@Sun.COM return (0); 333e9a193fcSJohn.Zolnowsky@Sun.COM 334e9a193fcSJohn.Zolnowsky@Sun.COM while (Conffd == -1) { 335e9a193fcSJohn.Zolnowsky@Sun.COM Canchange = CHG_BOTH; 336e9a193fcSJohn.Zolnowsky@Sun.COM if ((Conffd = open(Confname, O_RDWR)) < 0) { 337e9a193fcSJohn.Zolnowsky@Sun.COM if (Changing == CHG_BOTH) 338e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Confname); 339e9a193fcSJohn.Zolnowsky@Sun.COM Canchange = CHG_TIMES; 340e9a193fcSJohn.Zolnowsky@Sun.COM if ((Conffd = open(Confname, O_RDONLY)) < 0) 341e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Confname); 342e9a193fcSJohn.Zolnowsky@Sun.COM } 343e9a193fcSJohn.Zolnowsky@Sun.COM 344e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_type = (Canchange == CHG_BOTH) ? F_WRLCK : F_RDLCK; 345e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_whence = SEEK_SET; 346e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_start = 0; 347e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_len = 1; 348e9a193fcSJohn.Zolnowsky@Sun.COM if (fcntl(Conffd, F_SETLKW, &flock) < 0) 349e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "flock on %s", Confname); 350e9a193fcSJohn.Zolnowsky@Sun.COM 351e9a193fcSJohn.Zolnowsky@Sun.COM /* wait until after file is locked to get filesize */ 352e9a193fcSJohn.Zolnowsky@Sun.COM if (fstat(Conffd, &stbuf1) < 0) 353e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "fstat on %s", Confname); 354e9a193fcSJohn.Zolnowsky@Sun.COM 355e9a193fcSJohn.Zolnowsky@Sun.COM /* verify that we've got a lock on the active file */ 356e9a193fcSJohn.Zolnowsky@Sun.COM if (stat(Confname, &stbuf2) < 0 || 357e9a193fcSJohn.Zolnowsky@Sun.COM !(stbuf2.st_dev == stbuf1.st_dev && 358e9a193fcSJohn.Zolnowsky@Sun.COM stbuf2.st_ino == stbuf1.st_ino)) { 359e9a193fcSJohn.Zolnowsky@Sun.COM /* wrong config file, try again */ 360e9a193fcSJohn.Zolnowsky@Sun.COM (void) close(Conffd); 361e9a193fcSJohn.Zolnowsky@Sun.COM Conffd = -1; 362e9a193fcSJohn.Zolnowsky@Sun.COM } 363e9a193fcSJohn.Zolnowsky@Sun.COM } 364e9a193fcSJohn.Zolnowsky@Sun.COM 365e9a193fcSJohn.Zolnowsky@Sun.COM while (!Singlefile && Timesfd == -1) { 366e9a193fcSJohn.Zolnowsky@Sun.COM if ((Timesfd = open(Timesname, O_CREAT|O_RDWR, 0644)) < 0) { 367e9a193fcSJohn.Zolnowsky@Sun.COM if (Changing != CHG_NONE) 368e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Timesname); 369e9a193fcSJohn.Zolnowsky@Sun.COM Canchange = CHG_NONE; 370e9a193fcSJohn.Zolnowsky@Sun.COM if ((Timesfd = open(Timesname, O_RDONLY)) < 0) 371e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "open %s", Timesname); 372e9a193fcSJohn.Zolnowsky@Sun.COM } 373e9a193fcSJohn.Zolnowsky@Sun.COM 374e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_type = (Canchange != CHG_NONE) ? F_WRLCK : F_RDLCK; 375e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_whence = SEEK_SET; 376e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_start = 0; 377e9a193fcSJohn.Zolnowsky@Sun.COM flock.l_len = 1; 378e9a193fcSJohn.Zolnowsky@Sun.COM if (fcntl(Timesfd, F_SETLKW, &flock) < 0) 379e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "flock on %s", Timesname); 380e9a193fcSJohn.Zolnowsky@Sun.COM 381e9a193fcSJohn.Zolnowsky@Sun.COM /* wait until after file is locked to get filesize */ 382e9a193fcSJohn.Zolnowsky@Sun.COM if (fstat(Timesfd, &stbuf2) < 0) 383e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "fstat on %s", Timesname); 384e9a193fcSJohn.Zolnowsky@Sun.COM 385e9a193fcSJohn.Zolnowsky@Sun.COM /* verify that we've got a lock on the active file */ 386e9a193fcSJohn.Zolnowsky@Sun.COM if (stat(Timesname, &stbuf3) < 0 || 387e9a193fcSJohn.Zolnowsky@Sun.COM !(stbuf2.st_dev == stbuf3.st_dev && 388e9a193fcSJohn.Zolnowsky@Sun.COM stbuf2.st_ino == stbuf3.st_ino)) { 389e9a193fcSJohn.Zolnowsky@Sun.COM /* wrong timestamp file, try again */ 390e9a193fcSJohn.Zolnowsky@Sun.COM (void) close(Timesfd); 391e9a193fcSJohn.Zolnowsky@Sun.COM Timesfd = -1; 392e9a193fcSJohn.Zolnowsky@Sun.COM continue; 393e9a193fcSJohn.Zolnowsky@Sun.COM } 394e9a193fcSJohn.Zolnowsky@Sun.COM 395e9a193fcSJohn.Zolnowsky@Sun.COM /* check that Timesname isn't an alias for Confname */ 396e9a193fcSJohn.Zolnowsky@Sun.COM if (stbuf2.st_dev == stbuf1.st_dev && 397e9a193fcSJohn.Zolnowsky@Sun.COM stbuf2.st_ino == stbuf1.st_ino) 398e9a193fcSJohn.Zolnowsky@Sun.COM err(0, "Timestamp file %s can't refer to " 399e9a193fcSJohn.Zolnowsky@Sun.COM "Configuration file %s", Timesname, Confname); 400e9a193fcSJohn.Zolnowsky@Sun.COM } 401e9a193fcSJohn.Zolnowsky@Sun.COM 402e9a193fcSJohn.Zolnowsky@Sun.COM Conflen = stbuf1.st_size; 403e9a193fcSJohn.Zolnowsky@Sun.COM Timeslen = stbuf2.st_size; 404e9a193fcSJohn.Zolnowsky@Sun.COM 405e9a193fcSJohn.Zolnowsky@Sun.COM if (Conflen == 0) 406e9a193fcSJohn.Zolnowsky@Sun.COM return (1); /* empty file, don't bother parsing it */ 407e9a193fcSJohn.Zolnowsky@Sun.COM 408e9a193fcSJohn.Zolnowsky@Sun.COM if ((Confbuf = (char *)mmap(0, Conflen, 409e9a193fcSJohn.Zolnowsky@Sun.COM PROT_READ | PROT_WRITE, MAP_PRIVATE, Conffd, 0)) == (char *)-1) 410e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "mmap on %s", Confname); 411e9a193fcSJohn.Zolnowsky@Sun.COM 412*34969e74SJerry Jelinek ret = conf_scan(Confname, Confbuf, Conflen, 0); 413e9a193fcSJohn.Zolnowsky@Sun.COM if (ret == 3 && !Singlefile && Canchange == CHG_BOTH) { 414e9a193fcSJohn.Zolnowsky@Sun.COM /* 415e9a193fcSJohn.Zolnowsky@Sun.COM * arrange to transfer any timestamps 416e9a193fcSJohn.Zolnowsky@Sun.COM * from conf_file to timestamps_file 417e9a193fcSJohn.Zolnowsky@Sun.COM */ 418e9a193fcSJohn.Zolnowsky@Sun.COM Changing = Changed = CHG_BOTH; 419e9a193fcSJohn.Zolnowsky@Sun.COM } 420e9a193fcSJohn.Zolnowsky@Sun.COM 421e9a193fcSJohn.Zolnowsky@Sun.COM if (Timesfd != -1 && Timeslen != 0) { 422e9a193fcSJohn.Zolnowsky@Sun.COM if ((Timesbuf = (char *)mmap(0, Timeslen, 423e9a193fcSJohn.Zolnowsky@Sun.COM PROT_READ | PROT_WRITE, MAP_PRIVATE, 424e9a193fcSJohn.Zolnowsky@Sun.COM Timesfd, 0)) == (char *)-1) 425e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "mmap on %s", Timesname); 426*34969e74SJerry Jelinek ret &= conf_scan(Timesname, Timesbuf, Timeslen, 1); 427e9a193fcSJohn.Zolnowsky@Sun.COM } 428e9a193fcSJohn.Zolnowsky@Sun.COM 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * possible future enhancement: go through and mark any entries: 4317c478bd9Sstevel@tonic-gate * logfile -P <date> 4327c478bd9Sstevel@tonic-gate * as DELETED if the logfile doesn't exist 4337c478bd9Sstevel@tonic-gate */ 434e9a193fcSJohn.Zolnowsky@Sun.COM 435e9a193fcSJohn.Zolnowsky@Sun.COM return (ret); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * conf_close -- close the configuration file 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate void 4427c478bd9Sstevel@tonic-gate conf_close(struct opts *opts) 4437c478bd9Sstevel@tonic-gate { 444e9a193fcSJohn.Zolnowsky@Sun.COM char cuname[PATH_MAX], tuname[PATH_MAX]; 445e9a193fcSJohn.Zolnowsky@Sun.COM int cfd, tfd; 446e9a193fcSJohn.Zolnowsky@Sun.COM FILE *cfp = NULL, *tfp = NULL; 447e9a193fcSJohn.Zolnowsky@Sun.COM boolean_t safe_update = B_TRUE; 4487c478bd9Sstevel@tonic-gate 449e9a193fcSJohn.Zolnowsky@Sun.COM if (Changed == CHG_NONE || opts_count(opts, "n") != 0) { 4507c478bd9Sstevel@tonic-gate if (opts_count(opts, "v")) 451e9a193fcSJohn.Zolnowsky@Sun.COM (void) out("# %s and %s unchanged\n", 452e9a193fcSJohn.Zolnowsky@Sun.COM Confname, Timesname); 453e9a193fcSJohn.Zolnowsky@Sun.COM goto cleanup; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 456e9a193fcSJohn.Zolnowsky@Sun.COM if (Debug > 1) { 457e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(stderr, "conf_close, saving logadm context:\n"); 458e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(stderr, NULL); 459e9a193fcSJohn.Zolnowsky@Sun.COM } 460e9a193fcSJohn.Zolnowsky@Sun.COM 461e9a193fcSJohn.Zolnowsky@Sun.COM cuname[0] = tuname[0] = '\0'; 462e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BEGIN { 463e9a193fcSJohn.Zolnowsky@Sun.COM if (SETJMP) { 464e9a193fcSJohn.Zolnowsky@Sun.COM safe_update = B_FALSE; 465e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_BREAK; 466e9a193fcSJohn.Zolnowsky@Sun.COM } 467e9a193fcSJohn.Zolnowsky@Sun.COM if (Changed == CHG_BOTH) { 468e9a193fcSJohn.Zolnowsky@Sun.COM if (Canchange != CHG_BOTH) 469e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_JMP, "internal error: attempting " 470e9a193fcSJohn.Zolnowsky@Sun.COM "to update %s without locking", Confname); 471e9a193fcSJohn.Zolnowsky@Sun.COM (void) snprintf(cuname, sizeof (cuname), "%sXXXXXX", 472e9a193fcSJohn.Zolnowsky@Sun.COM Confname); 473e9a193fcSJohn.Zolnowsky@Sun.COM if ((cfd = mkstemp(cuname)) == -1) 474e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "open %s replacement", 475e9a193fcSJohn.Zolnowsky@Sun.COM Confname); 476e9a193fcSJohn.Zolnowsky@Sun.COM if (opts_count(opts, "v")) 477e9a193fcSJohn.Zolnowsky@Sun.COM (void) out("# writing changes to %s\n", cuname); 478e9a193fcSJohn.Zolnowsky@Sun.COM if (fchmod(cfd, 0644) == -1) 479e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "chmod %s", cuname); 480e9a193fcSJohn.Zolnowsky@Sun.COM if ((cfp = fdopen(cfd, "w")) == NULL) 481e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fdopen on %s", cuname); 482e9a193fcSJohn.Zolnowsky@Sun.COM } else { 483e9a193fcSJohn.Zolnowsky@Sun.COM /* just toss away the configuration data */ 484e9a193fcSJohn.Zolnowsky@Sun.COM cfp = fopen("/dev/null", "w"); 485e9a193fcSJohn.Zolnowsky@Sun.COM } 486e9a193fcSJohn.Zolnowsky@Sun.COM if (!Singlefile) { 487e9a193fcSJohn.Zolnowsky@Sun.COM if (Canchange == CHG_NONE) 488e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_JMP, "internal error: attempting " 489e9a193fcSJohn.Zolnowsky@Sun.COM "to update %s without locking", Timesname); 490e9a193fcSJohn.Zolnowsky@Sun.COM (void) snprintf(tuname, sizeof (tuname), "%sXXXXXX", 491e9a193fcSJohn.Zolnowsky@Sun.COM Timesname); 492e9a193fcSJohn.Zolnowsky@Sun.COM if ((tfd = mkstemp(tuname)) == -1) 493e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "open %s replacement", 494e9a193fcSJohn.Zolnowsky@Sun.COM Timesname); 495e9a193fcSJohn.Zolnowsky@Sun.COM if (opts_count(opts, "v")) 496e9a193fcSJohn.Zolnowsky@Sun.COM (void) out("# writing changes to %s\n", tuname); 497e9a193fcSJohn.Zolnowsky@Sun.COM if (fchmod(tfd, 0644) == -1) 498e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "chmod %s", tuname); 499e9a193fcSJohn.Zolnowsky@Sun.COM if ((tfp = fdopen(tfd, "w")) == NULL) 500e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fdopen on %s", tuname); 501e9a193fcSJohn.Zolnowsky@Sun.COM } 502e9a193fcSJohn.Zolnowsky@Sun.COM 503e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(cfp, tfp); 504e9a193fcSJohn.Zolnowsky@Sun.COM if (fclose(cfp) < 0) 505e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fclose on %s", Confname); 506e9a193fcSJohn.Zolnowsky@Sun.COM if (tfp != NULL && fclose(tfp) < 0) 507e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS|EF_JMP, "fclose on %s", Timesname); 508e9a193fcSJohn.Zolnowsky@Sun.COM LOCAL_ERR_END } 509e9a193fcSJohn.Zolnowsky@Sun.COM 510e9a193fcSJohn.Zolnowsky@Sun.COM if (!safe_update) { 511e9a193fcSJohn.Zolnowsky@Sun.COM if (cuname[0] != 0) 512e9a193fcSJohn.Zolnowsky@Sun.COM (void) unlink(cuname); 513e9a193fcSJohn.Zolnowsky@Sun.COM if (tuname[0] != 0) 514e9a193fcSJohn.Zolnowsky@Sun.COM (void) unlink(tuname); 515e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_JMP, "unsafe to update configuration file " 516e9a193fcSJohn.Zolnowsky@Sun.COM "or timestamps"); 517e9a193fcSJohn.Zolnowsky@Sun.COM return; 518e9a193fcSJohn.Zolnowsky@Sun.COM } 519e9a193fcSJohn.Zolnowsky@Sun.COM 520e9a193fcSJohn.Zolnowsky@Sun.COM /* rename updated files into place */ 521e9a193fcSJohn.Zolnowsky@Sun.COM if (cuname[0] != '\0') 522e9a193fcSJohn.Zolnowsky@Sun.COM if (rename(cuname, Confname) < 0) 523e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "rename %s to %s", cuname, Confname); 524e9a193fcSJohn.Zolnowsky@Sun.COM if (tuname[0] != '\0') 525e9a193fcSJohn.Zolnowsky@Sun.COM if (rename(tuname, Timesname) < 0) 526e9a193fcSJohn.Zolnowsky@Sun.COM err(EF_SYS, "rename %s to %s", tuname, Timesname); 527e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_NONE; 528e9a193fcSJohn.Zolnowsky@Sun.COM 529e9a193fcSJohn.Zolnowsky@Sun.COM cleanup: 5307c478bd9Sstevel@tonic-gate if (Conffd != -1) { 5317c478bd9Sstevel@tonic-gate (void) close(Conffd); 5327c478bd9Sstevel@tonic-gate Conffd = -1; 5337c478bd9Sstevel@tonic-gate } 534e9a193fcSJohn.Zolnowsky@Sun.COM if (Timesfd != -1) { 535e9a193fcSJohn.Zolnowsky@Sun.COM (void) close(Timesfd); 536e9a193fcSJohn.Zolnowsky@Sun.COM Timesfd = -1; 537e9a193fcSJohn.Zolnowsky@Sun.COM } 5387c478bd9Sstevel@tonic-gate if (Conflut) { 5397c478bd9Sstevel@tonic-gate lut_free(Conflut, free); 5407c478bd9Sstevel@tonic-gate Conflut = NULL; 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate if (Confentries) { 5437c478bd9Sstevel@tonic-gate fn_list_free(Confentries); 5447c478bd9Sstevel@tonic-gate Confentries = NULL; 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* 5497c478bd9Sstevel@tonic-gate * conf_lookup -- lookup an entry in the config file 5507c478bd9Sstevel@tonic-gate */ 551e9a193fcSJohn.Zolnowsky@Sun.COM void * 5527c478bd9Sstevel@tonic-gate conf_lookup(const char *lhs) 5537c478bd9Sstevel@tonic-gate { 5547c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 5557c478bd9Sstevel@tonic-gate 556e9a193fcSJohn.Zolnowsky@Sun.COM if (cp != NULL) 5577c478bd9Sstevel@tonic-gate err_fileline(Confname, cp->cf_lineno); 558e9a193fcSJohn.Zolnowsky@Sun.COM return (cp); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate /* 5627c478bd9Sstevel@tonic-gate * conf_opts -- return the parsed opts for an entry 5637c478bd9Sstevel@tonic-gate */ 5647c478bd9Sstevel@tonic-gate struct opts * 5657c478bd9Sstevel@tonic-gate conf_opts(const char *lhs) 5667c478bd9Sstevel@tonic-gate { 5677c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 5687c478bd9Sstevel@tonic-gate 569e9a193fcSJohn.Zolnowsky@Sun.COM if (cp != NULL) 5707c478bd9Sstevel@tonic-gate return (cp->cf_opts); 571e9a193fcSJohn.Zolnowsky@Sun.COM return (opts_parse(NULL, NULL, OPTF_CONF)); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * conf_replace -- replace an entry in the config file 5767c478bd9Sstevel@tonic-gate */ 5777c478bd9Sstevel@tonic-gate void 5787c478bd9Sstevel@tonic-gate conf_replace(const char *lhs, struct opts *newopts) 5797c478bd9Sstevel@tonic-gate { 5807c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, lhs); 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate if (Conffd == -1) 5837c478bd9Sstevel@tonic-gate return; 5847c478bd9Sstevel@tonic-gate 585b493790cSbasabi if (cp != NULL) { 5867c478bd9Sstevel@tonic-gate cp->cf_opts = newopts; 587e9a193fcSJohn.Zolnowsky@Sun.COM /* cp->cf_args = NULL; */ 5887c478bd9Sstevel@tonic-gate if (newopts == NULL) 5897c478bd9Sstevel@tonic-gate cp->cf_flags |= CONFF_DELETED; 5907c478bd9Sstevel@tonic-gate } else 591e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(0, lhs, newopts, NULL, 0); 592e9a193fcSJohn.Zolnowsky@Sun.COM 593e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_BOTH; 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * conf_set -- set options for an entry in the config file 5987c478bd9Sstevel@tonic-gate */ 5997c478bd9Sstevel@tonic-gate void 6007c478bd9Sstevel@tonic-gate conf_set(const char *entry, char *o, const char *optarg) 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate struct confinfo *cp = lut_lookup(Conflut, entry); 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate if (Conffd == -1) 6057c478bd9Sstevel@tonic-gate return; 6067c478bd9Sstevel@tonic-gate 607b493790cSbasabi if (cp != NULL) { 6087c478bd9Sstevel@tonic-gate cp->cf_flags &= ~CONFF_DELETED; 6097c478bd9Sstevel@tonic-gate } else { 610e9a193fcSJohn.Zolnowsky@Sun.COM fillconflist(0, STRDUP(entry), 611e9a193fcSJohn.Zolnowsky@Sun.COM opts_parse(NULL, NULL, OPTF_CONF), NULL, 0); 6127c478bd9Sstevel@tonic-gate if ((cp = lut_lookup(Conflut, entry)) == NULL) 6137c478bd9Sstevel@tonic-gate err(0, "conf_set internal error"); 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate (void) opts_set(cp->cf_opts, o, optarg); 616e9a193fcSJohn.Zolnowsky@Sun.COM if (strcmp(o, "P") == 0) 617e9a193fcSJohn.Zolnowsky@Sun.COM Changed |= CHG_TIMES; 618e9a193fcSJohn.Zolnowsky@Sun.COM else 619e9a193fcSJohn.Zolnowsky@Sun.COM Changed = CHG_BOTH; 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate /* 6237c478bd9Sstevel@tonic-gate * conf_entries -- list all the entry names 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate struct fn_list * 6267c478bd9Sstevel@tonic-gate conf_entries(void) 6277c478bd9Sstevel@tonic-gate { 6287c478bd9Sstevel@tonic-gate return (Confentries); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate /* print the config file */ 6327c478bd9Sstevel@tonic-gate static void 633e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(FILE *cstream, FILE *tstream) 6347c478bd9Sstevel@tonic-gate { 6357c478bd9Sstevel@tonic-gate struct confinfo *cp; 636e9a193fcSJohn.Zolnowsky@Sun.COM char *exclude_opts = "PFfhnrvVw"; 637e9a193fcSJohn.Zolnowsky@Sun.COM const char *timestamp; 6387c478bd9Sstevel@tonic-gate 639e9a193fcSJohn.Zolnowsky@Sun.COM if (tstream == NULL) { 640e9a193fcSJohn.Zolnowsky@Sun.COM exclude_opts++; /* -P option goes to config file */ 641e9a193fcSJohn.Zolnowsky@Sun.COM } else { 642e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(tstream, gettext( 643e9a193fcSJohn.Zolnowsky@Sun.COM "# This file holds internal data for logadm(1M).\n" 644e9a193fcSJohn.Zolnowsky@Sun.COM "# Do not edit.\n")); 645e9a193fcSJohn.Zolnowsky@Sun.COM } 6467c478bd9Sstevel@tonic-gate for (cp = Confinfo; cp; cp = cp->cf_next) { 6477c478bd9Sstevel@tonic-gate if (cp->cf_flags & CONFF_DELETED) 6487c478bd9Sstevel@tonic-gate continue; 6497c478bd9Sstevel@tonic-gate if (cp->cf_entry) { 650e9a193fcSJohn.Zolnowsky@Sun.COM opts_printword(cp->cf_entry, cstream); 651e9a193fcSJohn.Zolnowsky@Sun.COM if (cp->cf_opts) 652e9a193fcSJohn.Zolnowsky@Sun.COM opts_print(cp->cf_opts, cstream, exclude_opts); 653e9a193fcSJohn.Zolnowsky@Sun.COM /* output timestamps to tstream */ 654e9a193fcSJohn.Zolnowsky@Sun.COM if (tstream != NULL && (timestamp = 655e9a193fcSJohn.Zolnowsky@Sun.COM opts_optarg(cp->cf_opts, "P")) != NULL) { 656e9a193fcSJohn.Zolnowsky@Sun.COM opts_printword(cp->cf_entry, tstream); 657e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(tstream, " -P "); 658e9a193fcSJohn.Zolnowsky@Sun.COM opts_printword(timestamp, tstream); 659e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(tstream, "\n"); 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate if (cp->cf_com) { 6637c478bd9Sstevel@tonic-gate if (cp->cf_entry) 664e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(cstream, " "); 665e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(cstream, "#%s", cp->cf_com); 6667c478bd9Sstevel@tonic-gate } 667e9a193fcSJohn.Zolnowsky@Sun.COM (void) fprintf(cstream, "\n"); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate #ifdef TESTMODULE 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* 6747c478bd9Sstevel@tonic-gate * test main for conf module, usage: a.out conffile 6757c478bd9Sstevel@tonic-gate */ 676b493790cSbasabi int 6777c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 6787c478bd9Sstevel@tonic-gate { 679e9a193fcSJohn.Zolnowsky@Sun.COM struct opts *opts; 680e9a193fcSJohn.Zolnowsky@Sun.COM 6817c478bd9Sstevel@tonic-gate err_init(argv[0]); 6827c478bd9Sstevel@tonic-gate setbuf(stdout, NULL); 683e9a193fcSJohn.Zolnowsky@Sun.COM opts_init(Opttable, Opttable_cnt); 684e9a193fcSJohn.Zolnowsky@Sun.COM 685e9a193fcSJohn.Zolnowsky@Sun.COM opts = opts_parse(NULL, NULL, 0); 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if (argc != 2) 6887c478bd9Sstevel@tonic-gate err(EF_RAW, "usage: %s conffile\n", argv[0]); 6897c478bd9Sstevel@tonic-gate 690e9a193fcSJohn.Zolnowsky@Sun.COM conf_open(argv[1], argv[1], opts); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate printf("conffile <%s>:\n", argv[1]); 693e9a193fcSJohn.Zolnowsky@Sun.COM conf_print(stdout, NULL); 6947c478bd9Sstevel@tonic-gate 695e9a193fcSJohn.Zolnowsky@Sun.COM conf_close(opts); 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate err_done(0); 698b493790cSbasabi /* NOTREACHED */ 699b493790cSbasabi return (0); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate #endif /* TESTMODULE */ 703