Solved

Problems with 'use of uninitialized value' using ReadParse in CGI

Posted on 1997-10-20
19
699 Views
Last Modified: 2013-12-25
Hi There,

Weel my problem seems to be a catch 22 sistuation. I have used numerous hours trying to figure out why ReadParse returns a value of '0' when it reads from a HTML form using the POST method. When I test the script from the browser it exits to the error message. When I test it from a commandline it returns the error message:

Use of uninitialized value at manpage.pl line 24.
Content-type: text/html
Status: 500 UNIX Manual Page Gateway Error

<html>
<head><title>CGI Program - Unexspected Error</title></head>
<body>
<h1>UNIX Manual Page Gateway Error</h1>
<hr>Invalid manual page specification.<hr>
Please contact <a href="mailto:you@your.address">Name (cj@hum.auc.dk)</a> for more information!
</body>
</html>

The script is written to work as a gateway for displaying UNIX man pages in HTML format. i have tried to get teh script to print $_ as well as <STDIN> before executing anything else, but it still returns a vaule of '0' and fails. How can I solve this problem? Should I use CGI.pm instead og the ReadParse in the standard cgi-lib.pl??? What gives...

Sincerely,  Chris.

Below is the script:
!# /path/to/perl -w
require "cgi-lib.pl";

$webmaster = "Your Name Here(name\@your.address)";
$script = $ENV{'SCRIPT_NAME'};
$man_path = "/path/to/man";
$nroff = "/path/to/nroff -man";
$last_line = "Last change:";


&ReadParse (*FORM);

my $manpage = $FORM{'manpage'}; #this is where it fails
my $section = $FORM{'section'};

($manpage = $FORM{'manpage'}) =~ s/^\s*(.*)\b\s*$/$1/;

if ( (!$manpage) || ($manpage !~ /^[\w\+\-]+$/) ) {
   &error (500, "UNIX Manual Page Gateway Error", "Invalid manual page specification.");
}
else
{
   if ($section !~ /^\d+$/) {
       $section = &find_section ();
       } else {
       $section = &check_section ();
}
   if ( ($section >= 1) && ($section <= 9) ) {
   &display ();
}
else
{
   &error (500, "UNIX Manual Page Gateway Error", "Could not find the requested document.");
}
}

exit (0);

sub find_section {
    local ($temp_section, $loop, $temp_dir, $temp_file);

    $temp_section = 0;

    for ($loop = 1; $loop <= 9; $loop++) {
        $temp_dir = join ("", $man_path, "/man", $loop);
        $temp_file = join ("", $temp_dir, "/", $manpage, ".", $loop);
   
        if (-e $temp_file) {
           $temp_section = $loop;
        }
    }
    return ($temp_section);
}

sub check_section {
    local ($temp_section, $temp_file);
    $temp_section = 0;
    $temp_file = join ("", $man_path, "/man", $section, "/", $manpage, ".", $section);

    if (-e $temp_file) {
       $temp_section = $section;
    }
    return ($temp_section);
}

sub display {
    local ($file, $blank, $heading);
    $file = join ("", $man_path, "/man", $section, "/", $manpage, ".", $section);

    print "Content-type: text/html\n\n";
    print "<HTML>\n";
    print "<HEAD><TITLE>UNIX Manual Page Gateway</TITLE></HEAD>\n";
    print "<BODY>\n";
    print "<p align=\"center\"><font size=\"6\"><strong>UNIX Manual Page Gateway</strong></font></p>\n";
    print "<p><pre>\n";

    open (MANUAL, "$nroff $file |");
    $blank = 0;
    while (<MANUAL>) {
       next if ( (/^$manpage\(\w+\)/i) || (/\b$last_line/o) );

    if (/^([A-Z0-9_ ]+)$/) {
        $heading = $1;
        print "<H2>", $heading, "</H2>", "\n";
    } elsif (/^\s*$/) {
        $blank++;
        if ($blank < 2) {
           print;
        }
    } else {
        $blank = 0;
        s//&amp;/g    if(/&/);
        s//&lt;/g     if(/</);
        s//&gt;/g     if(/>/);
 
        if (/((_\010\S)+)/) {
           s//<B>$1<\/B>/g;
           s/_\010//g;
        }

        if ($heading =~ /ALSO/) {
           if (/([\w\+\-]+)\((\w+)\)/) {
              s//<A HREF="$script\?manpage=$1\&section=$2">$1($2)<\/A>/g;
           }
        }

        print;
     }
  }

  print "</pre><hr>\n";
  print "</BODY></HTML>\n";
  close (MANUAL);
}

