Replace homegrown PID file functions with std BSD pidfile()

- Import pidfile() v1.11 from OpenBSD and libite (-lite) project
- Import utimensat() replacement, for systems that don't have it
- Simplify syslogd and klogd program start and PID file creation
- Rip out -i and -I from klogd, uses old PID file functions, and
  they're only kill(1) wrappers anyway

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson
2019-11-02 20:57:07 +01:00
parent 1236334c39
commit ff4f2cdb31
10 changed files with 267 additions and 363 deletions

View File

@@ -23,19 +23,20 @@ lib_LTLIBRARIES = libsyslog.la
AM_CFLAGS = -W -Wall -Wextra
AM_CFLAGS += -Wno-unused-result -Wno-unused-parameter -fno-strict-aliasing
AM_CPPFLAGS = -DSYSCONFDIR=\"@sysconfdir@\" -DLOCALSTATEDIR=\"@localstatedir@\"
AM_CPPFLAGS += -D_BSD_SOURCE -D_DEFAULT_SOURCE
syslogd_SOURCES = syslogd.c syslog.h pidfile.c pidfile.h queue.h
syslogd_CPPFLAGS = -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE
syslogd_SOURCES = syslogd.c syslog.h queue.h
syslogd_CPPFLAGS = $(AM_CPPFLAGS) -D_XOPEN_SOURCE=600
syslogd_LDADD = $(LIBS) $(LIBOBJS)
klogd_SOURCES = klogd.c klogd.h syslog.h pidfile.c pidfile.h \
ksym.c ksyms.h ksym_mod.c module.h
klogd_CPPFLAGS = -DALLOW_KERNEL_LOGGING -D_BSD_SOURCE -D_DEFAULT_SOURCE
klogd_SOURCES = klogd.c klogd.h syslog.h ksym.c ksyms.h ksym_mod.c module.h
klogd_CPPFLAGS = $(AM_CPPFLAGS) -DALLOW_KERNEL_LOGGING
klogd_LDADD = $(LIBS) $(LIBOBJS)
klogd_LDADD += libsyslog.la
logger_SOURCES = logger.c syslog.h
logger_CPPFLAGS = -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE
logger_CPPFLAGS = $(AM_CPPFLAGS) -D_XOPEN_SOURCE=600
logger_LDADD = $(LIBS) $(LIBOBJS)
logger_LDADD += libsyslog.la
@@ -44,5 +45,5 @@ pkgincludedir = $(includedir)/syslog
pkgconfig_DATA = libsyslog.pc
pkginclude_HEADERS = syslog.h
libsyslog_la_SOURCES = syslog.c syslog.h
libsyslog_la_CPPFLAGS = -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE
libsyslog_la_CPPFLAGS = $(AM_CPPFLAGS) -D_XOPEN_SOURCE=600
libsyslog_la_LDFLAGS = $(AM_LDFLAGS) -version-info 0:0:0

View File

