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:
parent
1236334c39
commit
ff4f2cdb31
@ -40,7 +40,7 @@ AC_HEADER_STDC
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
# Check for usually missing API's, which we can replace
|
||||
AC_REPLACE_FUNCS([strlcpy strlcat])
|
||||
AC_REPLACE_FUNCS([pidfile strlcpy strlcat utimensat])
|
||||
AC_CONFIG_LIBOBJ_DIR([lib])
|
||||
|
||||
# Command line options
|
||||
|
138
lib/pidfile.c
Normal file
138
lib/pidfile.c
Normal file
@ -0,0 +1,138 @@
|
||||
/* Updated by troglobit for libite/finit/uftpd projects 2016/07/04 */
|
||||
/* $OpenBSD: pidfile.c,v 1.11 2015/06/03 02:24:36 millert Exp $ */
|
||||
/* $NetBSD: pidfile.c,v 1.4 2001/02/19 22:43:42 cgd Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* Needed with GLIBC to get asprintf() */
|
||||
#include <sys/stat.h> /* utimensat() */
|
||||
#include <sys/time.h> /* utimensat() on *BSD */
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "compat.h"
|
||||
|
||||
#ifndef HAVE_UTIMENSAT
|
||||
int utimensat(int dirfd, const char *pathname, const struct timespec ts[2], int flags);
|
||||
#endif
|
||||
|
||||
static char *pidfile_path = NULL;
|
||||
static pid_t pidfile_pid = 0;
|
||||
|
||||
static void pidfile_cleanup(void);
|
||||
|
||||
const char *__pidfile_path = LOCALSTATEDIR "/run";
|
||||
const char *__pidfile_name = NULL;
|
||||
|
||||
int
|
||||
pidfile(const char *basename)
|
||||
{
|
||||
int save_errno;
|
||||
int atexit_already;
|
||||
pid_t pid;
|
||||
FILE *f;
|
||||
|
||||
if (basename == NULL)
|
||||
basename = getprogname();
|
||||
|
||||
pid = getpid();
|
||||
atexit_already = 0;
|
||||
|
||||
if (pidfile_path != NULL) {
|
||||
if (!access(pidfile_path, R_OK) && pid == pidfile_pid) {
|
||||
utimensat(0, pidfile_path, NULL, 0);
|
||||
return (0);
|
||||
}
|
||||
free(pidfile_path);
|
||||
pidfile_path = NULL;
|
||||
__pidfile_name = NULL;
|
||||
atexit_already = 1;
|
||||
}
|
||||
|
||||
if (basename[0] != '/') {
|
||||
if (asprintf(&pidfile_path, "%s/%s.pid", __pidfile_path, basename) == -1)
|
||||
return (-1);
|
||||
} else {
|
||||
if (asprintf(&pidfile_path, "%s", basename) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((f = fopen(pidfile_path, "w")) == NULL) {
|
||||
save_errno = errno;
|
||||
free(pidfile_path);
|
||||
pidfile_path = NULL;
|
||||
errno = save_errno;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (fprintf(f, "%ld\n", (long)pid) <= 0 || fflush(f) != 0) {
|
||||
save_errno = errno;
|
||||
(void) fclose(f);
|
||||
(void) unlink(pidfile_path);
|
||||
free(pidfile_path);
|
||||
pidfile_path = NULL;
|
||||
errno = save_errno;
|
||||
return (-1);
|
||||
}
|
||||
(void) fclose(f);
|
||||
__pidfile_name = pidfile_path;
|
||||
|
||||
/*
|
||||
* LITE extension, no need to set up another atexit() handler
|
||||
* if user only called us to update the mtime of the PID file
|
||||
*/
|
||||
if (atexit_already)
|
||||
return (0);
|
||||
|
||||
pidfile_pid = pid;
|
||||
if (atexit(pidfile_cleanup) < 0) {
|
||||
save_errno = errno;
|
||||
(void) unlink(pidfile_path);
|
||||
free(pidfile_path);
|
||||
pidfile_path = NULL;
|
||||
pidfile_pid = 0;
|
||||
errno = save_errno;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
pidfile_cleanup(void)
|
||||
{
|
||||
if (pidfile_path != NULL && pidfile_pid == getpid()) {
|
||||
(void) unlink(pidfile_path);
|
||||
free(pidfile_path);
|
||||
pidfile_path = NULL;
|
||||
}
|
||||
}
|
47
lib/utimensat.c
Normal file
47
lib/utimensat.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Replacement in case utimensat(2) is missing
|
||||
*
|
||||
* Copyright (C) 2017-2018 Joachim Nilsson <troglobit@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <sys/time.h> /* lutimes(), utimes(), utimensat() */
|
||||
|
||||
int utimensat(int dirfd, const char *pathname, const struct timespec ts[2], int flags)
|
||||
{
|
||||
int ret = -1;
|
||||
struct timeval tv[2];
|
||||
|
||||
if (dirfd != 0) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
|
||||
TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
|
||||
|
||||
#ifdef AT_SYMLINK_NOFOLLOW
|
||||
if ((flags & AT_SYMLINK_NOFOLLOW) == AT_SYMLINK_NOFOLLOW)
|
||||
ret = lutimes(pathname, tv);
|
||||
else
|
||||
#endif
|
||||
ret = utimes(pathname, tv);
|
||||
|
||||
return ret;
|
||||
}
|
29
man/klogd.8
29
man/klogd.8
@ -31,14 +31,6 @@ Enable debugging mode. This will generate potentially LOTS of output to
|
||||
stderr.
|
||||
.It Fl f Ar FILE
|
||||
Log messages to the specified filename rather than to the syslog facility.
|
||||
.It Fl i | Fl I
|
||||
Signal the currently executing klogd daemon. Both of these switches control
|
||||
the loading/reloading of symbol information. The
|
||||
.Fl i
|
||||
switch signals the daemon to reload the kernel module symbols. The
|
||||
.Fl I
|
||||
switch signals for a reload of both the static kernel symbols and the
|
||||
kernel module symbols.
|
||||
.It Fl n
|
||||
Avoid auto-backgrounding. This is needed especially if
|
||||
.Nm
|
||||
@ -251,22 +243,23 @@ Proper and accurate resolution of addresses in kernel modules requires
|
||||
that
|
||||
.Nm
|
||||
be informed whenever the kernel module status changes. The
|
||||
.Fl i
|
||||
.Ar SIGUSR1
|
||||
and
|
||||
.Fl I
|
||||
switches can be used to signal the currently executing daemon that
|
||||
symbol information be reloaded. Of most importance to proper resolution
|
||||
of module symbols is the
|
||||
.Fl i
|
||||
switch. Each time a kernel module is loaded or removed from the kernel
|
||||
the following command should be executed:
|
||||
.Ar SIGUSR2
|
||||
signals can be used to signal the currently executing
|
||||
.Nm
|
||||
that symbol information should be reloaded. Of most importance to
|
||||
proper resolution of module symbols is
|
||||
.Ar SIGUSR1 .
|
||||
Each time a kernel module is loaded or removed from the kernel the
|
||||
following command should be executed:
|
||||
.Bd -literal -offset indent
|
||||
klogd -i
|
||||
kill -USR1 `cat /run/klogd.pid`
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Fl p
|
||||
switch can also be used to insure that module symbol information is up
|
||||
switch can also be used to ensure that module symbol information is up
|
||||
to date. This switch instructs
|
||||
.Nm
|
||||
to reload the module symbol information whenever a protection fault
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
111
src/klogd.c
111
src/klogd.c
@ -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)
|
||||
|
147
src/pidfile.c
147
src/pidfile.c
@ -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:
|
||||
*/
|
@ -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_ */
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user