summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorgad <gad@FreeBSD.org>2003-02-24 00:51:41 +0000
committergad <gad@FreeBSD.org>2003-02-24 00:51:41 +0000
commit06f0413c15c9b30e7951763c79d1d49358f870f6 (patch)
tree79762d40ff2172a32664e0f8f82a14c1239dfc6a /usr.sbin
parent6e6d69e258e9ee8fe9172340163ac3665d2c4ad9 (diff)
downloadFreeBSD-src-06f0413c15c9b30e7951763c79d1d49358f870f6.zip
FreeBSD-src-06f0413c15c9b30e7951763c79d1d49358f870f6.tar.gz
Add the idea of a "default rotate action", which will be used if a file is
specified at runtime, but that filename is not listed in the newsyslog.conf file. This default-action can be changed by having a line in newsyslog.conf with the filename of "<default>". Before this change, the program would quietly ignore the given file. An update to the man page will be written after I finish some other updates to newsyslog.c. Reviewed by: no objections from freebsd-arch MFC after: 3 weeks
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/newsyslog/newsyslog.c227
1 files changed, 194 insertions, 33 deletions
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index 041a948..1d9c82e 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -87,9 +87,12 @@ struct conf_entry {
int permissions; /* File permissions on the log */
int flags; /* CE_COMPACT, CE_BZCOMPACT, CE_BINARY */
int sig; /* Signal to send */
+ int def_cfg; /* Using the <default> rule for this file */
struct conf_entry *next;/* Linked list pointer */
};
+#define DEFAULT_MARKER "<default>"
+
int archtodir = 0; /* Archive old logfiles to other directory */
int verbose = 0; /* Print out what's going on */
int needroot = 1; /* Root privs are necessary */
@@ -109,11 +112,14 @@ static char *sob(char *p);
static char *son(char *p);
static char *missing_field(char *p, char *errline);
static void do_entry(struct conf_entry * ent);
+static void free_entry(struct conf_entry *ent);
+static struct conf_entry *init_entry(const char *fname,
+ struct conf_entry *src_entry);
static void PRS(int argc, char **argv);
static void usage(void);
static void dotrim(char *log, const char *pid_file, int numdays, int falgs,
- int perm, int owner_uid, int group_gid, int sig);
-static int log_trim(char *log);
+ int perm, int owner_uid, int group_gid, int sig, int def_cfg);
+static int log_trim(char *log, int def_cfg);
static void compress_log(char *log, int dowait);
static void bzcompress_log(char *log, int dowait);
static int sizefile(char *file);
@@ -152,7 +158,7 @@ main(int argc, char **argv)
}
}
p = p->next;
- free((char *) q);
+ free_entry(q);
q = p;
}
while (wait(NULL) > 0 || errno == EINTR)
@@ -160,6 +166,77 @@ main(int argc, char **argv)
return (0);
}
+static struct conf_entry *
+init_entry(const char *fname, struct conf_entry *src_entry)
+{
+ struct conf_entry *tempwork;
+
+ if (verbose > 4)
+ printf("\t--> [creating entry for %s]\n", fname);
+
+ tempwork = malloc(sizeof(struct conf_entry));
+ if (tempwork == NULL)
+ err(1, "malloc of conf_entry for %s", fname);
+
+ tempwork->log = strdup(fname);
+ if (tempwork->log == NULL)
+ err(1, "strdup for %s", fname);
+
+ if (src_entry != NULL) {
+ tempwork->pid_file = NULL;
+ if (src_entry->pid_file)
+ tempwork->pid_file = strdup(src_entry->pid_file);
+ tempwork->uid = src_entry->uid;
+ tempwork->gid = src_entry->gid;
+ tempwork->numlogs = src_entry->numlogs;
+ tempwork->size = src_entry->size;
+ tempwork->hours = src_entry->hours;
+ tempwork->trim_at = src_entry->trim_at;
+ tempwork->permissions = src_entry->permissions;
+ tempwork->flags = src_entry->flags;
+ tempwork->sig = src_entry->sig;
+ tempwork->def_cfg = src_entry->def_cfg;
+ } else {
+ /* Initialize as a "do-nothing" entry */
+ tempwork->pid_file = NULL;
+ tempwork->uid = NONE;
+ tempwork->gid = NONE;
+ tempwork->numlogs = 1;
+ tempwork->size = -1;
+ tempwork->hours = -1;
+ tempwork->trim_at = (time_t)0;
+ tempwork->permissions = 0;
+ tempwork->flags = 0;
+ tempwork->sig = SIGHUP;
+ tempwork->def_cfg = 0;
+ }
+ tempwork->next = NULL;
+
+ return (tempwork);
+}
+
+static void
+free_entry(struct conf_entry *ent)
+{
+
+ if (ent == NULL)
+ return;
+
+ if (ent->log != NULL) {
+ if (verbose > 4)
+ printf("\t--> [freeing entry for %s]\n", ent->log);
+ free(ent->log);
+ ent->log = NULL;
+ }
+
+ if (ent->pid_file != NULL) {
+ free(ent->pid_file);
+ ent->pid_file = NULL;
+ }
+
+ free(ent);
+}
+
static void
do_entry(struct conf_entry * ent)
{
@@ -223,7 +300,7 @@ do_entry(struct conf_entry * ent)
}
dotrim(ent->log, pid_file, ent->numlogs,
ent->flags, ent->permissions, ent->uid, ent->gid,
- ent->sig);
+ ent->sig, ent->def_cfg);
} else {
if (verbose)
printf("--> skipping\n");
@@ -279,7 +356,7 @@ usage(void)
{
fprintf(stderr,
- "usage: newsyslog [-Fnrv] [-f config-file] [-a directory]\n");
+ "usage: newsyslog [-Fnrv] [-f config-file] [-a directory] [ filename ... ]\n");
exit(1);
}
@@ -293,13 +370,13 @@ parse_file(char **files)
FILE *f;
char line[BUFSIZ], *parse, *q;
char *cp, *errline, *group;
- char **p;
- struct conf_entry *first, *working;
+ char **given;
+ struct conf_entry *defconf, *first, *working, *worklist;
struct passwd *pass;
struct group *grp;
int eol;
- first = working = NULL;
+ defconf = first = working = worklist = NULL;
if (strcmp(conf, "-"))
f = fopen(conf, "r");
@@ -331,27 +408,55 @@ parse_file(char **files)
errline);
*parse = '\0';
+ /*
+ * If newsyslog was run with a list of specific filenames,
+ * then this line of the config file should be skipped if
+ * it is NOT one of those given files (except that we do
+ * want any line that defines the <default> action).
+ *
+ * XXX - note that CE_GLOB processing is *NOT* done when
+ * trying to match a filename given on the command!
+ */
if (*files) {
- for (p = files; *p; ++p)
- if (strcmp(*p, q) == 0)
- break;
- if (!*p)
+ if (strcasecmp(DEFAULT_MARKER, q) != 0) {
+ for (given = files; *given; ++given) {
+ if (strcmp(*given, q) == 0)
+ break;
+ }
+ if (!*given)
+ continue;
+ }
+ if (verbose > 2)
+ printf("\t+ Matched entry %s\n", q);
+ } else {
+ /*
+ * If no files were specified on the command line,
+ * then we can skip any line which defines the
+ * default action.
+ */
+ if (strcasecmp(DEFAULT_MARKER, q) == 0) {
+ if (verbose > 2)
+ printf("\t+ Ignoring entry for %s\n",
+ q);
continue;
+ }
}
- if (!first) {
- if ((working = malloc(sizeof(struct conf_entry))) ==
- NULL)
- err(1, "malloc");
- first = working;
+ working = init_entry(q, NULL);
+ if (strcasecmp(DEFAULT_MARKER, q) == 0) {
+ if (defconf != NULL) {
+ warnx("Ignoring duplicate entry for %s!", q);
+ free_entry(working);
+ continue;
+ }
+ defconf = working;
} else {
- if ((working->next = malloc(sizeof(struct conf_entry)))
- == NULL)
- err(1, "malloc");
- working = working->next;
+ if (!first)
+ first = working;
+ else
+ worklist->next = working;
+ worklist = working;
}
- if ((working->log = strdup(q)) == NULL)
- err(1, "strdup");
q = parse = missing_field(sob(++parse), errline);
parse = son(parse);
@@ -527,9 +632,57 @@ parse_file(char **files)
}
free(errline);
}
- if (working)
- working->next = (struct conf_entry *) NULL;
(void) fclose(f);
+
+ /*
+ * The entire config file has been processed. If there were
+ * no specific files given on the run command, then the work
+ * of this routine is done.
+ */
+ if (*files == NULL)
+ return (first);
+
+ /*
+ * If the program was given a specific list of files to process,
+ * it may be that some of those files were not listed in the
+ * config file. Those unlisted files should get the default
+ * rotation action. First, create the default-rotation action
+ * if none was found in the config file.
+ */
+ if (defconf == NULL) {
+ working = init_entry(DEFAULT_MARKER, NULL);
+ working->numlogs = 3;
+ working->size = 50;
+ working->permissions = S_IRUSR|S_IWUSR;
+ defconf = working;
+ }
+
+ for (given = files; *given; ++given) {
+ for (working = first; working; working = working->next) {
+ if (strcmp(*given, working->log) == 0)
+ break;
+ }
+ if (working != NULL)
+ continue;
+ if (verbose > 2)
+ printf("\t+ No entry for %s (will use %s)\n",
+ *given, DEFAULT_MARKER);
+ /*
+ * This given file was not found in the config file.
+ * Add another item on to our work list, based on the
+ * default entry.
+ */
+ working = init_entry(*given, defconf);
+ if (!first)
+ first = working;
+ else
+ worklist->next = working;
+ /* This is a file that was *not* found in config file */
+ working->def_cfg = 1;
+ worklist = working;
+ }
+
+ free_entry(defconf);
return (first);
}
@@ -544,7 +697,7 @@ missing_field(char *p, char *errline)
static void
dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
- int owner_uid, int group_gid, int sig)
+ int owner_uid, int group_gid, int sig, int def_cfg)
{
char dirpart[MAXPATHLEN], namepart[MAXPATHLEN];
char file1[MAXPATHLEN], file2[MAXPATHLEN];
@@ -659,8 +812,10 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
(void) chown(zfile2, owner_uid, group_gid);
}
}
- if (!noaction && !(flags & CE_BINARY))
- (void) log_trim(log); /* Report the trimming to the old log */
+ if (!noaction && !(flags & CE_BINARY)) {
+ /* Report the trimming to the old log */
+ (void) log_trim(log, def_cfg);
+ }
if (!_numdays) {
if (noaction)
@@ -691,9 +846,11 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
if (fchown(fd, owner_uid, group_gid))
err(1, "can't chmod new log file");
(void) close(fd);
- if (!(flags & CE_BINARY))
- if (log_trim(tfile)) /* Add status message */
+ if (!(flags & CE_BINARY)) {
+ /* Add status message to new log file */
+ if (log_trim(tfile, def_cfg))
err(1, "can't add status message to log");
+ }
}
if (noaction)
printf("chmod %o %s...\n", perm, log);
@@ -759,14 +916,18 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
/* Log the fact that the logs were turned over */
static int
-log_trim(char *log)
+log_trim(char *log, int def_cfg)
{
FILE *f;
+ const char *xtra;
if ((f = fopen(log, "a")) == NULL)
return (-1);
- fprintf(f, "%s %s newsyslog[%d]: logfile turned over\n",
- daytime, hostname, (int) getpid());
+ xtra = "";
+ if (def_cfg)
+ xtra = " using <default> rule";
+ fprintf(f, "%s %s newsyslog[%d]: logfile turned over%s\n",
+ daytime, hostname, (int) getpid(), xtra);
if (fclose(f) == EOF)
err(1, "log_trim: fclose:");
return (0);
OpenPOWER on IntegriCloud