
From jrj@gandalf.cc.purdue.edu Fri Jul 25 13:44 EDT 1997
Received: from FCRFV2.NCIFCRF.GOV (fcrfv2.ncifcrf.gov [129.43.51.3]) by ncisun1-nf0.ncifcrf.gov (8.8.5/8.7.3) with SMTP id NAA26083 for <toms@fcs280s.NCIFCRF.GOV>; Fri, 25 Jul 1997 13:44:44 -0400 (EDT)
Received: from gandalf.cc.purdue.edu by FCRFV1.NCIFCRF.GOV with ESMTP
          for toms@alum.mit.edu; Fri, 25 Jul 1997 13:50:08 -0400
Received: from gandalf.cc.purdue.edu (jrj@localhost [127.0.0.1]) by gandalf.cc.purdue.edu (8.8.3/8.8.3) with ESMTP id MAA13245; Fri, 25 Jul 1997 12:44:59 -0500 (EST)
Resent-Message-Id: <199707251744.NAA26083@ncisun1-nf0.ncifcrf.gov>
Resent-Date: Fri, 25 Jul 1997 13:49:53 -0400
Resent-From: toms@fcrfv2.ncifcrf.gov
Resent-To: toms@ncisun1-nf0.ncifcrf.gov
Message-Id: <199707251744.MAA13245@gandalf.cc.purdue.edu>
To: jsh@rd.qms.com
Cc: toms@alum.mit.edu
Subject: Tweaks for "atchange" and "eh"
Reply-to: jrj@cc.purdue.edu
Date: Fri, 25 Jul 1997 12:44:35 -0500
From: "John R. Jackson" <jrj@gandalf.cc.purdue.edu>
Content-Type: text
Content-Length: 5630
Status: OR

Never one to leave a perfectly good script alone :-), I've tweaked your
"atchange" and "eh" scripts a bit.

The "eh" script didn't work right as pulled off the web page.  I suspect
the "kill 0" at the end was supposed to be "kill %0".

Even so, we had some other problems (perl4 vs perl5) that were causing
"atchange" to fail, which in turn caused "eh" to misbehave, so I changed
it to save the pid, make sure "atchange" stayed running, then kill it
explicitly on exit.

As long as I was in the neighborhood :-), I also set it up to start
netscape if there didn't appear to be one running.  Yes, there are
some us old timers out here who do not have netscape permanently on the
desktop :-).

--- /tmp/eh	Fri Jul 25 11:40:36 1997
+++ bin/eh	Fri Jul 25 12:30:30 1997
@@ -12,11 +12,11 @@
 #	- fix the shebang line and the PATH
 # 	- make sure atchange is installed
 
 PATH=/usr/local/bin:/usr/local/bin:/bin:/usr/bin:/home/kaylor/toms/script
 
