sidhartha has asked for the wisdom of the Perl Monks concerning the following question:

Hello, Sorry if I'm missing the obvious (yes I'm a newbie) but I've got a simple little cgi script that works flawlessly from the command line but has problems working from the web. It is just supposed to load different background images on each visit. When I run it from the web the bg.cnt file with just counts from 0 to 3 doesn't get written to properly and ends up with nothing in it. The permissions seem ok, with rw-rw-rw on the counting file. Thanks for any help anyone can provide.
#!/usr/bin/perl open IN, "<bg.cnt" or die "can't open bg.cnt"; flock(IN,2); seek(IN,0,0); $cnt=<IN>; close IN; if ($cnt >= 3){ $cnt = 0; } else { $cnt = $cnt + 1; } open OUT, ">bg.cnt" or die "can't open bg.cnt for writing"; flock (OUT, 2); seek(OUT,0,2); print OUT "$cnt \n"; close OUT; @background=("corner.jgp","anduin.jpg","gandalf.jpg","ford.jpg"); print "Content-type: text/html\n\n"; print <<EndOfHTML; <td background="images/$background[$cnt]"> EndOfHTML

Replies are listed 'Best First'.
Re: writing to a file in a cgi script
by gav^ (Curate) on Feb 08, 2002 at 02:38 UTC

      While I agree that File::CounterFile (alt.) is worth using in this instance, it (IIRC) doesn't provide any method for reseting the counter, so your forced to unlink the counter file first, or do something like...

      $counter->lock; $counter->dec while $counter->value > $DEFAULT_VALUE; $counter->unlock;

      Neither solution seemed all that graceful to me (the latter being quite painful if the current value is of any significance), so I ended up writing a patch to add a reset method ...

      sub reset { my($self,$default) = @_; $default = $File::CounterFile::DEFAULT_INITIAL unless defined $default; if ($self->locked) { $self->{'value'} = $default; $self->{updated} = 1; } else { $self->lock; $self->{'value'} = $default; $self->{updated} = 1; $self->unlock; } $self->{'value'}; # return value }

      ... which'd turn sidhartha's code into ...

      #!/usr/bin/perl -w use strict; use File::CounterFile; my $COUNTER = '/path/to/bg.cnt'; my $DEFAULT_VALUE = 0; my @BACKGROUND = qw( corner.jpg anduin.jpg gandalf.jpg ford.jpg ); my $c = File::CounterFile->new( $COUNTER, $DEFAULT_VALUE ); $c->reset if $c->inc > $#BACKGROUND; print <<EndOfHTML; Content-type: text/html <td background="images/$BACKGROUND[$c]"> EndOfHTML

          --k.


        Awesome, I thank all of your for your help.
(cLive ;-) Re: writing to a file in a cgi script
by cLive ;-) (Prior) on Feb 08, 2002 at 04:43 UTC
    My guess is that the path to file is wrong.

    You can check this using the Cwd module.

    #!/usr/bin/perl use strict; use CGI; my $q = new CGI; use Cwd; $dir = cwd; print $q->header('text/plain'), $dir; exit(0);

    My bet is that the current working directory isn't what you think it is when run as a CGI script.

    Alternatively, use an absolute path rather than a relative one, ie:

    open OUT, ">/path/to/bg.cnt" or die "can't open bg.cnt for writing";

    .02

    cLive ;-)

    ps - and including $! in the die statment will help - if you put:

    use CGI::Carp 'fatalsToBrowser'
    at the beginning of your script.
Re: writing to a file in a cgi script
by Kanji (Parson) on Feb 08, 2002 at 07:38 UTC

    On "missing the obvious", there are several things you can do to help make sure you don't ...

    • use strict;
    • -w (or use warnings;)
    • Including $! in your dies so you know why something couldn't be done.

    You might also find Use strict warnings and diagnostics or die a worthwhile read. :)

        --k.


Re: writing to a file in a cgi script
by redsquirrel (Hermit) on Feb 08, 2002 at 06:12 UTC
    cLive ;-) is right, it's the images path that's messed up. You are probably running your script out of cgi-bin and I highly doubt that your images are located in cgi-bin/images/, right?

    Also wondering why you feel the need to use seek here...looks like it would work identically without it.

    --Dave

      this is true but i'm using SSI so the images directory is relative to my htdocs directory. thanks for the tip on the seek, i'll see about getting rid of that
Re: writing to a file in a cgi script
by rjray (Chaplain) on Feb 08, 2002 at 07:33 UTC

    The previous posters have covered most of the bases. When you go to try and debug this, keep in mind these specific things to watch/look for:

    • The background attribute for the td element should probably be something more like "/images/$background[$cnt]", unless you are certain that the pages using this script (it's clearly an SSI utility) will always be in the directory above that images directory.
    • Check the actual path to the counter-file. Or use the File::CounterFile module. The cgi-bin directory might not be where you want this file getting opened.
    • Check the UID/GID that the CGI application is running under. Running the script from the command-line as yourself isn't the same as having it run as a CGI under the UID of the web server's process.

    --rjray