Date: Fri, 23 May 2003 17:31:08 +0200 From: Gabriel Krabbe To: Andrew Ford Subject: cronolog: patch for FIFOs Hi Andrew - attached a patch for cronolog that will handle FIFOs as a data source rather than stdin ("--fifo="), plus an associated daemon mode ("--daemon", "--pidfile="). Additionally, I added a bunch of stuff that creates an additional target "sun-package", which builds a SysV-Datastream-Type Package, prticularly handy for Solaris systems. The man page is updated with the new options, the texinfo version isn't (never tried the format), hence the option no-installinfo in doc/Makefile.am (which, in turn, requires automake be passed "--foreign" for strictness). Cheers, and thanks for the software. Gabe diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/ChangeLog cronolog-1.6.2/ChangeLog --- cronolog-1.6.2.orig/ChangeLog 1999-12-20 09:58:25.000000000 +0100 +++ cronolog-1.6.2/ChangeLog 2003-05-23 15:02:33.429405000 +0200 @@ -1,3 +1,8 @@ +2003-05-23 Gabriel Krabbe + + * Added daemon mode and FIFO handling + * Added Solaris package creation files + 1999-12-20 Andrew Ford * New version 1.6.1 diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/configure.in cronolog-1.6.2/configure.in --- cronolog-1.6.2.orig/configure.in 2001-05-03 18:30:50.000000000 +0200 +++ cronolog-1.6.2/configure.in 2003-05-23 15:36:45.212445000 +0200 @@ -64,4 +64,4 @@ AC_CHECK_FUNCS(mkdir mktime putenv) AC_REPLACE_FUNCS(strptime localtime_r) -AC_OUTPUT(Makefile lib/Makefile src/Makefile doc/Makefile testsuite/Makefile src/cronosplit) +AC_OUTPUT(Makefile lib/Makefile src/Makefile doc/Makefile testsuite/Makefile src/cronosplit ) diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/cronolog.info.in cronolog-1.6.2/cronolog.info.in --- cronolog-1.6.2.orig/cronolog.info.in 1970-01-01 01:00:00.000000000 +0100 +++ cronolog-1.6.2/cronolog.info.in 2003-05-23 15:48:31.689444000 +0200 @@ -0,0 +1,7 @@ +PKG=cronolog +NAME=The cronolog logfile rotation program +ARCH=sparc +VERSION=@VERSION@ +CATEGORY=application +DESC="cronolog kicks ass in every conceivable way in which a utility like cronolog can kick ass." +BASEDIR=/ diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/cronolog.proto.in cronolog-1.6.2/cronolog.proto.in --- cronolog-1.6.2.orig/cronolog.proto.in 1970-01-01 01:00:00.000000000 +0100 +++ cronolog-1.6.2/cronolog.proto.in 2003-05-23 16:49:15.287443000 +0200 @@ -0,0 +1,9 @@ +i pkginfo=cronolog.info +d none @prefix@ 0755 root other +d none @sbindir@ 0755 root other +f none @sbindir@/cronolog 0755 root other +f none @sbindir@/cronosplit 0755 root other +d none @mandir@ 0755 root other +d none @mandir@ 0755 root other +f none @mandir@/man1/cronolog.1m 0644 root other +f none @mandir@/man1/cronosplit.1m 0644 root other diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/doc/cronolog.1m cronolog-1.6.2/doc/cronolog.1m --- cronolog-1.6.2.orig/doc/cronolog.1m 2001-05-04 10:44:55.000000000 +0200 +++ cronolog-1.6.2/doc/cronolog.1m 2003-05-23 16:15:04.783447000 +0200 @@ -144,6 +144,19 @@ .IP --version print version information and exit. .\" +.IP -D +.IP --daemon +fork into background and run as daemon. Requires \fI-F\fP. +.\" +.IP "-f \fINAME\fP" +.IP "--pidfile=\fINAME\fP" +(Only used with the \fI-D\fP option): save the daemon's Process ID into the +file \fINAME\fP, which must not exist. +.\" +.IP "-F \fINAME\fP" +.IP "--fifo=\fINAME\fP" +Instead of stdin, read from the FIFO (named pipe) \fINAME\fP. Required with the \fI-D\fP option. +.\" .\" .\" .IP "-p \fIprogram\fP" .\" postprocess each logfile using program once a new logfile is created. diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/doc/Makefile.am cronolog-1.6.2/doc/Makefile.am --- cronolog-1.6.2.orig/doc/Makefile.am 1997-04-15 21:57:58.000000000 +0200 +++ cronolog-1.6.2/doc/Makefile.am 2003-05-23 16:41:08.884444000 +0200 @@ -1,5 +1,7 @@ ## Process this file with automake to create Makefile.in +AUTOMAKE_OPTIONS = no-installinfo + info_TEXINFOS = cronolog.texi man_MANS = cronolog.1m cronosplit.1m diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/Makefile.am cronolog-1.6.2/Makefile.am --- cronolog-1.6.2.orig/Makefile.am 2001-05-04 10:56:16.000000000 +0200 +++ cronolog-1.6.2/Makefile.am 2003-05-23 16:51:02.940444000 +0200 @@ -1,6 +1,32 @@ ## Process this file with automake to create Makefile.in AUTOMAKE_OPTIONS = gnu dejagnu -EXTRA_DIST = cronolog.spec +EXTRA_DIST = cronolog.spec cronolog.info.in cronolog.proto.in SUBDIRS = lib src doc testsuite +noinst_PROGRAMS = cronolog.info cronolog.proto + +edit = sed \ + -e 's,@VERSION\@,$(VERSION),g' \ + -e 's,@prefix\@,$(prefix),g' \ + -e 's,@sbindir\@,$(sbindir),g' \ + -e 's,@mandir\@,$(mandir),g' \ + -e 's,@man1dir\@,$(man1dir),g' + +cronolog.info: Makefile $(srcdir)/cronolog.info.in + rm -f cronolog.info cronolog.info.tmp + $(edit) $(srcdir)/cronolog.info.in > cronolog.info.tmp + mv cronolog.info.tmp cronolog.info + +cronolog.proto: Makefile $(srcdir)/cronolog.proto.in + rm -f cronolog.proto cronolog.proto.tmp + $(edit) $(srcdir)/cronolog.proto.in > cronolog.proto.tmp + mv cronolog.proto.tmp cronolog.proto + +sun-package: cronolog.proto cronolog.info + $(MAKE) DESTDIR=/tmp/cronolog-staging install + mkdir /tmp/cronolog-package + pkgmk -o -d /tmp/cronolog-package -f cronolog.proto -r /tmp/cronolog-staging + pkgtrans -s /tmp/cronolog-package /tmp/cronolog.pkg cronolog + mv /tmp/cronolog.pkg . + rm -rf /tmp/cronolog-staging /tmp/cronolog-package diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/src/config.h cronolog-1.6.2/src/config.h --- cronolog-1.6.2.orig/src/config.h 2001-01-26 17:22:00.000000000 +0100 +++ cronolog-1.6.2/src/config.h 2003-05-22 18:56:35.000000000 +0200 @@ -26,9 +26,17 @@ #define BUFSIZE 65536 #endif -#ifndef MAX_PATH -#define MAX_PATH 1024 -#endif +/* POSIX-ify this: */ +#ifdef HAVE_LIMITS_H +# include +# ifndef MAX_PATH +# define MAX_PATH PATH_MAX +# endif +#else +# ifndef MAX_PATH +# define MAX_PATH 1024 +# endif +#endif /* HAVE_LIMITS_H */ /* Default permissions for files and directories that are created */ diff -EbBNru -x cronosplit -x install-sh -x missing -x mkinstalldirs -x Makefile.in -x configure -x aclocal.m4 -x depcomp -x texinfo.tex cronolog-1.6.2.orig/src/cronolog.c cronolog-1.6.2/src/cronolog.c --- cronolog-1.6.2.orig/src/cronolog.c 2001-05-03 18:42:48.000000000 +0200 +++ cronolog-1.6.2/src/cronolog.c 2003-05-23 17:18:49.371446000 +0200 @@ -117,12 +117,15 @@ " -e, --european European date formats (default)\n" \ " -s, --start-time=TIME starting time\n" \ " -z TZ, --time-zone=TZ use TZ for timezone\n" \ - " -V, --version print version number, then exit\n" + " -V, --version print version number, then exit\n" \ + " -D, --daemon Detach and run in background\n" \ + " -f NAME, --pidfile=NAME Save PID of daemon process to file NAME\n" \ + " -F NAME, --fifo=NAME Read from FIFO (named pipe) NAME rather than STDIN\n" /* Definition of the short and long program options */ -char *short_options = "ad:eop:s:z:H:P:S:l:hVx:"; +char *short_options = "ad:eop:s:z:H:P:S:l:hVx:DF:f:"; #ifndef _WIN32 struct option long_options[] = @@ -139,7 +142,10 @@ { "delay", required_argument, NULL, 'd' }, { "once-only", no_argument, NULL, 'o' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' } + { "version", no_argument, NULL, 'V' }, + { "daemon", no_argument, NULL, 'D' }, + { "pidfile", required_argument, NULL, 'f' }, + { "fifo", required_argument, NULL, 'F' } }; #endif @@ -153,9 +159,13 @@ int period_multiple = 1; int period_delay = 0; int use_american_date_formats = 0; + int runas_daemon = 0; char read_buf[BUFSIZE]; char tzbuf[BUFSIZE]; char filename[MAX_PATH]; + char pidfile[MAX_PATH]; + char pidnum[BUFSIZE]; + char *fifoname = NULL; char *start_time = NULL; char *template; char *linkname = NULL; @@ -167,6 +177,10 @@ time_t time_offset = 0; time_t next_period = 0; int log_fd = -1; + int pid_fd = -1; + int input_fd = 0; + int input_fdfl = -1; + pid_t pid = 0; #ifndef _WIN32 while ((ch = getopt_long(argc, argv, short_options, long_options, NULL)) != EOF) @@ -249,6 +263,30 @@ } break; + case 'D': + runas_daemon = 1; + break; + + case 'F': + fifoname = optarg; + if (-1 == (input_fd = open(fifoname, O_RDONLY | O_NONBLOCK))) { + perror("Cannot open input pipe"); + exit(1); + } + break; + + case 'f': + if (strlen(optarg) > (MAX_PATH - 1)) { + fprintf(stderr, "File name too long: %s\n", optarg); + exit(1); + } + strncpy(pidfile, optarg, MAX_PATH); + pidfile[strlen(optarg)] = '\0'; + if (-1 == (pid_fd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL))) { + perror("Cannot open PID file"); + } + break; + case 'V': fprintf(stderr, VERSION_MSG); exit(0); @@ -268,6 +306,32 @@ DEBUG((VERSION_MSG "\n")); + if (runas_daemon) { + if (input_fd == 0) { + fprintf(stderr, "Cannot read from stdin as daemon!\nUse the -F option.\n"); + exit(2); + } + if (-1 == (pid = fork())) { + perror("Cannot fork"); + exit(2); + } else if (pid > 0) { + _exit(0); + } else { + (void) setsid(); + if (-1 == (pid = fork())) { + perror("Cannot fork"); + exit(2); + } else if (pid > 0) { + snprintf(pidnum, BUFSIZE-1, "%d\n", pid); + write(pid_fd, pidnum, strlen(pidnum)); + close(pid_fd); + _exit(0); + } + /* only the daemon-child ever gets here */ + close(pid_fd); + } + } + if (start_time) { time_now = parse_time(start_time, use_american_date_formats); @@ -305,6 +369,12 @@ DEBUG(("Rotation period is per %d %s\n", period_multiple, periods[periodicity])); + if (runas_daemon) { + /* child process here: */ + fclose(stdin); + fclose(stdout); + fclose(stderr); + } /* Loop, waiting for data on standard input */ @@ -313,8 +383,8 @@ /* Read a buffer's worth of log file data, exiting on errors * or end of file. */ - n_bytes_read = read(0, read_buf, sizeof read_buf); - if (n_bytes_read == 0) + n_bytes_read = read(input_fd, read_buf, sizeof read_buf); + if ((input_fd == 0) && (n_bytes_read == 0)) { exit(3); }