Add a config-file flag of 'U' or 'u' to indicate that the pid-file

will contain the pid for a process group.  This means the file must
contain a negative value (as would be needed in the 'kill' commmand).
I still need to write man-page update before MFC-ing.

This started by rewriting the get_pid() routine.  Later I looked at
what OpenBSD has, and included a few ideas from their send_signal()
routine.  So, parts of this change are from OpenBSD, even though
OpenBSD does not actually have a 'U' flag.

PR:		bin/28435
Reviewed by:	no objections on freebsd-arch
MFC after:	3 weeks
This commit is contained in:
Garance A Drosehn 2003-03-08 20:07:01 +00:00
parent 09f958046c
commit ae77078c25

View File

@ -71,6 +71,8 @@ static const char rcsid[] =
/* 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 CE_SIGNALGROUP 0x0080 /* Signal a process-group instead of a single */
/* process when trimming this file. */
#define MIN_PID 5 /* Don't touch pids lower than this */
#define MAX_PID 99999 /* was lower, see /usr/include/sys/proc.h */
@ -134,7 +136,7 @@ static void compress_log(char *log, int dowait);
static void bzcompress_log(char *log, int dowait);
static int sizefile(char *file);
static int age_old_log(char *file);
static pid_t get_pid(const char *pid_file);
static int send_signal(const struct conf_entry *ent);
static time_t parse8601(char *s, char *errline);
static void movefile(char *from, char *to, int perm, uid_t owner_uid,
gid_t group_gid);
@ -363,6 +365,102 @@ do_entry(struct conf_entry * ent)
#undef REASON_MAX
}
/* Send a signal to the pid specified by pidfile */
static int
send_signal(const struct conf_entry *ent)
{
pid_t target_pid;
int did_notify;
FILE *f;
long minok, maxok, rval;
const char *target_name;
char *endp, *linep, line[BUFSIZ];
did_notify = 0;
f = fopen(ent->pid_file, "r");
if (f == NULL) {
warn("can't open pid file: %s", ent->pid_file);
return (did_notify);
/* NOTREACHED */
}
if (fgets(line, BUFSIZ, f) == NULL) {
/*
* XXX - If the pid file is empty, is that really a
* problem? Wouldn't that mean that the process
* has shut down? In that case there would be no
* problem with compressing the rotated log file.
*/
if (feof(f))
warnx("pid file is empty: %s", ent->pid_file);
else
warn("can't read from pid file: %s", ent->pid_file);
(void) fclose(f);
return (did_notify);
/* NOTREACHED */
}
(void) fclose(f);
target_name = "daemon";
minok = MIN_PID;
maxok = MAX_PID;
if (ent->flags & CE_SIGNALGROUP) {
/*
* If we are expected to signal a process-group when
* rotating this logfile, then the value read in should
* be the negative of a valid process ID.
*/
target_name = "process-group";
minok = -MAX_PID;
maxok = -MIN_PID;
}
errno = 0;
linep = line;
while (*linep == ' ')
linep++;
rval = strtol(linep, &endp, 10);
if (*endp != '\0' && !isspacech(*endp)) {
warnx("pid file does not start with a valid number: %s",
ent->pid_file);
rval = 0;
} else if (rval < minok || rval > maxok) {
warnx("bad value '%ld' for process number in %s",
rval, ent->pid_file);
if (verbose)
warnx("\t(expecting value between %ld and %ld)",
minok, maxok);
rval = 0;
}
if (rval == 0) {
return (did_notify);
/* NOTREACHED */
}
target_pid = rval;
if (noaction) {
did_notify = 1;
printf("\tkill -%d %d\n", ent->sig, (int) target_pid);
} else if (kill(target_pid, ent->sig)) {
/*
* XXX - Iff the error was "no such process", should that
* really be an error for us? Perhaps the process
* is already gone, in which case there would be no
* problem with compressing the rotated log file.
*/
warn("can't notify %s, pid %d", target_name,
(int) target_pid);
} else {
did_notify = 1;
if (verbose)
printf("%s pid %d notified\n", target_name,
(int) target_pid);
}
return (did_notify);
}
static void
parse_args(int argc, char **argv)
{
@ -798,6 +896,9 @@ parse_file(FILE *cf, const char *cfname, struct conf_entry **work_p,
case 'n':
working->flags |= CE_NOSIGNAL;
break;
case 'u':
working->flags |= CE_SIGNALGROUP;
break;
case 'w':
working->flags |= CE_COMPACTWAIT;
break;
@ -878,9 +979,16 @@ parse_file(FILE *cf, const char *cfname, struct conf_entry **work_p,
/*
* 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
* specified some other pid-file (and obviously the
* syslog pid-file will not be for a process-group).
* Also, we should only try to notify syslog if we
* are root.
*/
if (working->flags & CE_SIGNALGROUP) {
warnx("Ignoring flag 'U' in line:\n%s",
errline);
working->flags &= ~CE_SIGNALGROUP;
}
if (needroot)
working->pid_file = strdup(_PATH_SYSLOGPID);
}
@ -909,7 +1017,6 @@ dotrim(const struct conf_entry *ent, char *log, int numdays, int flags)
char tfile[MAXPATHLEN];
int notified, need_notification, fd, _numdays;
struct stat st;
pid_t pid;
if (archtodir) {
char *p;
@ -1073,31 +1180,19 @@ dotrim(const struct conf_entry *ent, char *log, int numdays, int flags)
* to the logfile, and as such, that process has already made sure
* that the logfile is not presently in use.
*/
pid = 0;
need_notification = notified = 0;
if (ent->pid_file != NULL) {
need_notification = 1;
if (!nosignal)
pid = get_pid(ent->pid_file); /* the normal case! */
notified = send_signal(ent); /* the normal case! */
else if (rotatereq)
need_notification = 0;
}
if (pid) {
if (noaction) {
notified = 1;
printf("\tkill -%d %d\n", ent->sig, (int) pid);
} else if (kill(pid, ent->sig))
warn("can't notify daemon, pid %d", (int) pid);
else {
notified = 1;
if (verbose)
printf("daemon pid %d notified\n", (int) pid);
}
}
if ((flags & CE_COMPACT) || (flags & CE_BZCOMPACT)) {
if (need_notification && !notified)
warnx(
"log %s.0 not compressed because daemon not notified",
"log %s.0 not compressed because daemon(s) not notified",
log);
else if (noaction)
if (flags & CE_COMPACT)
@ -1107,7 +1202,7 @@ dotrim(const struct conf_entry *ent, char *log, int numdays, int flags)
else {
if (notified) {
if (verbose)
printf("small pause to allow daemon to close log\n");
printf("small pause to allow daemon(s) to close log\n");
sleep(10);
}
if (archtodir) {
@ -1243,32 +1338,6 @@ age_old_log(char *file)
return ((int)(timenow - sb.st_mtime + 1800) / 3600);
}
static pid_t
get_pid(const char *pid_file)
{
FILE *f;
char line[BUFSIZ];
pid_t pid = 0;
if ((f = fopen(pid_file, "r")) == NULL)
warn("can't open %s pid file to restart a daemon",
pid_file);
else {
if (fgets(line, BUFSIZ, f)) {
pid = atol(line);
if (pid < MIN_PID || pid > MAX_PID) {
warnx("preposterous process number: %d",
(int)pid);
pid = 0;
}
} else
warn("can't read %s pid file to restart a daemon",
pid_file);
(void) fclose(f);
}
return (pid);
}
/* Skip Over Blanks */
static char *
sob(char *p)