From: dowding@ai.sri.com (John Dowding)
Newsgroups: comp.lang.perl,comp.unix.admin
Subject: Difficulties running a Perl/tip job from cron
Date: 20 Nov 92 19:32:40 GMT
Followup-To: comp.lang.perl
Distribution: comp
Organization: SRI International, Menlo Park, CA


Quick summary:  I have Perl program that spawns a modified version of
tip that works fine when called from the csh command line, but fails
when called from cron.

The details: I want to run a daily program that logs into a remote
(non-unix site), runs a variety of commands to download some
information (OK, basketball box scores), and exits.  I hacked up the
tip source to rip out the raw-mode stuff, so that tip could be run on
the ends of a pipe.  I then wrote a Perl script to spawn the tip
process, then issue a series of wait-for-prompt/send-string commands,
and send me email with the downloaded information when it finishes.

This script works fine when called from the csh command line, but
when called from cron fails with an infinite loop of 
"can't synchronize with hayes" messages.

The only obvious cron side-effect I know of is that the PATH needs to
be set in the script.  I believe that I have done this correctly, but
please let me know if there is anything I am leaving out.

I have included the relevant portions of the script I am using below,
any help is appreciated.

John Dowding
dowding@ai.sri.com
---------------------------------------------
#! /usr/local/bin/perl

$ENV{'PATH'} = "/usr/ucb:/usr/bin:/usr/local/bin";

$TIPSTRING = "/usr/local/bin/batch_tip tymnet96";

# open a pair of pipes
pipe(FROMPARENT,TOCHILD);
pipe(FROMCHILD,TOPARENT);

# make all pipe handles unbuffered
foreach $f ("FROMPARENT","TOCHILD","FROMCHILD","TOPARENT") {
  select($f); $|++;
}
select(STDOUT);

# Fork or die
$child = fork;
die "Cannot fork: $!" unless defined $child;

# Child code:
unless ($child) { 

# close the other ends
  close(FROMCHILD); 
  close(TOCHILD); 

# Reset STDIN
  close(STDIN);
  open(STDIN,"<&FROMPARENT");
  close(FROMPARENT);

# Reset STDOUT
  close(STDOUT);
  open(STDOUT,">&TOPARENT");
  close(TOPARENT);

  exec $TIPSTRING;

  exit 0;
}

# Now in Parent

# close the other ends
close(FROMPARENT); 
close(TOPARENT); 

#### parent code goes here, reading from FROMCHILD, writing to TOCHILD

# Unset Input record separator
undef $/;

# Allow multi-line patterns
#$* = 1;

open(MAIL, "| mail -s 'Daily Boxes' dowding");

$mail = 1;
# Set a timeout alarm and alarm-handler
alarm(300);

$SIG{'ALRM'} = 'alarm_handler';
$history_line = 0;

&waitfor("log in: ");
&send("linc");

# Long series of &waitfor and &send commands deleted.

&send_chars("~.");

close(TIP);

close(MAIL);

exit;
  

sub alarm_handler {
    print MAIL "Unable to download boxes today\n";
    close(MAIL);
    exit;
}

# waitfor ($string) -- reads output from tip until $string has occurred
sub waitfor {
  local ($string) = @_;
  $byte_counter = 0;
  while (1) {
    $bytes_read = read(FROMCHILD, $_, 1,$byte_counter);
    $byte_counter += $bytes_read;
    if (/\n/) {
      $history[$history_line++] = $_;
      print $_;
      if ($mail) {
	  print MAIL $_;
      }
      $byte_counter = 0;
      $_ = "";
    }
    if (/$string/) {
      print $_;
      if ($mail) {
	  print MAIL $_;
      }
      last;
    }
  }
}


# send string to child, followed by a ^M (octal 15)
sub send {
  local ($string) = @_;

  print TOCHILD $string,"\015";
}


# send chars, but do not send the ^M
sub send_chars {
  local ($string) = @_;

  print TOCHILD $string;
}

--
John Dowding
dowding@ai.sri.com
Newsgroups: comp.lang.perl