@@ -65,6 +65,10 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
size_t strlcat(char *dst, const char *src, size_t siz);
#endif
#ifndef pidfile
int pidfile(const char *basename);
#endif
static inline char *getprogname(void)
{
extern char *__progname;

View File

@@ -23,6 +23,7 @@
*/
#include "config.h"
#include "compat.h"
#include <errno.h>
#include <getopt.h>
@@ -35,9 +36,6 @@
#include <stdarg.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifndef TESTING
#include "pidfile.h"
#endif
#define __LIBRARY__
#include <linux/unistd.h>
@@ -47,9 +45,7 @@
#define LOG_BUFFER_SIZE 4096
#define LOG_LINE_LENGTH 1000
#ifndef TESTING
static char *PidFile = _PATH_VARRUN "klogd.pid";
#endif
static int kmsg;
static int change_state = 0;
@@ -81,7 +77,6 @@ extern void stop_logging(int sig);
extern void stop_daemon(int sig);
extern void reload_daemon(int sig);
static void Terminate(void);
static void SignalDaemon(int);
static void ReloadSymbols(void);
static void ChangeLogging(void);
static enum LOGSRC GetKernelLogSrc(void);
@@ -115,12 +110,10 @@ static void CloseLogSrc(void)
/*
* Signal handler to terminate the parent process.
*/
#ifndef TESTING
void doexit(int signo)
{
exit(0);
}
#endif
void restart(int signo)
{
@@ -153,26 +146,14 @@ static void Terminate(void)
CloseLogSrc();
Syslog(LOG_INFO, "Kernel log daemon terminating.");
sleep(1);
if (output_file != NULL)
fclose(output_file);
closelog();
#ifndef TESTING
(void)remove_pid(PidFile);
#endif
exit(1);
}
static void SignalDaemon(int signo)
{
#ifndef TESTING
int pid = check_pid(PidFile);
kill(pid, signo);
#else
kill(getpid(), signo);
#endif
}
static void ReloadSymbols(void)
{
if (symbol_lookup) {
@@ -257,7 +238,6 @@ static enum LOGSRC GetKernelLogSrc(void)
return kernel;
}
#ifndef TESTING
if ((kmsg = open(_PATH_KLOG, O_RDONLY)) < 0) {
fprintf(stderr, "klogd: Cannot open proc file system, "
"%d - %s.\n",
@@ -265,12 +245,10 @@ static enum LOGSRC GetKernelLogSrc(void)
ksyslog(7, NULL, 0);
exit(1);
}
#else
kmsg = fileno(stdin);
#endif
Syslog(LOG_INFO, "klogd v%s, log source = %s started.",
VERSION, _PATH_KLOG);
return proc;
}
@@ -333,18 +311,12 @@ extern void Syslog(int priority, char *fmt, ...)
}
syslog(priority, fmt, argl);
va_end(ap);
#ifdef TESTING
putchar('\n');
#endif
return;
}
va_start(ap, fmt);
vsyslog(priority, fmt, ap);
va_end(ap);
#ifdef TESTING
printf("\n");
#endif
}
/*
@@ -648,6 +620,8 @@ int usage(int code)
" -v Show program version and exit\n"
" -x Omit EIP translation, i.e. do not read System.map file\n"
"\n"
"SIGUSR1 reloads kernel module symbols, SIGUSR2 reloads all kernel symbols.\n"
"\n"
"Bug report address: %s\n",
PACKAGE_BUGREPORT);
exit(code);
@@ -659,14 +633,10 @@ int main(int argc, char *argv[])
char *output = NULL;
int use_output = 0;
int ch;
#ifndef TESTING
pid_t ppid = getpid();
chdir("/");
#endif
/* Parse the command-line. */
while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2?")) != EOF) {
while ((ch = getopt(argc, argv, "c:df:k:nopsvx2?")) != EOF) {
switch (ch) {
case '2': /* Print lines with symbols twice. */
symbols_twice = 1;
@@ -685,14 +655,6 @@ int main(int argc, char *argv[])
use_output++;
break;
case 'i': /* Reload module symbols. */
SignalDaemon(SIGUSR1);
return 0;
case 'I':
SignalDaemon(SIGUSR2);
return 0;
case 'k': /* Kernel symbol file. */
symfile = optarg;
break;
@@ -743,7 +705,6 @@ int main(int argc, char *argv[])
console_log_level = *log_level - '0';
}
#ifndef TESTING
/*
* The following code allows klogd to auto-background itself.
* What happens is that the program forks and the parent quits.
@@ -756,48 +717,40 @@ int main(int argc, char *argv[])
* such process running.
*/
if ((!one_shot) && (!no_fork)) {
if (!check_pid(PidFile)) {
signal(SIGTERM, doexit);
if (fork() == 0) {
int num_fds = getdtablesize();
int fl;
signal(SIGTERM, doexit);
if (fork() == 0) {
int num_fds = getdtablesize();
int fl;
signal(SIGTERM, SIG_DFL);
signal(SIGTERM, SIG_DFL);
/* This is the child closing its file descriptors. */
for (fl = 0; fl <= num_fds; ++fl) {
if (fileno(stdout) == fl && use_output)
if (strcmp(output, "-") == 0)
continue;
close(fl);
}
setsid();
} else {
/*
* Parent process
*/
sleep(300);
/*
* Not reached unless something major went wrong.
*/
exit(1);
/* This is the child closing its file descriptors. */
for (fl = 0; fl <= num_fds; ++fl) {
if (fileno(stdout) == fl && use_output)
if (strcmp(output, "-") == 0)
continue;
close(fl);
}
chdir("/");
setsid();
} else {
fputs("klogd: Already running.\n", stderr);
/*
* Parent process
*/
sleep(300);
/*
* Not reached unless something major went wrong.
*/
exit(1);
}
}
}
/* tuck my process id away */
if (!check_pid(PidFile)) {
if (!write_pid(PidFile))
Terminate();
} else {
fputs("klogd: Already running.\n", stderr);
if (pidfile(PidFile)) {
Syslog(LOG_ERR, "Failed creating PID file %s: %s",
PidFile, strerror(errno));
Terminate();
}
#endif
/* Signal setups. */
for (ch = 1; ch < NSIG; ++ch)

View File

@@ -1,147 +0,0 @@
/*-
* SPDX-License-Identifier: GPL-2.0-or-later
*
* pidfile.c - interact with pidfiles
* Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
*
* This file is part of the sysklogd package, a kernel and system log daemon.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this file; see the file COPYING. If not, write to the
* Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
/* read_pid
*
* Reads the specified pidfile and returns the read pid.
* 0 is returned if either there's no pidfile, it's empty
* or no pid can be read.
*/
int read_pid(char *pidfile)
{
FILE *fp;
int pid;
fp = fopen(pidfile, "r");
if (!fp)
return 0;
fscanf(fp, "%d", &pid);
fclose(fp);
return pid;
}
/* check_pid
*
* Reads the pid using read_pid and looks up the pid in the process
* table (using /proc) to determine if the process already exists. If
* so 1 is returned, otherwise 0.
*/
int check_pid(char *pidfile)
{
int pid = read_pid(pidfile);
/* Amazing ! _I_ am already holding the pid file... */
if ((!pid) || (pid == getpid()))
return 0;
/*
* The 'standard' method of doing this is to try and do a 'fake' kill
* of the process. If an ESRCH error is returned the process cannot
* be found -- GW
*/
/* But... errno is usually changed only on error.. */
if (kill(pid, 0) && errno == ESRCH)
return 0;
return pid;
}
/* write_pid
*
* Writes the pid to the specified file. If that fails 0 is
* returned, otherwise the pid.
*/
int write_pid(char *pidfile)
{
FILE *fp;
int fd;
int pid;
if (((fd = open(pidfile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) || ((fp = fdopen(fd, "r+")) == NULL)) {
fprintf(stderr, "Can't open or create %s.\n", pidfile);
return 0;
}
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
fscanf(fp, "%d", &pid);
fclose(fp);
printf("Can't lock, lock is held by pid %d.\n", pid);
return 0;
}
pid = getpid();
if (!fprintf(fp, "%d\n", pid)) {
printf("Can't write pid , %s.\n", strerror(errno));
close(fd);
return 0;
}
fflush(fp);
if (flock(fd, LOCK_UN) == -1) {
printf("Can't unlock pidfile %s, %s.\n", pidfile, strerror(errno));
close(fd);
return 0;
}
close(fd);
return pid;
}
/* touch_pid
*
* Touches the specified pidfile f.ex. when receiving a SIGHUP
* The result from utimensat() is returned
*/
int touch_pid(char *pidfile)
{
return utimensat(0, pidfile, NULL, 0);
}
/* remove_pid
*
* Remove the the specified file. The result from unlink(2)
* is returned
*/
int remove_pid(char *pidfile)
{
return unlink(pidfile);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/

View File

@@ -1,65 +0,0 @@
/*-
* SPDX-License-Identifier: GPL-2.0-or-later
*
* pidfile.h - interact with pidfiles
* Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
*
* This file is part of the sysklogd package, a kernel and system log daemon.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this file; see the file COPYING. If not, write to the
* Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef SYSKLOGD_PIDFILE_H_
#define SYSKLOGD_PIDFILE_H_
/* read_pid
*
* Reads the specified pidfile and returns the read pid.
* 0 is returned if either there's no pidfile, it's empty
* or no pid can be read.
*/
int read_pid (char *pidfile);
/* check_pid
*
* Reads the pid using read_pid and looks up the pid in the process
* table (using /proc) to determine if the process already exists. If
* so 1 is returned, otherwise 0.
*/
int check_pid (char *pidfile);
/* write_pid
*
* Writes the pid to the specified file. If that fails 0 is
* returned, otherwise the pid.
*/
int write_pid (char *pidfile);
/* touch_pid
*
* Touches the specified pidfile f.ex. when receiving a SIGHUP
* The result from utimensat() is returned
*/
int touch_pid (char *pidfile);
/* remove_pid
*
* Remove the the specified file. The result from unlink(2)
* is returned
*/
int remove_pid (char *pidfile);
#endif /* SYSKLOGD_PIDFILE_H_ */

View File

@@ -96,7 +96,6 @@ static char sccsid[] __attribute__((unused)) =
#include <syscall.h>
#include <paths.h>
#include "pidfile.h"
#include "syslogd.h"
#include "compat.h"
@@ -448,52 +447,39 @@ int main(int argc, char *argv[])
usage(1);
if ((!Foreground) && (!Debug)) {
logit("Checking pidfile.\n");
if (!check_pid(PidFile)) {
signal(SIGTERM, doexit);
chdir("/");
signal(SIGTERM, doexit);
chdir("/");
if (fork()) {
/*
* Parent process
*/
sleep(300);
/*
* Not reached unless something major went wrong. 5
* minutes should be a fair amount of time to wait.
* Please note that this procedure is important since
* the father must not exit before syslogd isn't
* initialized or the klogd won't be able to flush its
* logs. -Joey
*/
exit(1);
}
signal(SIGTERM, SIG_DFL);
num_fds = getdtablesize();
for (i = 0; i < num_fds; i++)
(void)close(i);
untty();
} else {
fputs("syslogd: Already running.\n", stderr);
if (fork()) {
/*
* Parent process
*/
sleep(300);
/*
* Not reached unless something major went wrong. 5
* minutes should be a fair amount of time to wait.
* Please note that this procedure is important since
* the father must not exit before syslogd isn't
* initialized or the klogd won't be able to flush its
* logs. -Joey
*/
exit(1);
}
signal(SIGTERM, SIG_DFL);
num_fds = getdtablesize();
for (i = 0; i < num_fds; i++)
(void)close(i);
untty();
} else {
debugging_on = 1;
setlinebuf(stdout);
}
/* tuck my process id away */
if (!Debug) {
logit("Writing pidfile.\n");
if (!check_pid(PidFile)) {
if (!write_pid(PidFile)) {
logit("Can't write pid.\n");
if (getpid() != ppid)
kill(ppid, SIGTERM);
exit(1);
}
} else {
logit("Pidfile (and pid) already exist.\n");
if (pidfile(PidFile)) {
logit("Failed creating PID file %s: %s",
PidFile, strerror(errno));
if (getpid() != ppid)
kill(ppid, SIGTERM);
exit(1);
@@ -593,13 +579,8 @@ int main(int argc, char *argv[])
logit("\nReceived SIGHUP, reloading syslogd.\n");
init();
if (check_pid(PidFile)) {
if (touch_pid(PidFile))
logerror("Not possible to touch pidfile");
} else {
if (!write_pid(PidFile))
logerror("Failed to write pidfile");
}
if (pidfile(PidFile))
flog(LOG_SYSLOG | LOG_ERR, "Failed writing %s", PidFile);
continue;
}
@@ -2267,7 +2248,6 @@ void die(int signo)
if (parts)
free(parts);
(void)remove_pid(PidFile);
exit(0);
}