aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Ruppert <idl0r@gentoo.org>2010-10-11 22:00:07 +0200
committerChristian Ruppert <idl0r@gentoo.org>2010-10-11 22:00:07 +0200
commitefcbec749f6955ee3c6d167847b34edc2360ecd9 (patch)
tree57af1b898dc93315677cc964da6dd31045a8a5a0 /fifo-cronolog.c
parentBump version to 1.1, tag v1.1. (diff)
downloadfifo-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.c188
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: */