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;
}