sub error {

   local ($status, $keyword, $message) = @_;

   print "Content-type: text/html", "\n";
   print "Status: $status $keyword\n\n";
   print "<html>\n";
   print "<head><title>CGI Program - Unexspected Error</title></head>\n";
   print "<body>\n";
   print "<h1>$keyword</h1>\n";
   print "<hr>$message<hr>\n";
   print "Please contact <a href=\"mailto:name\@your.address\">$webmaster<\/a> for more information!\n";
   print "</body>\n";
   print "</html>\n";
   close();

exit (1);
}
0
Comment
Question by:Bastholm
  • 9
  • 7
  • 3
19 Comments
 
LVL 7

Expert Comment

by:faster
ID: 1830962
It has no reason to fail there.  Probably you didn't config your cgi or cgi-lib correctly.
0
 

Author Comment

by:Bastholm
ID: 1830963
What do you mean when you say: Probably you didn't config your cgi or cgi-lib correctly??

My sys.adm. has used this cgi-lib.pl in other scripts and so have I - without any problems. I have used ReadParse prior to this script in a cgi-mail gateway - no problemo!

The script is running on a UNIX(r) System V Release 4.0 server, but I'm planning on moving all my scripts to an Apache 1.2.4 server running under SunOS 5.6 - and maybe using CGI.pm instead.

0
 
LVL 6

Expert Comment

by:alamo
ID: 1830964
Your script looks fine, in fact I tested the relevant portions of it here and it worked. You should do 2 things next to debug this:

- Post here the HTML source of the form which calls the script - this problem could be as simple as the fieldnames not matching (wrong case for example). If I made the fieldnames wrong on purpose in my test html I got the same errors you did.

- As a debugging measure change the method from POST to GET and see if the behavior changes. This might eliminate a few possibilities.
0
 

Author Comment

by:Bastholm
ID: 1830965
Hi Alamo,

This is how my html-form looks. My first "name=manpage" should work if I say $in{'manpage'} = $value and then put than into my variable $manpage - or not? And the same for "name=section" ?
What did you use in your form for "name=" in the textfield and selection?

The html-form I use is the following:

<form action="http://path/to/cgi-bin/manpage.pl"
method="POST">
<p><font size="2" face="Verdana, Arial,Helvetica">Command:</font> <input type="text" size="40" name="manpage"></p>
<p><font size="2" face="Verdana, Arial, Helvetica">Which section is the man page located in?</font>
<select name="section" size="1">
<option selected>Don't know</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
</select></p>
<p><input type="submit" value="Submit">
<input type="reset" value="Clear Form"></p>
</form>

0
 
LVL 6

Expert Comment

by:alamo
ID: 1830966
Unfortunately it looks like everything you are doing in your HTML and your .pl is correct :) Your HTML uses the same field names as I did, as expected. Maybe some quirk of the way your server sets up the environment or in how cgi-lib.pl runs on your particular version of perl is responsible. Here are some suggestions:

- make certain the version of cgi-lib.pl perl is using is what you expect - make the path explicit rather than depending on @INC (perhaps an old version is laying around somewhere on your system).

- Change POST to GET. GET is a little simpler and is probably the right choice for your script in the first place, anyway - the result of a GET can be bookmarked which seems useful for a manpage utility.

- If that doesn't work, decide whether you want to debug a library module. (The usual answer is 'no', though I am sometimes stubborn enough to debug it just to get it working, and then throw it away since it was so buggy in the first place).
Start by putting in a couple of lines of code to print out the contents of $ENV{} so you can check what you are being passed.  

You could also ditch cgi-lib.pl and add a simple ReadParse-like function into your code, it's not that hard. If you choose this path I can post one I have used. Or, as you considered in the first place, use CGI.pm. Of course it's unlikely but certainly possible you will have similar problems with CGI.pm as well.
0
 

Author Comment

by:Bastholm
ID: 1830967
Hi alamo,

I hope you understand why I have been bewildered about this problem ;-) and I have reached the point where I want to abort using the readparse in cgi-lib.pl, and I have just tried using CGI.pm - guess what? same thing! I would very much like to see the code you are using for a local readparse function :-)

The thing about the GET vs. POST action yopu point out I must admit I never thought of.. I'll use GET instead, thanx.

And I thank you for your help!! SMILES ALL AROUND - even my sys.adm ;-)
0
 
