diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | squid-cronolog.c | 106 |
2 files changed, 115 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1e50259 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +CFLAGS += -Wall + +all: squid-cronolog + +squid-cronolog: squid-cronolog.c + $(CC) $(CFLAGS) -o squid-cronolog squid-cronolog.c + +clean: + $(RM) squid-cronolog diff --git a/squid-cronolog.c b/squid-cronolog.c new file mode 100644 index 0000000..bfc5346 --- /dev/null +++ b/squid-cronolog.c @@ -0,0 +1,106 @@ +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <string.h> + +#define CRONOLOG "/usr/sbin/cronolog" + +char *pidfile; + +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, 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]); + exit(1); + } + + pidfile = argv[1]; + fifo = argv[2]; + log = argv[3]; + + /* 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)); + 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)); + exit(1); + } else { + pidlen = snprintf(pidstr, pidlen, "%d\n", getpid()); + write(pidfd, pidstr, pidlen); + 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 */ + 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); + return 0; +} |