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

In the tutorial there is an example of code:
open(FILE, "data.txt"); #opens data.txt in read-mode while(<FILE>){ #reads line by line from FILE w +hich is the fi +lehandle for data.txt chomp; print "Saw $_ in data.txt\n"; #shows you what we have read } close FILE; #close the file.
I've used this code which is similar:
open (FILE, "users"); while (<FILE>) { chomp; ($name, $value) = split(/,/, $_);
Now, that code WORKS, but when I use it in a web-setting, it gives error 500, tho, only if you use the wrong login info... (code is from a login script) if you login correctly, it goes to a page, and seems to work properly... (The actual source is that of an error 500)

That's where I need help, I would like, for cosmetic reasons, to not have error 500's... When I use a veriable other than perls own ($_), it doesn't work properly (tho I may be doing it wrong)... it seems as though it doesn't read some of the file...

If anyone could lend me a hand, I'd be greatful :-)

Edited by Ovid. 2001-04-25

Replies are listed 'Best First'.
Re: file input problem
by Masem (Monsignor) on Apr 25, 2001 at 18:29 UTC
    If 'open' cannot open the file for whatever reason, it will return false; typically most do open (...) or die $!;, but if you want a cleaner way for a CGI output, for example, just test the return value of open, and if false, report that nicely to the user, otherwise continue to read in the file.
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: file input problem
by diarmuid (Beadle) on Apr 25, 2001 at 18:57 UTC
    If you are running it as a cgi script then you must print some http headers before you print the content. For this use CGI.pm

    eg:

    use CGI; my $q = new CGI; print $q->header, # create the HTTP header $q->start_html('Whatever'), # start the HTML open(FILE, "data.txt"); while(<FILE>){ chomp; print "Saw $_ in data.txt<br>\n"; } close FILE; print $q->end_html;
    You could really do with finding out the error_log file for your web server and seeing what it prints out about your script.
    Apache by default has an env.cgi in the cgi-bin directory. Try http://server.name.com/cgi-bin/env.cgi and have a look for the server root directory there.

    If you dont have CGI.pm then try this. I'm not sure if it will work but it should

    print "Content-type: text/html\n\n"; print "<HTML><HEAD><TITLE>STUFF</TITLE>"; print "</HEAD><BODY>" open(FILE, "data.txt"); while(<FILE>){ chomp; print "Saw $_ in data.txt<br>\n"; } close FILE; print "</BODY></HTML>";

    -Diarmuid

Re: file input problem
by little (Curate) on Apr 25, 2001 at 19:05 UTC
    if $q is the cgi object; you might try this (pseudo halfway code)
    # try to open or die but not immediately open $file or go_away($file,$!); sub go_away { $file = shift; $error = shift; # tell the surfer something nice print $q->redirect($url_to_see_nicer_pages_than_500error); # now die and preserve my error log from being incomplete die(couldn't open $file: $error); }
    so U don't loose the info to track on errors and can use your __DIE__ handler but fake a "nice world" to the surfer

    Have a nice day
    All decision is left to your taste
Re: file input problem
by thabenksta (Pilgrim) on Apr 25, 2001 at 18:32 UTC

    I'm a little confused. The code you provided seems to be fine. It would help if you provided some more code for us to look at. I'm pretty sure the error is somewhere else in your script.

    -thabenksta
    my $name = 'Ben Kittrell'; $name=~s/^(.+)\s(.).+$/\L$1$2/g; my $nick = 'tha' . $name . 'sta';
Re: file input problem
by tadman (Prior) on Apr 25, 2001 at 18:58 UTC
    Maybe you're printing the file before your header:
    # (Your print stuff) open (FILE, "..."); # ... my ($cgi) = new CGI; print $cgi->header;
    In this case, the CGI will not output a valid header, instead showing the contents of your file. An invalid header is grounds for a 500 error.

    Note that if you run your script on the command line, it will "work" fine, in as much as it runs, but it will not output the proper header for your Web server.

    For debugging this kind of thing, you absolutely must use CGI::Carp. It's not optional. It will log all errors to your error_log instead of them being lost in the great void.
Re: file input problem
by elwarren (Priest) on Apr 25, 2001 at 20:10 UTC
    Sounds like a permissions issue on the files you're trying to open.

    Check your httpd processes and find out who they run as, then check your file to make sure it is available to the owner of that process. If it runs as nobody, as most good servers should, then you'll want the file to be world readable.
Re: file input problem
by Anonymous Monk on Apr 25, 2001 at 19:58 UTC
    #!/usr/bin/perl use CGI::Cookie; print "Content-type:text/html\n"; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORM{$name} = $value; } $log = $FORM{username}; $pass = $FORM{password}; open (FILE, "users"); while(<FILE>){ $fl = <FILE>; chomp $fl; ($name, $value) = split(/,/, $fl); $refpass = $value; $reflog = $name; close FILE; if ($pass eq $refpass && $log eq $reflog) { print "Set-Cookie: usernamefromzybak=$refpass\n\n"; print <<EndHTML; <html><head><title>testing</title></head> <body> welcome , $FORM{username} <br /> to 171:4's headquarters!<br /> <a href="hq.cgi">Enter now!</a> </body></html> EndHTML close FILE; } } close FILE;
    This is the latest update I have done... it may be working, or I may have been in the middle of something... but this is the entire script.

    Thanks to those that have answered

      The reason you are getting 500 error is becuase you are not printing anything out if the username and password don't match. You need to do an else statement after the if ($pass eq $refpass && $log eq $reflog) that prints out invalid login or something, to account for failed logins.

      -thabenksta
      my $name = 'Ben Kittrell'; $name=~s/^(.+)\s(.).+$/\L$1$2/g; my $nick = 'tha' . $name . 'sta';
        THANK YOU thabenksta!!!!

        although I can't use the else the way the script is now, you were 100% right... no more 500's...

        I have taken some of the other suggestions to heart as well... so thanks to everyone who replied!!!

        now if I knew how to delete the question...
      I don't mean to critisize your code, especially when you haven't asked for this type of comment, but CGI.pm will handle all the parameters for you, so you don't need all the stuff on line five to fourteen. You could even change them to $log=param('username');$pass=param('password');

      It will also generate all the HTML for you. Ovid has an excellent tutorial linked to on his home node that has helped me with CGI a great deal, and talks about why you shouldn't try get the parameters the way you have. He also wrote use CGI or Die;.

      Actually, merlyn beat me to it.

      michael
      the blue haired monk

      Yer?

      uh, the open part of it I was tinkering with, it was always what I had at the top, I changed it to try and avoid the 500's... but it just worked less... :-(

      as for CGI.pm, I wanted to get it working before I tried that, but if you guys think it'd help, I can give it a go...
        well even if the file doesnt exist and you have -w and use strict set you still will not get a 500 error. for example
        #!/usr/local/bin/perl -w use strict; use CGI; my $q = new CGI; print $q->header, # create the HTTP header $q->start_html('Whatever'), # start the HTML open(FILE, "data.txt") while(<FILE>){ chomp; print "Saw $_ in data.txt<br>\n"; } close FILE; print $q->end_html;
        Will produce :
        Content-Type: text/html; charset=ISO-8859-1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head><title>W +hatever</title> Use of uninitialized value in print at ./test.pl line 8. readline() on closed filehandle main::FILE at ./test.pl line 12. </head><body></body></html>
        if data.txt doesn't exist, which most browsers+servers will handle ok....
        Of course I'm not saying you should do it like this :-) D