diff --git a/Makefile b/Makefile index a1cb13d..58dbbd8 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ endif DISTFILES = README LICENSE HEADERS = lite.h OBJS := chomp.o copyfile.o dir.o fexist.o fisdir.o fmode.o fsendfile.o -OBJS += makepath.o rsync.o strlcpy.o strlcat.o strtonum.o tempfile.o +OBJS += makepath.o pidfile.o rsync.o strlcpy.o strlcat.o strtonum.o tempfile.o DEPS := $(OBJS:.o=.d) JUNK = *~ *.bak *.map .*.d *.d DEADJOE semantic.cache *.gdb *.elf core core.* diff --git a/README.md b/README.md index 3722587..d396fc1 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,22 @@ Generic Functions with the `dst` name. On successful operation the source is removed and the function returns POSIX OK (0). +- `pidfile(basename)` + + Write a daemon pid file. Creates a pidfile in `_PATH_VARRUN` using + either `basename` or, if `basename` is `NULL`, `__progname`. The + file name has the form `/var/run/basename.pid`. + + Use this function to create a pid file for your daemon when it is + ready to receive signals. A client application may poll for the + existence of this file, so make sure to have your signal handlers + properly setup before calling this function. + + The pidfile is removed when the program exits, using an `atexit()` + handler. However, depending on how the program terminates the file + may still exist even though the program is no longer running. This + is only a problem for clients. + - `rsync(src, dst, delete, *filter())` Very simple `rsync()` to copy files files and directories diff --git a/lite.h b/lite.h index d49f74f..901ba21 100644 --- a/lite.h +++ b/lite.h @@ -51,6 +51,8 @@ int makepath (char *dir); int dir (const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip); int rsync (char *src, char *dst, int delete, int (*filter) (const char *file)); +int pidfile (const char *basename); + #ifndef strlcpy size_t strlcpy (char *dst, const char *src, size_t siz); #endif diff --git a/pidfile.c b/pidfile.c new file mode 100644 index 0000000..fa89c4e --- /dev/null +++ b/pidfile.c @@ -0,0 +1,107 @@ +/* $OpenBSD: pidfile.c,v 1.10 2014/06/30 00:26:22 deraadt 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. + */ + +#include +#include +#include +#include +#include +#include + +static char *pidfile_path; +static pid_t pidfile_pid; + +static void pidfile_cleanup(void); + +extern char *__progname; + +int +pidfile(const char *basename) +{ + int save_errno, result; + pid_t pid; + FILE *f; + + if (basename == NULL) + basename = __progname; + + if (pidfile_path != NULL) { + free(pidfile_path); + pidfile_path = NULL; + } + + /* _PATH_VARRUN includes trailing / */ + result = asprintf(&pidfile_path, "%s%s.pid", _PATH_VARRUN, basename); + if (result == -1 || pidfile_path == NULL) + return (-1); + + if ((f = fopen(pidfile_path, "w")) == NULL) { + save_errno = errno; + free(pidfile_path); + pidfile_path = NULL; + errno = save_errno; + return (-1); + } + + pid = getpid(); + 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_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); +}