LVL 7

Expert Comment

by:faster
ID: 1830968
This has to be some config problem, since all the html and pl are files are correct.  We just use your code for test and it turns out to be OK.

You can try one thing: put debug lines in cgi-lib.pl's ReadParse function and see where it goes wrong.  By trying this for several times( put it in different places to locate the exact problem), you should be able to solve it quickly.
0
 
LVL 7

Expert Comment

by:faster
ID: 1830969
For example, you can use the following code to replace the corresponding part of your cgi-lib.pl and see what it outputs.


  if ($len > $cgi_lib'maxdata) { #'
      &CgiDie("cgi-lib.pl: Request to receive too much data: $len bytes\n");
  }

print "type=$type,len=$len,meth=$meth\n";
 
  if (!defined $meth || $meth eq '' || $meth eq 'GET' ||
      $type eq 'application/x-www-form-urlencoded') {
    local ($key, $val, $i);
print "0000000000000";
       
    # Read in text
    if (!defined $meth || $meth eq '') {
      $in = $ENV{'QUERY_STRING'};
      $cmdflag = 1;  # also use command-line options
    } elsif($meth eq 'GET' || $meth eq 'HEAD') {
      $in = $ENV{'QUERY_STRING'};
    } elsif ($meth eq 'POST') {
print "11111111111111";
        if (($got = read(STDIN, $in, $len) != $len))
          {$errflag="Short Read: wanted $len, got $got\n";};
    } else {
      &CgiDie("cgi-lib.pl: Unknown request method: $meth\n");
    }


0
 
LVL 6

Expert Comment

by:alamo
ID: 1830970
Here's the simple drop-in replacement for ReadParse which assumes you are using GET. It's not intended to be general-purpose. Comment out the require line for cgi-lib.pl.

sub ReadParse {
  *FORM = pop;
  local(@rawargs) = split(/&/, $ENV{'QUERY_STRING'});
  foreach (@rawargs) {
    local($name, $value) = split(/=/);
    $value =~ tr/+/ /;
    $value =~ s/%([a-fA-F0-9]{2})/pack("C", hex($1))/eg;
    $FORM{$name} = $value;
  }
}

I suggest for debugging you add the following lines after calling ReadParse:

print "Content-type: text/html\n\n";  # need headers
foreach (keys %ENV) { print "ENV: $_=$ENV{$_}<br>\n"; } # print Environment
foreach (keys %FORM) { print "FORM: $_=$FORM{$_}<br>\n"; } # print form values

I would expect the following values in your environment:

ENV: REQUEST_METHOD=GET
ENV: QUERY_STRING=manpage=command&section=1 (exact values depend on query of course)

If you don't see those, something is wrong in how your script is being called - configuration, as faster said. If this works but you want to figure out what was wrong before, I'd expect the following in your previous program using POST:

ENV: REQUEST_METHOD=POST
ENV: HTTP_CONTENT_LENGTH=25 (exact length isn't that important)
ENV: HTTP_CONTENT_TYPE=application/x-www-form-urlencoded
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:Bastholm
ID: 1830971
Hi alamo and faster,

I have put the ReadParse function alamo included and changed the method to GET - and it works :) just fine now - except for the formatting of the nroff pages - but that might have something to do with the format of our man pages. The script runs fine and it returns:
 
print "Content-type: text/html\n\n"; # need headers
                   foreach (keys %ENV) { print "ENV: $_=$ENV{$_}<br>\n"; } # print Environment
                   foreach (keys %FORM) { print "FORM: $_=$FORM{$_}<br>\n"; } # print form values

as it is supposed to.

I haven't had time to test faster's add-on-script on my local cgi-lib.pl - but I hope to get it done quickly.

cheers!
0
 
LVL 6

Accepted Solution

by:
alamo earned 100 total points
ID: 1830972
Well, since the GET function I posted as a comment worked, let me propose it as the answer :-) We can continue to debug your POST problem via comments. The ENV debugging code I gave you should help determine where the problem was - maybe in the environment passed to you, maybe in the read from STDIN of the POST arguments  , maybe something else.
0
 

Author Comment

by:Bastholm
ID: 1830973
Thanx to both alamo and faster for their help with my problem - faster eventually ;-) threw in a couple of goodies to use in debugging my script!
0
 

Author Comment

by:Bastholm
ID: 1830974
Hi all,

