return to first page linux journal archive
keywordscontents

Listing 5. loop.pl

#!/usr/bin/perl
#
# loop.pl
#
use POSIX "sys_wait_h";   # Need this for waitpid with WNOHANG

#
# Loop forever
#
while (1)
{
	# Fix the screen (my console sometimes gets wacked out if
	#   the connection doesn't go through quite right)
	# This just prints a console reset
	timed_system("/usr/local/bin/fix",5);

	# Delete default route
	timed_system("route del default",5);

	# Start up the PPP connection
	while  ( &dip() != 0 )
	{
		print "dip failed, try again in 60 seconds\n";
		print "dip -k\n";
		timed_system("dip -k",5);
		sleep 60;
	}
	print "sleep 5\n";
	sleep 5;
	timed_system("/bin/date",5);

	# Ping doesn't always return an error when
	#  the connection fails.  (I should probably
	#  write  a Perl script to do this.)
	if ( `ping -c2 ftp.frii.net` )
	{
		#
		# Fork off a child process to run the ftp upload script
		#
		if (!defined($doup_pid = fork()))
		{
			print "fork error\n";
		}
		elsif ($doup_pid)
		{
			# 
			# This is the parent process.
			# Do our other chores while ftp upload is  running.
			#
			print "parent: child pid=$doup_pid\n";
			
			# Set the clock  (you should probably pick some other
			#    time servers if you are going to use my script!)
			timed_system("ntpdate black-ice.cc.vt.edu clock-2.cs.cmu.edu ntp-0.cso.uiuc.edu",15);
			
			# Fetch my e-mail
			#   getmail is a script that runs popclient
			timed_system("/root/getmail",30);
			print "sleep 5\n";
			sleep 5;

			# Send any waiting outgoing mail
			timed_system("/usr/sbin/runq -d1",30);

			# Sleep awhile to let the ftp upload finish
			# Catch it if it is done.
			print "sleep 30\n";
			sleep 30;
			waitpid($doup_pid,WNOHANG);

			# If upload is not finished
			# (the - checks all processes in the process group).
			if( kill(0, -$doup_pid) ) 
			{
				print " doup still running: sleep 60\n";
				sleep 60;

				# Time's up.  Kill the upload and 
				#   all processes in it's process group.
				if( kill(0, -$doup_pid) ) 
				{
					print "doup hung ($doup_pid)-kill it\n";
					kill(9, -$doup_pid);
					sleep 3;
				}
				waitpid($doup_pid,WNOHANG);
			}
		}
		else  # Child
		{
			# This is the child process.
			# Give ourself a new process group.
			# Start the ftp upload script.
		
			print "child running doup\n";
			setpgrp($$);
			exec("/bin/su -c /home/weather/bin/doup weather");
			print "*********** Should never get here!";
			exit 0;
		}
	}
	#
	# Shutdown the PPP connection
	#
	timed_system("/usr/sbin/dip -k",5);
	timed_system("/bin/date",5);
	
	# Sleep for a while, about right for
	# calling every 15 minutes or so.
	sleep 840;
}

#
# Subroutine to try each of my two dialout scripts if necessary
#
sub dip
{
	local($ret) = 0;
	print ("Trying to dial out\n");
	$ret = timed_system("/usr/sbin/dip -v /root/frii.dip",90);
	print ("dip return value $ret\n");
	if( $ret != 0 )
	{
		timed_system("/usr/sbin/dip -k",10);
		print ("sleep 10 before retry\n");
		sleep 10;
		$ret = timed_system("/usr/sbin/dip -v /root/frii.dip2",90);
		print ("dip2 return value $ret\n");
	}
	return $ret;
}

#
# timed_system subroutine.
# Fork and exec a child process to run another command.
# Time ourself, and kill the child if it goes overtime.
#
sub timed_system
{
        local($command,$time) = @_;
        local($ret) = 9999;
 
	if (!defined($child_pid = fork()))
	{
		print("Fork Error\n");
	}
	elsif ( $child_pid )
	{
		# This is the parent.  Wait and kill if necessary.
		# (Eval/alarm structure taken from perlipc man page.)
		eval
		{
			local $SIG{ALRM} = sub { die "timeout!" };
			alarm $time;
			waitpid($child_pid,0);
			$ret = ($? >> 8);
			alarm 0;
		};
		if ($@ and $@ =~ /timeout/)
		{
			# Kill the child and all in it's process group.
			print "TIMEOUT! [$command]  $child_pid\n";
			kill(9,-$child_pid);
			sleep 2;
			waitpid($child_pid,WNOHANG);
			$ret = 999;
		}
		print "End *** $time [$command] $$ <$ret>\n";
	}
	else
	{
		# This is the child.  Give myself a new process group,
		# then run the command.
		print "Start *** $time [$command] $$\n";
		setpgrp($$);
		exec($command);
		print "*********** Should never get here!";
		exit 0;
	}
	
        return $ret;
}