+ARGV0=${0##*/}
 # print usage message and exit
 usage() {
-	ARGV0=${0##*/}
 	echo "usage: $ARGV0 [-l] filename|filename.html" 1>&2
 	test "$1" = "long" || exit 0
 
@@ -88,10 +86,27 @@
 	
 test -f $html || html_template > $html
 
-netscape -noraise -remote "openFile($html)"
+if netscape -noraise -remote "openFile($html)"
+then
+	:
+else
+	netscape $html &
+fi
+
 atchange $html "netscape -noraise -remote 'reload'" &
+pid=$!
+
+# make sure atchange stays running
+sleep 1
+if kill -0 $pid > /dev/null 2>&1
+then
+	:
+else
+	echo "$ARGV0: atchange failed"
+	exit 1
+fi
 
 # finally, invoke the editor:
 ${EDITOR:-vi} $html
-kill 0
-wait
+kill $pid
+wait $pid

On the "atchange" front are the following:

    * When using "atchange", I find myself constantly changing things
      in the "automate" script (e.g. adding new html files).  This version
      of "atchange" treats a command script like any other file when
      looking for changes, and if it is altered, "atchange" restarts
      itself.

    * Added a "-t" option to control the sleep time.  If many other
      options are added, one of the getopt() routines should be used
      for argument parsing.  Since I just added one, I kept it simple.

    * Made the script work with either perl4 or perl5.

    * Used "-w" to catch questionable code.  Fixed a few odds and ends
      as a result.

    * Closed the command file when done.

    * Skipped files that do not exist.

    * Used select() in the "wait for idle" loop.

Enjoy, and thanks for the new tool.

John R. Jackson, Technical Software Specialist, jrj@purdue.edu

#!/usr/local/bin/perl -w
# by Jeff Haemer
#	and a tip o' the hat to Tom Schneider
#       who wrote the original version as a shell script

# version = 2.03 of atchange 1997 Jan 9
# delay time is 0.25 seconds

#  For current version and other information about this program, see:
#  https://alum.mit.edu/www/toms/atchange.html

#  Tom Schneider
#  toms@alum.mit.edu
#  https://alum.mit.edu/www/toms/

$save_cmd = $0;			# save the command name
@save_args = @ARGV;		# and the argument list
$0 =~ s(.*/)();			# basename
$usage  = "usage: $0 [-t sleeptime] filename cmd\n";
$usage .= "       $0 [-t sleeptime] command_file\n";
@ARGV || die $usage;		# check for proper invocation

$sleeptime = 0.25;		# default is to check every 0.25 seconds
if ($ARGV[0] =~ /^-t([.\d]+)$/) {
	# e.g. "-t2.5" or "-t5"
	$sleeptime = $1;	# set a new sleep time
	shift;			# skip this argument
} elsif ($ARGV[0] eq "-t" && $#ARGV > 0 && $ARGV[1] =~ /^[.\d]+$/) {
	# e.g. "-t 2.5" or "-t 5"
	$sleeptime = $ARGV[1];	# set a new sleep time
	shift;			# skip the "-t"
	shift;			# skip the sleep time
}
@ARGV || die $usage;		# check for proper invocation

$shell = $ENV{"SHELL"} ? $ENV{"SHELL"} : "/bin/sh";
open(SHELL, "|$shell") || die "Can't pipe to $shell: $!";
select(SHELL); $| = 1;

if (@ARGV > 1) {		# it's a file and a command
	$file = shift;				# peel off the filename
	$cmd{$file} = join(" ", @ARGV) . "\n";	#	and the command
	$old{$file} = (stat($file))[9];	# mod time.
} else {			# it's a program
	$cmd{$ARGV[0]} = "";
	$old{$ARGV[0]} = (stat($ARGV[0]))[9];	# mod time.
	open(PGM, $ARGV[0]) || die "Can't open $ARGV[0]: $!";
	$/ = "";		# paragraph mode
	while(<PGM>) {		# first read the program
		s/#.*\n/\n/g;
		($file, $cmd) = /(\S*)\s+([^\000]+)/;
		if ($file) {
			if (! $cmd) {
				warn "file without command";
			} else {
				$cmd{$file} = $cmd;
				$old{$file} = (stat($file))[9];	# mod time.
			}
		} elsif ($cmd) {
			print $cmd;		# shell command as-is
		}
	}
	close(PGM);
}

while(1) {
	# The following "select" call pauses for some period of time,
	# then falls through.
	select(undef, undef, undef, $sleeptime);
	foreach (keys %cmd) {	# rip through the whole list
		if (&atchange($_) && @ARGV <= 1 && $_ eq $ARGV[0]) {
			close(SHELL);	# the script changed, re-exec ourself
			exec $save_cmd, @save_args;
		}
	}
}

sub atchange {		# if $file has changed, do $cmd{$file}
	local($file) = @_;
	local($new);

	return 0 unless (-e $file);	# test for existance
	$new = (stat(_))[9];		# use -e stat result for mod time
	return 0 if (defined ($old{$file}) && $old{$file} == $new);
	while (1) {			# wait until it stops changing
		$old{$file} = $new;
		# We want to wait a little longer than one second because
		# that is the resolution of the modification time.
		select(undef, undef, undef, 1.1);
		return 0 unless (-e $file);	# test for existance
		$new = (stat(_))[9];		# use -e result for mod time
		last if ($old{$file} == $new);	# file has gone idle
	}
	print $cmd{$file};
	return 1;
}

exit (0);