Just a question: did the formating from nroff to html work fine in the environment you tested the script? I have tried to fiddle around with the $nroff = "/path/to/nroff -man"; statement - alternatively I have used -sun and some of the -ehiq switches. If you try to use these switches what sort of output behaviour do you get? Mine is all f... up - including the formating of the nroff in this statement - it just doesn't get the job done:

else {
                   $blank = 0;
                   s//&amp;/g if(/&/);
                   s//&lt;/g if(/</);
                   s//&gt;/g if(/>/);
                 
                   if (/((_\010\S)+)/) {
                   s//<B>$1<\/B>/g;
                   s/_\010//g;
                   }

                   if ($heading =~ /ALSO/) {
                   if (/([\w\+\-]+)\((\w+)\)/) {
                   s//<A HREF="$script\?manpage=$1\&section=$2">$1($2)<\/A>/g;
                   }

Just more trouble heading my way ;-[
0
 
LVL 6

Expert Comment

by:alamo
ID: 1830975
Well I orginally stripped that whole function out of my test, since it really wasn't relevant to the previous problem, but i took a look at it now. The biggest thing I noticed is that you weren't properly dealing with the bold sequence (at least on my nroff output). On mine, to bold a character it issues \010 and the character a few times, and to underline it it preceeds it with _\010. I think your code
  if (/((_\010\S)+)/) {
     s//<B>$1<\/B>/g;
     s/_\010//g;
  }
was supposed to do this. Replace the above code with:

# convert x\010x sequences to <b>x</b>
# need to check for < > & since we aleady converted them to multichar sequences
  s/(&amp;|&lt;|&gt;|.)(\010\1)+/<b>$1<\/b>/g;
  s/<\/b><b>//g;
# do same for underlined text - though in this case we convert to <i>
  s/(_\010)+(.)/<i>$2<\/i>/g;
  s/<\/i><i>//g;

If your output is anything like mine this will make a big difference. You still need to detect headers properly (move the header check to after the above code, not the first thing in the function, and change what it's looking for). This should get you a lot farther though and give you something to work with.
0
 

Author Comment

by:Bastholm
ID: 1830976
That snippet of code really helped alot, the full man-page is now displayed with the bold and italics (as expected ;-)) - but I still have the problem with the style for SYNOPSIS, DESCRIPTION etc. they are displayed as:

SSSSYYYYNNNNOOOOPPPPOOOOSSSSIIIISSSS

I have looked in the info on nroff that is available to me (not much) but I can't really figure out what sort of nroff heading I'm supposed to look for to replace with a html <h3>

if (nroff format) {
s/(format)+/<h3>$3<\/h3>/g;
s/<\/h3><h3>//g;
}

Who said it was ever going to be easy?!


0
 
LVL 6

Expert Comment

by:alamo
ID: 1830977
Isn't the heading line simply bold? for example, if you don't check for the header at all does it get converted to bold by the code you just added? That's how it looks to me. If not- maybe you could nroff -man (file) >out and make the out file accessible somewhere on the web so I see exactly what the codes are.
0
 

Author Comment

by:Bastholm
ID: 1830978
The nroff output is available at this url:

http://www.hum.auc.dk/~cj/nroff.format.txt

I have captured the perl.1 document and saved it to this file.
All the codes should be there.

If you want to see the scripts output - go to:

http://www.hum.auc.dk/~cj/unix.html -  then type in perl

(notice that it is NOT all commands which can be found??!!).
0
 
LVL 6

Expert Comment

by:alamo
ID: 1830979
Hi Bastholm, I didn't just forget about you, but I have tried that page every few days for 2 weeks now and I have always gotten the html form but the submit never ever connects. Is the action URL correct? Is the CGI machine behind a firewall or somehow otherwise inaccessible? If you can make it accessible to me I'll still look at it.
0
 

Author Comment

by:Bastholm
ID: 1830980
The local sys.adm has moved the Apache-server I use behind a local firewall which means that the script is only accessible to someone on the local network - I'll see if I can get him to put my script on another server - and then I'll post the URL that can access it, OK ;-) Sorry about the hassle.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
php survey script 4 57
website content maintenance 3 57
Problem to file 3 47
Problem to ToolkitScriptManager 2 28
Shoutout to Emily Plummer (http://www.experts-exchange.com/members/eplummer26.html) for giving me this article! She did most of it, I just finished it up and posted it for her :)    Introduction In a previous article (http://www.experts-exchang…
Styling your websites can become very complex. Here I'll show how SASS can help you better organize, maintain and reuse your CSS code.
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now