diff -uNr logsurfer-1.5a/src/logsurfer.c logsurfer-1.5ap1/src/logsurfer.c --- logsurfer-1.5a/src/logsurfer.c Fri Dec 1 12:49:34 2000 +++ logsurfer-1.5ap1/src/logsurfer.c Fri Sep 6 14:07:57 2002 @@ -3,6 +3,8 @@ * * (C) DFN-CERT, Germany * Authors: Wolfgang Ley, Uwe Ellermann + * + * Semi-real-time patch: Henk Kloepping */ @@ -139,7 +141,12 @@ #endif /* SENDMAIL_FLUSH */ - +/* + * flag needed for synchronisation of timer-triggered + * and flow-triggered progam events that share the same + * procedure. + */ +int not_now_please; /* * process a line from the logfile @@ -161,12 +168,12 @@ #endif if ( (logline_context=(struct context_line *)malloc(sizeof(struct context_line))) == NULL ) { - (void) fprintf(stderr, "out of memory processing logling: %s\n", + (void) fprintf(stderr, "out of memory processing logline: %s\n", logline); return; } if ( (logline_context->content=(char *)malloc(strlen(logline)+1)) == NULL ) { - (void) fprintf(stderr, "out of memory processing logling: %s\n", + (void) fprintf(stderr, "out of memory processing logline: %s\n", logline); (void) free(logline_context); return; @@ -258,6 +265,58 @@ /* + * This procedure checks for rules and context that might time out, flushes the + * sendmail queue (if this was configured, of course) and checks if a context + * line limit was exceeded. This code will be called both once a second (triggered + * by an alarm) and after an input logline was read. A variable should be set to + * prevent the alarm from starting the procedure while it is already running. + */ +void check_and_process_timed_out_contexts_and_rules(void) { + + /* + * Prevent the alarm from interrupting this routine. The alarm + * is a safeguide to ensure that this code is executed at least + * once a second. However, it's pointless to force execution + * of code that currently _is_ executed :-). + */ + not_now_please=1; + + regex_submatches_num=0; + (void) time(¤t_time); + + if ( next_rule_timeout < (long) current_time ) check_rule_timeout(); + if ( next_context_timeout < (long) current_time ) check_context_timeout(); +#ifdef SENDMAIL_FLUSH + if ( flush_time != LONG_MAX ) { + if ( flush_time < (long) current_time ) { +#ifdef DEBUG + (void) printf("time to flush the sendmail queue now\n"); +#endif + flush_queue(); + } +#ifdef DEBUG + else + (void) printf("next flush time in %ld seconds\n", flush_time-((long) current_time)); +#endif + } +#endif + check_context_linelimit(); + + not_now_please=0; +} + +/* + * process wallclock events + */ +void wallclock_check(int sig) +{ + if (not_now_please==0) { + check_and_process_timed_out_contexts_and_rules(); + } + alarm(1); +} + +/* * reopen the input logfile */ void @@ -336,6 +395,7 @@ next_context_timeout=LONG_MAX; logline_num=0; logline=NULL; + not_now_please=0; /* alarm is allowed to do work on contexts/rules */ #ifdef SENDMAIL_FLUSH flush_time=LONG_MAX; @@ -532,14 +592,39 @@ exit(8); } + /* + * The following code will set a handler that is executed upon reception of + * an ALRM signal. + */ + signal_info.sa_handler=wallclock_check; + if ( sigaction(SIGALRM, &signal_info, NULL) ) { + (void) fprintf(stderr, "can't set signal to handle ALRM - abort\n"); + exit(8); + } + /* + * the first alarm() call will sent a SIG_ALRM to this process after roughly + * one second has passed. The handler will re-issue this alarm, in effect + * ensuring that the handler is called at least once a second. + */ + alarm(1); + + /* + * The handler observes the global variable not_now_please. If not_now_please + * is set to '1', the handler will not execute any code to work on the + * contexts/rules, it will only re-issue the alarm. + */ + not_now_please=0; + while ( logfile != NULL ) { logline=readline(logfile, &logline_buffer, &logline_buffer_size, &logline_buffer_pos); (void) time(¤t_time); if ( logline != NULL ) { + not_now_please=1; /* protect this code .. */ logline_num++; process_logline(); (void) free(logline); + not_now_please=0; /* .. and unprotect again */ } else if ( do_follow ) (void) sleep(1); @@ -547,30 +632,12 @@ (void) fclose(logfile); logfile=NULL; } - regex_submatches_num=0; - if ( next_rule_timeout < (long) current_time ) - check_rule_timeout(); - if ( next_context_timeout < (long) current_time ) - check_context_timeout(); - check_context_linelimit(); -#ifdef SENDMAIL_FLUSH - if ( flush_time != LONG_MAX ) { - if ( flush_time < (long) current_time ) { -#ifdef DEBUG -(void) printf("time to flush the sendmail queue now\n"); -#endif - flush_queue(); - } -#ifdef DEBUG - else -(void) printf("next flush time in %ld seconds\n", flush_time-((long) current_time)); -#endif - } -#endif - while ( waitpid((pid_t) -1, NULL, WNOHANG) > 0 ) - ; + check_and_process_timed_out_contexts_and_rules(); + while ( waitpid((pid_t) -1, NULL, WNOHANG) > 0 ) /* , do nothing */ ; } - logsurfer_exit(0); + not_now_please=1; /* prevent timer */ + alarm(0); /* kill timer */ + logsurfer_exit(0); /* exit */ /* NOTREACHED */ return(99); diff -uNr logsurfer-1.5a/src/rt_test.conf logsurfer-1.5ap1/src/rt_test.conf --- logsurfer-1.5a/src/rt_test.conf Thu Jan 1 01:00:00 1970 +++ logsurfer-1.5ap1/src/rt_test.conf Fri Sep 6 14:08:21 2002 @@ -0,0 +1,2 @@ +'reset ([0-9])' - - - 0 delete alarm_$2 +'alarm ([0-9])' - - - 0 open "alarm_$2" - 100 10 - exec "/bin/echo ALARM_$2"