So, with a few comments from some of the monks here, I've made some simplifications. Thanks especially to
crazyinsomniac for suggesting
Tie::File. I had read about it before, but using it didn't even occur to me.
#!perl -wT
#config variables
my $logfile = q(D:\httpd\Apache\logs\error.log);
my $domain = "";
my $path = "";
my $expires = "";
my $cookiename = "veloglastline";
###########################################
#
# A very simple error_log viewer CGI script for Apache
# more instructions will be provided later.
# Error lines are wrapped with Text::Wrap
# Each time the script is loaded, it tries to set a cookie
# containing the last line read in the error log.
# Each load of the script accesses the cookie and only
# displays unread lines.
#
# useage:
# http://host/path/velog.cgi will show the lines
# in the error log you haven't seen yet.
# http://host/path/velog.cgi?all=234 will show all
# the lines in the error log
use strict;
use CGI;
use Text::Wrap;
use Tie::File;
my $q = CGI->new();
my $lastline;
my @filelines;
my @unread;
my $cookie;
$cookie = $q->cookie($cookiename) || 0;
if($cookie =~ m/^(\d*)$/) {$lastline = $1;}
else{$lastline = 0;}
$lastline = 0 if(defined($q->param("all")));
tie (@filelines, 'Tie::File', $logfile, autochomp => 0) ||
die "unexpected error opening $logfile: $!";
@unread = @filelines[$lastline .. $#filelines];
@unread = ("No new entries found") if($#unread == 0);
$cookie = $q->cookie({-name => $cookiename,-value => $#filelines,
-domain => $domain, -expires => $expires, -path => $path });
print $q->header(-type => "text/plain", -cookie => $cookie),
wrap("", "", @unread);