diff options
author | Christian Ruppert <idl0r@gentoo.org> | 2010-10-11 22:00:07 +0200 |
---|---|---|
committer | Christian Ruppert <idl0r@gentoo.org> | 2010-10-11 22:00:07 +0200 |
commit | efcbec749f6955ee3c6d167847b34edc2360ecd9 (patch) | |
tree | 57af1b898dc93315677cc964da6dd31045a8a5a0 /fifo-cronolog.c | |
parent | Bump version to 1.1, tag v1.1. (diff) | |
download | fifo-cronolog-efcbec749f6955ee3c6d167847b34edc2360ecd9.tar.gz fifo-cronolog-efcbec749f6955ee3c6d167847b34edc2360ecd9.tar.bz2 fifo-cronolog-efcbec749f6955ee3c6d167847b34edc2360ecd9.zip |
Rename everything from squid-cronolog to fifo-cronolog.
Diffstat (limited to 'fifo-cronolog.c')
-rw-r--r-- | fifo-cronolog.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/fifo-cronolog.c b/fifo-cronolog.c new file mode 100644 index 0000000..ef5609d --- /dev/null +++ b/fifo-cronolog.c @@ -0,0 +1,188 @@ +/* +Copyright (c) 2007-2010, Gentoo Foundation +All rights reserved. + +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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> + +#define VERSION "1.1" + +char *pidfile; + +char *get_cronolog(void) { + int len = 0; + char *path, *tmp = NULL; + struct stat st; + + path = strtok(getenv("PATH"), ":"); + while(path != NULL) { + len = (strlen(path) + strlen("/cronolog") + 1); + tmp = (char *)malloc(len); + snprintf(tmp, len, "%s%s", path, "/cronolog"); + + if(stat(tmp, &st) == -1) { + if(errno == ENOENT) { + free(tmp); + path = strtok(NULL, ":"); + continue; + } + + fprintf(stderr, "stat(): Error: %s\n", strerror(errno)); + free(tmp); + return NULL; + } + + if(st.st_mode & S_IFREG) + return tmp; + else { + free(tmp); + return NULL; + } + } + + if(tmp != NULL) + free(tmp); + + return NULL; +} + +void die(int sig) { + /* kill off children */ + kill(0, SIGTERM); + /* remove pid file, quit */ + unlink(pidfile); + exit(0); +} + +struct sigaction sigdie = { .sa_handler = die }; + +int main(int argc, char *argv[]) { + time_t t = 0; + pid_t pid = 0; + int fd, pidfd, pidlen = 16; + char *fifo, *log, *cronolog, pidstr[16]; + + if (argc != 4) { + fprintf(stderr, "Usage: %s /path/to/pidfile /path/to/fifo" + " /path/to/logs/%%Y%%m%%d.log\n", argv[0]); + fprintf(stderr, "fifo-cronolog version: %s\n", VERSION); + exit(1); + } + + pidfile = argv[1]; + fifo = argv[2]; + log = argv[3]; + + cronolog = get_cronolog(); + if(cronolog == NULL) { + fprintf(stderr, "cronolog not found in PATH\n"); + exit(1); + } + + /* Test for fifo access, leave open for use */ + /* O_NONBLOCK allows us to fork into the background */ + fd = open(fifo, O_RDONLY|O_NONBLOCK); + if (fd == -1) { + fprintf(stderr, "Cannot open fifo %s: %s\n", fifo, strerror(errno)); + free(cronolog); + exit(1); + } + + pid = fork(); + + if (pid == 0) { + /* CHILD 0 */ + + /* Record pid to pidfile */ + pidfd = open(pidfile, O_WRONLY|O_CREAT|O_EXCL, 0644); + if (pidfd == -1) { + fprintf(stderr, "Cannot create and open pid file %s: %s\n", + pidfile, strerror(errno)); + free(cronolog); + exit(1); + } else { + pidlen = snprintf(pidstr, pidlen, "%d\n", getpid()); + if(write(pidfd, pidstr, pidlen) == -1) { + fprintf(stderr, "Cannot write pid file %s: %s\n", pidfile, strerror(errno)); + free(cronolog); + exit(1); + } + close(pidfd); + } + + /* close shell output */ + close(0); + close(1); + close(2); + + /* set a process group for easy cleanup */ + setpgrp(); + sigaction(SIGTERM, &sigdie, NULL); + + /* keep the cronolog process open */ + while (1) { + t = time(NULL); + pid = fork(); + if (pid == 0) { + /* CHILD 1 */ + + /* replace stdin with fifo */ + dup2(fd, 0); + /* unset O_NONBLOCK */ + fcntl(0, F_SETFL, 0); + /* exec cronolog */ + execl(cronolog, cronolog, log, (char *) 0); + /* filure! give up on life */ + free(cronolog); + exit(1); + } else { + /* PARENT 1 */ + /* watch child 1 */ + waitpid(pid, NULL, 0); + if (time(NULL) - t < 2) { + /* restarting too fast, wait 10 seconds */ + sleep(10); + } + } + } + } + + /* PARENT 0 exits */ + close(fd); + + free(cronolog); + + return 0; +} + +/* vim: set ts=4 sw=4 tw=80: */ |