Add a command-line option of '-s', which indicates that newsyslog should

not send a signal to any processes.  Also add a config-file flag of 'N' or
'n', which indicates that the given logfile has no process which needs a
signal when it is rotated.  Both of these are based on changes NetBSD
has made, although the implementation is somewhat different.

PR:		bin/36553  (2nd half)
Reviewed by:	no objections on freebsd-arch
Obtained from:	NetBSD (in spirit, at least)
MFC after:	3 weeks
This commit is contained in:
Garance A Drosehn 2003-03-02 22:05:17 +00:00
parent 7f760c4890
commit f2c3715aa7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=111768

View File

@ -64,14 +64,19 @@ static const char rcsid[] =
#define dbtob(db) ((unsigned)(db) << UBSHIFT)
#endif
#define CE_COMPACT 1 /* Compact the achived log files */
#define CE_BINARY 2 /* Logfile is in binary, don't add */
#define CE_BZCOMPACT 8 /* Compact the achived log files with bzip2 */
/* status messages */
#define CE_TRIMAT 4 /* trim at a specific time */
#define CE_GLOB 16 /* name of the log is file name pattern */
#define CE_COMPACTWAIT 32 /* wait till compressing finishes before */
/* starting the next one */
/*
* Bit-values for the 'flags' parsed from a config-file entry.
*/
#define CE_COMPACT 0x0001 /* Compact the achived log files with gzip. */
#define CE_BZCOMPACT 0x0002 /* Compact the achived log files with bzip2. */
#define CE_COMPACTWAIT 0x0004 /* wait until compressing one file finishes */
/* before starting the next step. */
#define CE_BINARY 0x0008 /* Logfile is in binary, do not add status */
/* messages to logfile(s) when rotating. */
#define CE_NOSIGNAL 0x0010 /* There is no process to signal when */
/* trimming this file. */
#define CE_TRIMAT 0x0020 /* trim file at a specific time. */
#define CE_GLOB 0x0040 /* name of the log is file name pattern. */
#define NONE -1
@ -97,6 +102,7 @@ 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 */
int noaction = 0; /* Don't do anything, just show it */
int nosignal; /* Do not send any signals */
int force = 0; /* Force the trim no matter what */
char *archdirname; /* Directory path to old logfiles archive */
const char *conf = _PATH_CONF; /* Configuration file to use */
@ -117,9 +123,10 @@ 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, int def_cfg);
static int log_trim(char *log, int def_cfg);
static void dotrim(const struct conf_entry *trim_ent, char *log,
int numdays, int flags, int perm, int owner_uid,
int group_gid, int sig);
static int log_trim(const char *log, const struct conf_entry *log_ent);
static void compress_log(char *log, int dowait);
static void bzcompress_log(char *log, int dowait);
static int sizefile(char *file);
@ -131,6 +138,14 @@ static void movefile(char *from, char *to, int perm, int owner_uid,
static void createdir(char *dirpart);
static time_t parseDWM(char *s, char *errline);
/*
* All the following are defined to work on an 'int', in the
* range 0 to 255, plus EOF. Define wrappers which can take
* values of type 'char', either signed or unsigned.
*/
#define isspacech(Anychar) isspace(((int) Anychar) & 255)
#define tolowerch(Anychar) tolower(((int) Anychar) & 255)
int
main(int argc, char **argv)
{
@ -244,7 +259,6 @@ static void
do_entry(struct conf_entry * ent)
{
int size, modtime;
const char *pid_file;
if (verbose) {
if (ent->flags & CE_COMPACT)
@ -292,18 +306,8 @@ do_entry(struct conf_entry * ent)
printf("%s <%d>: trimming\n",
ent->log, ent->numlogs);
}
if (ent->pid_file) {
pid_file = ent->pid_file;
} else {
/* Only try to notify syslog if we are root */
if (needroot)
pid_file = _PATH_SYSLOGPID;
else
pid_file = NULL;
}
dotrim(ent->log, pid_file, ent->numlogs,
ent->flags, ent->permissions, ent->uid, ent->gid,
ent->sig, ent->def_cfg);
dotrim(ent, ent->log, ent->numlogs, ent->flags,
ent->permissions, ent->uid, ent->gid, ent->sig);
} else {
if (verbose)
printf("--> skipping\n");
@ -328,29 +332,35 @@ PRS(int argc, char **argv)
if ((p = strchr(hostname, '.'))) {
*p = '\0';
}
while ((c = getopt(argc, argv, "nrvFf:a:")) != -1)
/* Parse command line options. */
while ((c = getopt(argc, argv, "a:f:nrsvF")) != -1)
switch (c) {
case 'n':
noaction++;
break;
case 'a':
archtodir++;
archdirname = optarg;
break;
case 'f':
conf = optarg;
break;
case 'n':
noaction++;
break;
case 'r':
needroot = 0;
break;
case 's':
nosignal = 1;
break;
case 'v':
verbose++;
break;
case 'f':
conf = optarg;
break;
case 'F':
force++;
break;
default:
usage();
/* NOTREACHED */
}
}
@ -359,7 +369,7 @@ usage(void)
{
fprintf(stderr,
"usage: newsyslog [-Fnrv] [-f config-file] [-a directory] [ filename ... ]\n");
"usage: newsyslog [-Fnrsv] [-f config-file] [-a directory] [ filename ... ]\n");
exit(1);
}
@ -574,21 +584,42 @@ parse_file(char **files)
*parse = '\0';
}
while (q && *q && !isspace(*q)) {
if ((*q == 'Z') || (*q == 'z'))
working->flags |= CE_COMPACT;
else if ((*q == 'J') || (*q == 'j'))
working->flags |= CE_BZCOMPACT;
else if ((*q == 'B') || (*q == 'b'))
for (; q && *q && !isspacech(*q); q++) {
switch (tolowerch(*q)) {
case 'b':
working->flags |= CE_BINARY;
else if ((*q == 'G') || (*q == 'c'))
break;
case 'c':
/*
* netbsd uses 'c' for "create". We will
* temporarily accept it for 'g', because
* earlier freebsd versions had a typo
* of ('G' || 'c')...
*/
warnx("Assuming 'g' for 'c' in flags for line:\n%s",
errline);
/* FALLTHROUGH */
case 'g':
working->flags |= CE_GLOB;
else if ((*q == 'W') || (*q == 'w'))
break;
case 'j':
working->flags |= CE_BZCOMPACT;
break;
case 'n':
working->flags |= CE_NOSIGNAL;
break;
case 'w':
working->flags |= CE_COMPACTWAIT;
else if (*q != '-')
break;
case 'z':
working->flags |= CE_COMPACT;
break;
case '-':
break;
default:
errx(1, "illegal flag in config file -- %c",
*q);
q++;
}
}
if (eol)
@ -633,7 +664,46 @@ parse_file(char **files)
if (working->sig < 1 || working->sig >= NSIG)
goto err_sig;
}
/*
* Finish figuring out what pid-file to use (if any) in
* later processing if this logfile needs to be rotated.
*/
if ((working->flags & CE_NOSIGNAL) == CE_NOSIGNAL) {
/*
* This config-entry specified 'n' for nosignal,
* see if it also specified an explicit pid_file.
* This would be a pretty pointless combination.
*/
if (working->pid_file != NULL) {
warnx("Ignoring '%s' because flag 'n' was specified in line:\n%s",
working->pid_file, errline);
free(working->pid_file);
working->pid_file = NULL;
}
} else if (nosignal) {
/*
* While this entry might usually signal some
* process via the pid-file, newsyslog was run
* with '-s', so quietly ignore the pid-file.
*/
if (working->pid_file != NULL) {
free(working->pid_file);
working->pid_file = NULL;
}
} else if (working->pid_file == NULL) {
/*
* This entry did not specify the 'n' flag, which
* means it should signal syslogd unless it had
* specified some other pid-file. But we only
* try to notify syslog if we are root
*/
if (needroot)
working->pid_file = strdup(_PATH_SYSLOGPID);
}
free(errline);
errline = NULL;
}
(void) fclose(f);
@ -699,8 +769,8 @@ 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 def_cfg)
dotrim(const struct conf_entry *trim_ent, char *log, int numdays, int flags,
int perm, int owner_uid, int group_gid, int sig)
{
char dirpart[MAXPATHLEN], namepart[MAXPATHLEN];
char file1[MAXPATHLEN], file2[MAXPATHLEN];
@ -817,7 +887,7 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
}
if (!noaction && !(flags & CE_BINARY)) {
/* Report the trimming to the old log */
(void) log_trim(log, def_cfg);
(void) log_trim(log, trim_ent);
}
if (!_numdays) {
@ -851,7 +921,7 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
(void) close(fd);
if (!(flags & CE_BINARY)) {
/* Add status message to new log file */
if (log_trim(tfile, def_cfg))
if (log_trim(tfile, trim_ent))
err(1, "can't add status message to log");
}
}
@ -867,9 +937,9 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
pid = 0;
need_notification = notified = 0;
if (pid_file != NULL) {
if (trim_ent->pid_file != NULL) {
need_notification = 1;
pid = get_pid(pid_file);
pid = get_pid(trim_ent->pid_file);
}
if (pid) {
if (noaction) {
@ -919,7 +989,7 @@ 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, int def_cfg)
log_trim(const char *log, const struct conf_entry *log_ent)
{
FILE *f;
const char *xtra;
@ -927,7 +997,7 @@ log_trim(char *log, int def_cfg)
if ((f = fopen(log, "a")) == NULL)
return (-1);
xtra = "";
if (def_cfg)
if (log_ent->def_cfg)
xtra = " using <default> rule";
fprintf(f, "%s %s newsyslog[%d]: logfile turned over%s\n",
daytime, hostname, (int) getpid(), xtra);