/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2013, Joyent, Inc. All rights reserved.
*/
/*
*/
#include <stdio.h>
#include <libintl.h>
#include <fcntl.h>
#include <ctype.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include "err.h"
#include "lut.h"
#include "fn.h"
#include "opts.h"
#include "conf.h"
/* forward declarations of functions private to this module */
#define CHG_NONE 0
/*
* our structured representation of the configuration file
* is made up of a list of these
*/
struct confinfo {
int cf_flags;
};
/* allocate & fill in another entry in our list */
static void
{
}
else {
Confinfolast = cp;
}
}
/* callback for lut_walk to build a cmdargs vector */
static void
{
/* need bigger table */
ArgsN += CONF_ARGS_INC;
}
}
/* isolate and return the next token */
static char *
{
char *eptr;
ptr++;
/* found end quote */
*eptr++ = '\0';
return (ptr);
/* found end of unquoted area */
*eptr++ = '\0';
return (ptr);
}
/*NOTREACHED*/
return (NULL);
else
return (ptr);
}
/*
* scan the memory image of a file
* returns: 0: error, 1: ok, 3: -P option found
*/
static int
{
int lineno = 0;
char *line;
char *eline;
char *ebuf;
"last line ignored.", fname);
char *ap;
lineno++;
/* check for continued lines */
*eline = ' ';
lineno++;
continue;
}
/* check for comments */
*eline = '\0';
continue;
}
/* check for end of line */
if (*eline == '\n')
break;
}
/* discard trailing unterminated line */
continue;
}
*eline++ = '\0';
/*
* now we have the entry, if any, at "line"
* and the comment, if any, at "comment"
*/
/* entry is first token */
/* it's just a comment line */
if (!timescan)
continue;
}
/*
* we somehow opened some future format
* conffile that we likely don't understand.
* if the given version is "1" then go on,
* otherwise someone is mixing versions
* and we can't help them other than to
* print an error and exit.
*/
err(0, "%s version not supported "
"by this version of logadm.",
fname);
continue;
}
/* form an argv array */
ArgsI = 0;
/*
* If there is no next token on the line, make sure that
* we get a non-NULL Args array.
*/
if (SETJMP) {
entry);
ret = 0;
}
if (timescan) {
/* append to config options */
}
}
/*
* If we're not doing timescan, we track this
* entry. If we are doing timescan and have
* what looks like an orphaned entry (cp ==
* NULL) then we also have to track. See the
* comment in rotatelog. We need to allow for
* the case where the logname is not the same as
* the log file name.
*/
}
ret = 3;
}
err_fileline(NULL, 0);
return (ret);
}
/*
* conf_open -- open the configuration file, lock it if we have write perms
*/
int
{
int ret;
/* special case this so we don't even try locking the file */
return (0);
while (Conffd == -1) {
}
/* wait until after file is locked to get filesize */
/* verify that we've got a lock on the active file */
/* wrong config file, try again */
Conffd = -1;
}
}
}
/* wait until after file is locked to get filesize */
/* verify that we've got a lock on the active file */
/* wrong timestamp file, try again */
Timesfd = -1;
continue;
}
/* check that Timesname isn't an alias for Confname */
err(0, "Timestamp file %s can't refer to "
}
if (Conflen == 0)
return (1); /* empty file, don't bother parsing it */
/*
* arrange to transfer any timestamps
* from conf_file to timestamps_file
*/
}
Timesfd, 0)) == (char *)-1)
}
/*
* possible future enhancement: go through and mark any entries:
* logfile -P <date>
* as DELETED if the logfile doesn't exist
*/
return (ret);
}
/*
* conf_close -- close the configuration file
*/
void
{
(void) out("# %s and %s unchanged\n",
goto cleanup;
}
if (Debug > 1) {
}
if (SETJMP) {
}
"to update %s without locking", Confname);
Confname);
Confname);
} else {
/* just toss away the configuration data */
}
if (!Singlefile) {
"to update %s without locking", Timesname);
}
if (!safe_update) {
if (cuname[0] != 0)
if (tuname[0] != 0)
"or timestamps");
return;
}
/* rename updated files into place */
if (cuname[0] != '\0')
if (tuname[0] != '\0')
if (Conffd != -1) {
Conffd = -1;
}
if (Timesfd != -1) {
Timesfd = -1;
}
if (Conflut) {
}
if (Confentries) {
Confentries = NULL;
}
}
/*
* conf_lookup -- lookup an entry in the config file
*/
void *
{
return (cp);
}
/*
* conf_opts -- return the parsed opts for an entry
*/
struct opts *
{
}
/*
* conf_replace -- replace an entry in the config file
*/
void
{
if (Conffd == -1)
return;
/* cp->cf_args = NULL; */
} else
}
/*
* conf_set -- set options for an entry in the config file
*/
void
{
if (Conffd == -1)
return;
} else {
err(0, "conf_set internal error");
}
if (strcmp(o, "P") == 0)
else
}
/*
* conf_entries -- list all the entry names
*/
struct fn_list *
conf_entries(void)
{
return (Confentries);
}
/* print the config file */
static void
{
const char *timestamp;
exclude_opts++; /* -P option goes to config file */
} else {
"# This file holds internal data for logadm(1M).\n"
"# Do not edit.\n"));
}
continue;
/* output timestamps to tstream */
}
}
}
}
}
#ifdef TESTMODULE
/*
* test main for conf module, usage: a.out conffile
*/
int
{
if (argc != 2)
err_done(0);
/* NOTREACHED */
return (0);
}
#endif /* TESTMODULE */