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
fillconflist(int lineno,const char * entry,struct opts * opts,const char * com,int flags)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
fillargs(char * arg)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 *
nexttok(char ** ptrptr)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
conf_scan(const char * fname,char * buf,int buflen,int timescan)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
conf_open(const char * cfname,const char * tfname,struct opts * cliopts)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
conf_close(struct opts * opts)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 *
conf_lookup(const char * lhs)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 *
conf_opts(const char * lhs)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
conf_replace(const char * lhs,struct opts * newopts)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
conf_set(const char * entry,char * o,const char * optarg)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 *
conf_entries(void)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
conf_print(FILE * cstream,FILE * tstream)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
main(int argc,char * argv[])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