SOURCES: cronolog-jumbo-patch.txt (NEW) - added
glen
glen at pld-linux.org
Tue Dec 6 14:07:05 CET 2005
Author: glen Date: Tue Dec 6 13:07:05 2005 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- added
---- Files affected:
SOURCES:
cronolog-jumbo-patch.txt (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/cronolog-jumbo-patch.txt
diff -u /dev/null SOURCES/cronolog-jumbo-patch.txt:1.1
--- /dev/null Tue Dec 6 14:07:05 2005
+++ SOURCES/cronolog-jumbo-patch.txt Tue Dec 6 14:07:00 2005
@@ -0,0 +1,663 @@
+From: Matthew Grosso < mgrosso at looksmart dot net>
+To: cronolog-users at icarus.demon.co.uk
+Subject: CRONOLOG: jumbo patch, includes launching external program to handle logs
+Date: Fri, 10 Oct 2003 13:02:14 -0400
+
+I've put together a jumbo patch with some features that are on the todo
+list and most of the outstanding patches on the site. specifically:
+
+the todo list items completed (which motivated the work for my companies use) are:
+
+- ability to launch a helper program on every log file after it is closed
+ if multiple cronologs writing to the same file, only one helper is
+ launched.
+
+- signal handling to ensure that every log file has a chance to be handled
+ by that helper and that cronolog doesnt ever hang apache restarts
+
+- alarm() used so log files rotate on time period boundary even if there is no
+ traffic
+
+I also implemented (with tweaks) many of the outstanding patches, some of
+which are also on the todo list:
+
+- uid/gid patch from Isaac Wilcox <iwilcox at eatstatic dot net>
+ minus the configure changes which broke the build for me.
+
+- the large file patch from matt lanier <mlanier at danger dot .com>
+ with tweaks from me to work with my own changes above.
+
+- incorporated a slightly different implementation of
+ the SIGUSR1 patch from Prakash Kailasa <PKailasa at seisint dot com>
+
+- the s/stat/lstat/ fix from Victor Martinez <victor at kablinkteam dot com>
+
+the changes have only been tested on my Linux 2.4 box, and should be considered
+beta until more users have tried it. That said, we'll be starting to qa this at
+looksmart soon, but again, only on linux.
+
+I'm including a sample script that can be used as a helper. It will first
+compress, then scp a log to multiple destinations, then remove it.
+
+Still todo: I need to put my new options into the man page, not just the usage,
+and see if the configure.in needs modification.
+
+the patch is available below, and at this url:
+http://www.falconweb.com/~mattg/code/cronolog-1.6.2-jumbo-20031010.diff
+
+diff -Nur cronolog-1.6.2/src/cronolog.c cronolog-1.6.2-jumbo-20031008/src/cronolog.c
+--- cronolog-1.6.2/src/cronolog.c 2001-05-03 12:42:48.000000000 -0400
++++ cronolog-1.6.2-jumbo-20031008/src/cronolog.c 2003-10-08 00:22:10.000000000 -0400
+@@ -82,6 +82,18 @@
+ * written to "file" (e.g. /dev/console) or to stderr if "file" is "-".
+ */
+
++#ifndef _WIN32
++#define _GNU_SOURCE 1
++#define OPEN_EXCLUSIVE O_WRONLY|O_CREAT|O_EXCL|O_APPEND|O_LARGEFILE
++#define OPEN_SHARED O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE
++#else
++#define OPEN_EXCLUSIVE O_WRONLY|O_CREAT|O_EXCL|O_APPEND
++#define OPEN_SHARED O_WRONLY|O_CREAT|O_APPEND
++#endif
++
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <signal.h>
+ #include "cronoutils.h"
+ #include "getopt.h"
+
+@@ -91,6 +103,16 @@
+ int new_log_file(const char *, const char *, mode_t, const char *,
+ PERIODICITY, int, int, char *, size_t, time_t, time_t *);
+
++void cleanup(int );
++void handle_file();
++void fork_to_handle_file();
++
++int openwrapper( const char *filename );
++
++#ifndef _WIN32
++void setsig_handler( int signum, void (*action)(int, siginfo_t *, void *));
++void set_signal_handlers();
++#endif
+
+ /* Definition of version and usage messages */
+
+@@ -100,6 +122,12 @@
+ #define VERSION_MSG "cronolog version 0.1\n"
+ #endif
+
++#ifndef _WIN32
++#define SETUGID_USAGE " -u USER, --set-uid=USER change to USER before doing anything (name or UID)\n" \
++ " -g GROUP, --set-gid=GROUP change to GROUP before doing anything (name or GID)\n"
++#else
++#define SETUGID_USAGE ""
++#endif
+
+ #define USAGE_MSG "usage: %s [OPTIONS] logfile-spec\n" \
+ "\n" \
+@@ -113,6 +141,11 @@
+ " -o, --once-only create single output log from template (not rotated)\n" \
+ " -x FILE, --debug=FILE write debug messages to FILE\n" \
+ " ( or to standard error if FILE is \"-\")\n" \
++ " -r, --helper=SCRIPT post rotation helper script to fork exec on old files\n" \
++ " ( will be called like \"SCRIPT <oldlog>\" )\n" \
++ " ( not tested on windows )\n" \
++ " -G, --helper-arg=ARG argument passed to rotation helper script\n" \
++ SETUGID_USAGE \
+ " -a, --american American date formats\n" \
+ " -e, --european European date formats (default)\n" \
+ " -s, --start-time=TIME starting time\n" \
+@@ -122,7 +155,7 @@
+
+ /* 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:r:G:u:g:";
+
+ #ifndef _WIN32
+ struct option long_options[] =
+@@ -137,12 +170,23 @@
+ { "link", required_argument, NULL, 'l' },
+ { "period", required_argument, NULL, 'p' },
+ { "delay", required_argument, NULL, 'd' },
++ { "helper", required_argument, NULL, 'r' },
++ { "helper-arg", required_argument, NULL, 'G' },
++ { "set-uid", required_argument, NULL, 'u' },
++ { "set-gid", required_argument, NULL, 'g' },
+ { "once-only", no_argument, NULL, 'o' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' }
+ };
+ #endif
+
++static char handler[MAX_PATH];
++static char handler_arg[MAX_PATH];
++static char filename[MAX_PATH];
++static int use_handler =0;
++static int use_handler_arg =0;
++static int i_am_handler =0;
++
+ /* Main function.
+ */
+ int
+@@ -155,11 +199,16 @@
+ int use_american_date_formats = 0;
+ char read_buf[BUFSIZE];
+ char tzbuf[BUFSIZE];
+- char filename[MAX_PATH];
+ char *start_time = NULL;
+ char *template;
+ char *linkname = NULL;
+ char *prevlinkname = NULL;
++#ifndef _WIN32
++ uid_t new_uid = 0;
++ gid_t new_gid = 0;
++ int change_uid = 0;
++ int change_gid = 0;
++#endif
+ mode_t linktype = 0;
+ int n_bytes_read;
+ int ch;
+@@ -167,6 +216,10 @@
+ time_t time_offset = 0;
+ time_t next_period = 0;
+ int log_fd = -1;
++
++ memset( handler, '\0', MAX_PATH );
++ memset( handler_arg, '\0', MAX_PATH );
++ memset( filename, '\0', MAX_PATH );
+
+ #ifndef _WIN32
+ while ((ch = getopt_long(argc, argv, short_options, long_options, NULL)) != EOF)
+@@ -234,6 +287,16 @@
+ }
+ break;
+
++#ifndef _WIN32
++ case 'u':
++ new_uid = parse_uid(optarg, argv[0]);
++ change_uid = 1;
++ break;
++ case 'g':
++ new_gid = parse_gid(optarg, argv[0]);
++ change_gid = 1;
++ break;
++#endif
+ case 'o':
+ periodicity = ONCE_ONLY;
+ break;
+@@ -248,7 +311,15 @@
+ debug_file = fopen(optarg, "a+");
+ }
+ break;
+-
++ case 'r':
++ strncat(handler, optarg, MAX_PATH );
++ use_handler=1;
++ break;
++ case 'G':
++ strncat(handler_arg, optarg, MAX_PATH );
++ use_handler_arg=1;
++ break;
++
+ case 'V':
+ fprintf(stderr, VERSION_MSG);
+ exit(0);
+@@ -266,6 +337,17 @@
+ exit(1);
+ }
+
++#ifndef _WIN32
++ if (change_gid && setgid(new_gid) == -1) {
++ fprintf(stderr, "setgid: unable to change to gid: %d\n", new_gid);
++ exit(1);
++ }
++ if (change_uid && setuid(new_uid) == -1) {
++ fprintf(stderr, "setuid: unable to change to uid: %d\n", new_uid);
++ exit(1);
++ }
++#endif
++
+ DEBUG((VERSION_MSG "\n"));
+
+ if (start_time)
+@@ -306,6 +388,10 @@
+ DEBUG(("Rotation period is per %d %s\n", period_multiple, periods[periodicity]));
+
+
++#ifndef _WIN32
++ set_signal_handlers();
++#endif
++
+ /* Loop, waiting for data on standard input */
+
+ for (;;)
+@@ -316,15 +402,17 @@
+ n_bytes_read = read(0, read_buf, sizeof read_buf);
+ if (n_bytes_read == 0)
+ {
+- exit(3);
++ cleanup(3);
+ }
+ if (errno == EINTR)
+ {
+- continue;
++ /*
++ * fall through, it may have been alarm, in which case it will be time to rotate.
++ * */
+ }
+ else if (n_bytes_read < 0)
+ {
+- exit(4);
++ cleanup(4);
+ }
+
+ time_now = time(NULL) + time_offset;
+@@ -336,6 +424,7 @@
+ {
+ close(log_fd);
+ log_fd = -1;
++ fork_to_handle_file();
+ }
+
+ /* If there is no log file open then open a new one.
+@@ -345,6 +434,7 @@
+ log_fd = new_log_file(template, linkname, linktype, prevlinkname,
+ periodicity, period_multiple, period_delay,
+ filename, sizeof (filename), time_now, &next_period);
++ alarm( next_period - time_now );
+ }
+
+ DEBUG(("%s (%d): wrote message; next period starts at %s (%d) in %d secs\n",
+@@ -354,10 +444,10 @@
+
+ /* Write out the log data to the current log file.
+ */
+- if (write(log_fd, read_buf, n_bytes_read) != n_bytes_read)
++ if (n_bytes_read && write(log_fd, read_buf, n_bytes_read) != n_bytes_read)
+ {
+ perror(filename);
+- exit(5);
++ cleanup(5);
+ }
+ }
+
+@@ -383,6 +473,7 @@
+ struct tm *tm;
+ int log_fd;
+
++
+ start_of_period = start_of_this_period(time_now, periodicity, period_multiple);
+ tm = localtime(&start_of_period);
+ strftime(pfilename, BUFSIZE, template, tm);
+@@ -394,13 +485,13 @@
+ timestamp(*pnext_period), *pnext_period,
+ *pnext_period - time_now));
+
+- log_fd = open(pfilename, O_WRONLY|O_CREAT|O_APPEND, FILE_MODE);
++ log_fd = openwrapper(pfilename);
+
+ #ifndef DONT_CREATE_SUBDIRS
+ if ((log_fd < 0) && (errno == ENOENT))
+ {
+ create_subdirs(pfilename);
+- log_fd = open(pfilename, O_WRONLY|O_CREAT|O_APPEND, FILE_MODE);
++ log_fd = openwrapper(pfilename);
+ }
+ #endif
+
+@@ -416,3 +507,179 @@
+ }
+ return log_fd;
+ }
++
++/*
++ * fork, then exec an external handler to deal with rotated file.
++ */
++void
++fork_to_handle_file()
++{
++ int fk ;
++ static int childpid=0;
++
++ if( ! use_handler || !i_am_handler || handler[0] =='\0' || filename[0] == '\0' )
++ {
++ return;
++ }
++ fk=fork();
++ if( fk < 0 )
++ {
++ perror("couldnt fork");
++ exit(2);
++ }else if( fk > 0 )
++ {
++ if( childpid )
++ {
++ /*
++ * collect zombies. run twice, in case one or more children took longer than
++ * the rotation period for a while, this will eventually clean them up.
++ * Of course, if handler children take longer than rotation period to handle
++ * things, you will eventually have a big problem.
++ *
++ * */
++ (void) waitpid( 0, NULL, WNOHANG | WUNTRACED );
++ (void) waitpid( 0, NULL, WNOHANG | WUNTRACED );
++ }
++ childpid=fk;
++ return; /* parent */
++ }
++ /* child */
++ /* dont muck with stdin or out of parent, but allow stderr to be commingled */
++ close(0);
++ close(1);
++ handle_file();
++}
++
++/*
++ * exec an external handler to deal with rotated file.
++ */
++void
++handle_file()
++{
++ char **exec_argv ;
++ if( ! use_handler || !i_am_handler || handler[0] =='\0' || filename[0] == '\0' )
++ {
++ return;
++ }
++ if ( use_handler_arg == 0 )
++ {
++ exec_argv = malloc( sizeof( char *)*3);
++ exec_argv[0] = strdup( handler );
++ exec_argv[1] = strdup( filename );
++ exec_argv[2] = NULL;
++ }else
++ {
++ exec_argv = malloc( sizeof( char *)*4);
++ exec_argv[0] = strdup( handler );
++ exec_argv[1] = strdup( handler_arg );
++ exec_argv[2] = strdup( filename );
++ exec_argv[3] = NULL ;
++ }
++ execvp( exec_argv[0], exec_argv );
++ perror("cant execvp");
++ exit(2);
++}
++
++
++
++#ifndef _WIN32
++/*
++ * wrapper to be called as signal handler.
++ */
++void
++handle_file_on_sig( int sig, siginfo_t *si, void *v )
++{
++ handle_file();
++ /* not reached */
++ exit( 3 );
++};
++
++/*
++ * wrapper to be called for alarm signal
++ */
++void
++alarm_signal_handler( int sig, siginfo_t *si, void *v )
++{
++ ;
++ /*
++ * do nothing; the key thing is that the alarm will cause the read()
++ * to fail with errno=EINTR. this empty handler is required, because the
++ * default handler will exit(1)
++ *
++ */
++};
++
++void
++set_signal_handlers()
++{
++ /*
++ * all signals which usually kill a process that can be caught are
++ * set to handle_file when received. This will make apache shutdowns more
++ * graceful even if use_handler is false.
++ */
++ setsig_handler( SIGHUP, handle_file_on_sig );
++ setsig_handler( SIGINT, handle_file_on_sig );
++ setsig_handler( SIGQUIT, handle_file_on_sig );
++ setsig_handler( SIGILL, handle_file_on_sig );
++ setsig_handler( SIGABRT, handle_file_on_sig );
++ setsig_handler( SIGBUS, handle_file_on_sig );
++ setsig_handler( SIGFPE, handle_file_on_sig );
++ setsig_handler( SIGPIPE, handle_file_on_sig );
++ setsig_handler( SIGTERM, handle_file_on_sig );
++ setsig_handler( SIGUSR1, handle_file_on_sig );
++
++ /* sigalrm is used to break out of read() when it is time to rotate the log. */
++ setsig_handler( SIGALRM, alarm_signal_handler );
++}
++
++void
++setsig_handler( int signum, void (*action)(int, siginfo_t *, void *))
++{
++ struct sigaction siga ;
++ memset( &siga, '\0', sizeof( struct sigaction ));
++ siga.sa_sigaction= action ;
++ siga.sa_flags = SA_SIGINFO ;
++ if( -1== sigaction( signum, &siga, NULL ))
++ {
++ perror( "cant set sigaction" );
++ }
++}
++#endif
++
++
++/*
++ * cleanup
++ */
++void
++cleanup( int exit_status )
++{
++ handle_file();
++ exit(exit_status);
++}
++
++/*
++ * only the first cronolog process to open a particular file is responsible
++ * for starting the cleanup process later. This wrapper sets i_am_handler
++ * according to that logic.
++ * */
++int
++openwrapper( const char *ofilename )
++{
++ int ret;
++ if( use_handler !=1 )
++ {
++ return open(ofilename, OPEN_SHARED, S_IRWXU );
++ }
++ ret = open(ofilename, OPEN_EXCLUSIVE, S_IRWXU );
++ if( ret < 0 )
++ {
++ ret = open(ofilename, OPEN_SHARED, S_IRWXU );
++ i_am_handler= 0;
++ }
++ else
++ {
++ i_am_handler=1;
++ }
++ return ret;
++}
++
+diff -Nur cronolog-1.6.2/src/cronoutils.c cronolog-1.6.2-jumbo-20031008/src/cronoutils.c
+--- cronolog-1.6.2/src/cronoutils.c 2001-05-03 12:43:21.000000000 -0400
++++ cronolog-1.6.2-jumbo-20031008/src/cronoutils.c 2003-10-08 00:22:10.000000000 -0400
+@@ -195,11 +195,11 @@
+ {
+ struct stat stat_buf;
+
+- if (stat(prevlinkname, &stat_buf) == 0)
++ if (lstat(prevlinkname, &stat_buf) == 0)
+ {
+ unlink(prevlinkname);
+ }
+- if (stat(linkname, &stat_buf) == 0)
++ if (lstat(linkname, &stat_buf) == 0)
+ {
+ if (prevlinkname) {
+ rename(linkname, prevlinkname);
+@@ -710,4 +710,50 @@
+ return retval;
+ }
+
+-
++
++#ifndef _WIN32
++/* Turn a string specifying either a username or UID into an actual
++ * uid_t for use in setuid(). A string is assumed to be a UID if
++ * it contains only decimal digits. */
++uid_t
++parse_uid(char *user, char *argv0)
++{
++ char *probe = user;
++ struct passwd *ent;
++
++ while (*probe && isdigit(*probe)) {
++ probe++;
++ }
++ if (!(*probe)) {
++ return atoi(user);
++ }
++ if (!(ent = getpwnam(user))) {
++ fprintf(stderr, "%s: Bad username %s\n", argv0, user);
++ exit(1);
++ }
++ return (ent->pw_uid);
++}
++
++
++/* Turn a string specifying either a group name or GID into an actual
++ * gid_t for use in setgid(). A string is assumed to be a GID if
++ * it contains only decimal digits. */
++gid_t
++parse_gid(char *group, char *argv0)
++{
++ char *probe = group;
++ struct group *ent;
++
++ while (*probe && isdigit(*probe)) {
++ probe++;
++ }
++ if (!(*probe)) {
++ return atoi(group);
++ }
++ if (!(ent = getgrnam(group))) {
++ fprintf(stderr, "%s: Bad group name %s\n", argv0, group);
++ exit(1);
++ }
++ return (ent->gr_gid);
++}
++#endif /* _WIN32 */
+diff -Nur cronolog-1.6.2/src/cronoutils.h cronolog-1.6.2-jumbo-20031008/src/cronoutils.h
+--- cronolog-1.6.2/src/cronoutils.h 2001-05-03 12:40:12.000000000 -0400
++++ cronolog-1.6.2-jumbo-20031008/src/cronoutils.h 2003-10-08 00:22:10.000000000 -0400
+@@ -84,6 +84,8 @@
+ #include <limits.h>
+ #ifndef _WIN32
+ #include <unistd.h>
++#include <pwd.h>
++#include <grp.h>
+ #else
+ #include <io.h>
+ #include <direct.h>
+@@ -172,7 +174,8 @@
+ void print_debug_msg(char *msg, ...);
+ time_t parse_time(char *time_str, int);
+ char *timestamp(time_t thetime);
+-
++uid_t parse_uid(char *user, char *argv0);
++gid_t parse_gid(char *group, char *argv0);
+
+ /* Global variables */
+
+diff -Nur cronolog-1.6.2/src/zip_send_rm.sh cronolog-1.6.2-jumbo-20031008/src/zip_send_rm.sh
+--- cronolog-1.6.2/src/zip_send_rm.sh 1969-12-31 19:00:00.000000000 -0500
++++ cronolog-1.6.2-jumbo-20031008/src/zip_send_rm.sh 2003-10-10 12:37:22.000000000 -0400
+@@ -0,0 +1,64 @@
++#!/bin/bash
++## ----------------------------------------------------------------------
++## ----------------------------------------------------------------------
++##
++## File: zip_send_rm
++## Author: mgrosso
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list