#!/usr/bin/expect --

# Copyright 1996,1997 James H. Lowe, Jr.
# Copying Policy: FSF's GPL

# $Id: shak_errmon_v 1.17 1997/06/29 23:51:02 jhl Exp $
# Program to monitor the stderr stream located in a file.
# ARGS:
#   0
#   1:  pid number of process
#   2:  file name containing the stderr stream.
#   3:  user program name and args.
# ENV VARIABLES 
#   shak_errmon_fatal  -- regular expression matching fatal error
#   shak_errmon_warn   -- regular expression matching non-fatal error
#   shak_errmon_begin  -- regular expression matching a start signature
#   shak_errmon_end    -- regular expression matching a end signature 
#   shak_errmon_sigterm   -- regular expression matching a signaled termination.
#   shak_errmon_timeout1  -- allowable time between _begin and _end events.
#   shak_errmon_maxwarn   -- maximum no. of shak_errmon_warn, produces 
#                            shak_errmon_fatal if exceeded.

# shak_errmon_begin must match within 60 seconds.

# The contents of the stderr file is compared to the values of the
# variables above.  If a variable matches an action is taken.

proc cleanup { pid libpath } {
	system "$libpath/shak_kill 15 -$pid"
}

set argc [llength $argv]

set USERCMDPID [lindex $argv 0]
set filename [lindex $argv 1]
set USERCMD [lindex $argv 2]

set number_of_warnings 0

trap { cleanup $USERCMDPID $env(SHAK_LIBPATH) } {SIGINT}
trap { exit 2 } {SIGTERM}

set timebase [timestamp]

spawn -noecho /usr/bin/tail -f $filename

if { $env(shak_errmon_fatal) != "" } { eval set errmon_fatal "$env(shak_errmon_fatal)" } else { set errmon_fatal "" }
if { $env(shak_errmon_end) != "" }   { eval set errmon_end "$env(shak_errmon_end)" } else { set errmon_end "" }
if { $env(shak_errmon_begin) != "" } { eval set errmon_begin "$env(shak_errmon_begin)" } else { set errmon_begin "" }
if { $env(shak_errmon_sigterm) != "" } { eval set errmon_sigterm "$env(shak_errmon_sigterm)" } else { set errmon_sigterm "" }
if { $env(shak_errmon_warn) != "" }  { eval set errmon_warn "$env(shak_errmon_warn)" } else { set errmon_warn "" }
if { $env(shak_errmon_timeout1) != ""} { eval set errmon_timeout1 "$env(shak_errmon_timeout1)" } else { set shak_errmon_timeout1 "" }
if { $env(shak_errmon_maxwarn) != "" }  { eval set errmon_maxwarn "$env(shak_errmon_maxwarn)" } else { set errmon_maxwarn "" }

#set errmon_fatal "I/O|Error|ERROR|error|fail|fatal"
#set errmon_warn "^..*$"
#set errmon_begin "__BEGIN__\r\n"
#set errmon_end "__END__\r\n"
#set errmon_timeout1 "-1"
#set errmon_sigterm "__SIGTERM__\r\n"

proc err_action { id timebase USERCMDPID USERCMD} {
	
        global number_of_warnings
	global errmon_maxwarn
	global errmon_timeout1
	global env
	global filename
	global expect_out(buffer)
	set currenttime [timestamp]
	set elapsedtime "[expr $currenttime - $timebase]"

	upvar expect_out(0,string) local_expect_out
	send_error -- "$local_expect_out"
	regsub "\r\n" $local_expect_out "" local_expect_out
	set env(shakerrorline) "$local_expect_out"
	system "$env(SHAK_LIBPATH)/shak0_errmon_u $id  $elapsedtime $USERCMDPID $USERCMD <$filename &"
	if {$id == 1} {
		exit 1
	} elseif {$id == 2} {
            if { $errmon_maxwarn != ""  && $errmon_maxwarn != "-1" } {    
	        incr number_of_warnings 1
                if { $number_of_warnings > $errmon_maxwarn } {
		   send_error "shak_errmon: too many warnings. sending SIGTERM.\n"
                   cleanup $USERCMDPID $env(SHAK_LIBPATH)
		}
            }	
	} elseif {$id == 3} {
		upvar timeout ltimeout
		set ltimeout $errmon_timeout1
	} elseif {$id == 6} {
		exit 5
	} else {
		exit 0
	}
}

proc err_timeout {id timebase USERCMD USERCMDPID} {
	global env
	global filename
	set currenttime [timestamp]
	set elapsedtime "[expr $currenttime - $timebase]"
	send_error "shak_errmon: expect timeout error.\n"
	system "$env(SHAK_LIBPATH)/shak0_errmon_u 5 $elapsedtime $filename $USERCMDPID $USERCMD"
	exit 4
}

set patlist ""

lappend  patlist  timeout {err_timeout 1 $timebase $USERCMD $USERCMDPID}
if { $errmon_fatal != "" } {lappend  patlist -re "$errmon_fatal" {err_action 1 $timebase "$USERCMDPID" "$USERCMD"; exp_continue} }
if { $errmon_begin != "" } {lappend patlist -re "$errmon_begin" {err_action 3 $timebase "$USERCMDPID" "$USERCMD"; exp_continue} }
if { $errmon_end != "" } {lappend  patlist  -re "$errmon_end" {err_action 4 $timebase "$USERCMDPID" "$USERCMD"; exp_continue} }
if { $errmon_sigterm != "" } {lappend  patlist  -re "$errmon_sigterm" {err_action 6 $timebase "$USERCMDPID" "$USERCMD"; exp_continue} }
if { $errmon_warn != "" } {lappend  patlist  -re "$errmon_warn" {err_action 2 $timebase "$USERCMDPID" "$USERCMD"; exp_continue -continue_timer} }

set timeout 60
expect -brace $patlist

exit 2

