Simple code runs on linux, but not on windows -- why?

S

Suresh Govindachar

#!/usr/bin/perl
use warnings;
use strict;
use CGI qw:)standard);

=head

This .pl file runs correctly on a linux box, but gives
the following wrong output on Win98 active perl 5.8.0:

|>perl bug.pl
| Enter a number (>=1): 1234
|
| rolls of a fair die:34
|
| was returned from get_input

Commenting out either one of (not necessarily both of)
the lines "use CGI qw:)standard);" or "chomp $number;"
generates expected output.

What is the explanation?

Thanks,

--Suresh

=cut

my $the_number = &get_input;

print "\n\tResults of $the_number rolls of a fair die:\n\n";
print "The number $the_number was returned from get_input\n\n\n";

#### get_input ##################################
sub get_input()
{
my $number = 0;
{
print "\tEnter a number (>=1): ";
$number = <STDIN>;
chomp $number;
($number <=0) and redo;
}
return $number;
}
 
A

Alan J. Flavell

#!/usr/bin/perl
use warnings;
use strict;
use CGI qw:)standard);
[...]

This .pl file runs correctly on a linux box, but gives
the following wrong output on Win98 active perl 5.8.0:
[...]

Commenting out either one of (not necessarily both of)
the lines "use CGI qw:)standard);" or "chomp $number;"
generates expected output.

What is the explanation?

If you're aiming to read STDIN yourself, why would you be using
CGI.pm? In the CGI environment, STDIN holds the POST data provided by
the Common Gateway Interface.

If you're using CGI.pm, then it will take care of reading the
POST data from STDIN, with whatever binmode() settings it considers
appropriate for the platform.

But your code is apparently expecting to read in text mode, so if
CGI.pm decides to set binmode() then it gets confused. Your data has
an unexpected \015 on the end of it, so it no longer checks out as a
number. Or something close to that, anyway.

good luck
 
S

Suresh Govindachar

Alan J. Flavell wrote
#!/usr/bin/perl
use warnings;
use strict;
use CGI qw:)standard);
[...]

This .pl file runs correctly on a linux box, but gives
the following wrong output on Win98 active perl 5.8.0:
[...]

Commenting out either one of (not necessarily both of)
the lines "use CGI qw:)standard);" or "chomp $number;"
generates expected output.

What is the explanation?

If you're aiming to read STDIN yourself, why would you be using
CGI.pm?
------------------------------------------
The context: For homework, we need to provide a .cgi and a .pl
solution. I am trying to submit a single .cgi file that can run
in the shell too -- using things like:

sub get_input()
{
(param()) ? return &get_cgi_input : return &get_shell_input;
}

The homework is verified on a linux machine, and the single
..cgi file runs correctly on the linux-shell too. But to do
the homework, I use a win98 active perl 5.8.0 machine on which
the .cgi cannot get the dos-shell input correctly.

------------------------------------------
In the CGI environment, STDIN holds the POST data
provided by the Common Gateway Interface.

If you're using CGI.pm, then it will take care of reading the
POST data from STDIN, with whatever binmode() settings it considers
appropriate for the platform.

But your code is apparently expecting to read in text mode, so if
CGI.pm decides to set binmode() then it gets confused. Your data has
an unexpected \015 on the end of it, so it no longer checks out as a
number. Or something close to that, anyway.

good luck

Thanks for the explanation. Is it possible to do something
like:

(param()) or "set binmode() to something for shell input";

If so, what?

Another thing I noticed is that when the taint flag (-T) in on,
the .cgi can be run in the linux-shell but not in a dos-shell;
the dos-shell generates the error message:

|>perl bug.pl
|Too late for "-T" option at bug.pl line 1.

How come the dos-shell is more strict than the linux-shell?

--Suresh
 
G

Gunnar Hjalmarsson

Suresh said:
Another thing I noticed is that when the taint flag (-T) in on, the
.cgi can be run in the linux-shell but not in a dos-shell; the
dos-shell generates the error message:

|>perl bug.pl
|Too late for "-T" option at bug.pl line 1.

How come the dos-shell is more strict than the linux-shell?

Don't know, but I know you can invoke the program like this:

perl -T myscript.cgi
 
M

Matt Garrish

Gunnar Hjalmarsson said:
Don't know, but I know you can invoke the program like this:

perl -T myscript.cgi

Because even though the shebang line is ignored in DOS, you can still pass
through arguments like -w on it (I could be very wrong here, but my
understanding is that the DOS shell needs to know what program to use before
it will process a file, so the path to Perl is useless but the switches are
still respected). -T, as the warning notes, cannot be invoked after the
executable has been called.

Matt
 
A

Alan J. Flavell

Suresh said:
Another thing I noticed is that when the taint flag (-T) in on, the
.cgi can be run in the linux-shell but not in a dos-shell; the
dos-shell generates the error message:

|>perl bug.pl
|Too late for "-T" option at bug.pl line 1.

How come the dos-shell is more strict than the linux-shell?

Don't know, [...]

But also in linux etc., if you attempt to run

perl bug.pl

and bug.pl specifies -T , then you'll get the above diagnostic.

It's only when you execute the script directly, i.e by turning its
execute bit on and nominating it (and not perl) as the command to run
from the shell, that the -T will be accepted.
 
G

Gunnar Hjalmarsson

Suresh said:
Is it possible to do something like:

(param()) or "set binmode() to something for shell input";

If you want to be able to invoke the script both from shell and CGI, I
suppose you can simply do something like this:

if ($ENV{GATEWAY_INTERFACE}) {
require CGI;
import CGI qw:)standard);
}
 
A

Alan J. Flavell

But also in linux etc., if you attempt to run

perl bug.pl

and bug.pl specifies -T , then you'll get the above diagnostic.

It's only when you execute the script directly, i.e by turning its
execute bit on and nominating it (and not perl) as the command to run
from the shell, that the -T will be accepted.

Of course I didn't quite mean what I said there: if bug,pl specifies
-T in its shebang line, you /could/ still issue

perl -T bug.pl

and it will work fine. But the regular unix/linux way would be to
turn the execute bit on, and call bug.pl directly from the shell, and
then the -T on the shebang line is honoured.
 
G

Gunnar Hjalmarsson

Matt said:
Because even though the shebang line is ignored in DOS, you can
still pass through arguments like -w on it (I could be very wrong
here, but my understanding is that the DOS shell needs to know what
program to use before it will process a file, so the path to Perl
is useless but the switches are still respected). -T, as the
warning notes, cannot be invoked after the executable has been
called.

I just thought that the latter was true on Linux as well, and when I
just tested I found that it is if you invoke the script with

perl myscript.cgi

But if you set the exec bit and let the shebang line find perl, i.e.
invoke the script by just saying

myscript.cgi

you don't get that error message.
 
T

Tad McClellan

Suresh Govindachar said:
The context: For homework, we need to provide a .cgi and a .pl
solution. I am trying to submit a single .cgi file that can run
in the shell too -- using things like:

sub get_input()


You probably shouldn't be using prototypes, are you using them
on purpose or by accident?


{
(param()) ? return &get_cgi_input : return &get_shell_input;


This is likely "better":

-t STDIN ? return &get_shell_input : return &get_cgi_input;

and if that is a little better, then this is a lot better still:

return -t STDIN ? get_shell_input() : get_cgi_input();

( Using ?: for its side effects is a bad idea. You should use
it for the value that it returns instead.

You shouldn't use ampersand on function calls unless you know
what it does, and what it does is what you want.
)
 
B

Ben Morrow

( Using ?: for its side effects is a bad idea. You should use
it for the value that it returns instead.

Could you give some reasons for this? Obviously in the case you were
referring to 'return x ? y : z' is preferable to 'x ? return y : return
z', simply because it avoids duplicating the return; but if the
statement had been, say, 'x ? return y : die z', what would be wrong
with it?

(FWIW, I would say that the change to ?? :: to match && and || in perl6
indicates that Larry agrees with me; also, I for one would really like a
low-precedence keyword version, though precedence means that 'x and y or
z' is usually good enough.)

Ben
 
J

James Willmore

On Sat, 21 Feb 2004 21:22:42 +0000, Suresh Govindachar wrote:

The context: For homework, we need to provide a .cgi and a .pl
solution. I am trying to submit a single .cgi file that can run
in the shell too -- using things like:
<snip>

use CGI qw:)standard -debug);

Now, you can run the script either on the command line or through a web
server.

`perldoc CGI` for more information.

HTH

--
Jim

Copyright notice: all code written by the author in this post is
released under the GPL. http://www.gnu.org/licenses/gpl.txt
for more information.

a fortune quote ...
Computers will not be perfected until they can compute how much
more than the estimate the job will cost.
 
T

Tad McClellan

Ben Morrow said:
Could you give some reasons for this?


It's just my personal style I guess.

I like if/else actions to look like it.

?: for me is an if/else value rather than an if/else action.

if the
statement had been, say, 'x ? return y : die z', what would be wrong
with it?


Too little typing for my tastes. :)

if ( x )
{ return y }
else
{ die z }

seems to communicate much more clearly what is going on in the flow.

I am generally willing to spend a little more effort upfront if I
get a lot of debugging benefit later on. I drop bread crumbs to
help me find my way if I should become lost.

I seem to get the "opportunity" to debug my code more often than
I feel is strictly necessary. When I do have to debug, I want it
to be over with as soon as possible. :)

If I can read and understand the code faster, I can fix the problem faster.
 
S

Suresh Govindachar

#!/usr/bin/perl
use warnings;
use strict;

use CGI qw:)standard);

=begin comment

Thanks for all the private and public response.

The upshot is that "use CGI qw:)standard);" results
in the $/ variable having the wrong value for STDIN,
and chomp'ing the stuff read from STDIN cannot remove
a trailing "\r" in the stuff.

Using the command "binmode STDIN;" before reading
from STDIN did not help.

Using "use CGI qw:)standard -debug);" is not a solution
since the context calls for the shell code to use
a different input scheme from that used by the cgi code;
and -debug is for when the shell code takes its input
using the same scheme as the cgi (for example, with
commands such as param("keyword")).

I haven't yet figured out hot to use the suggestion:

if ($ENV{GATEWAY_INTERFACE})
{
require CGI;
import CGI qw:)standard);
}

since the code has lines such as the following:

print header; # executed when param()

which causes the compiler to complain.

Anyway, for those who are interested in some more insight,
consider running this code on Windows with and
without commenting out the "use CGI qw:)standard);" line.

=end comment

=cut

(0) and print header; #compiler will complain if without CGI

print "Enter a number: ";
my $the_number = <STDIN>;

$the_number =~ m/\d*(.*)/so;
my $tail = $1;

($/ eq "\n") and print "\tchomp eats \\n\n";
($/ eq "\r") and print "\tchomp eats \\r\n";
($/ eq "\r\n") and print "\tchomp eats \\r\\n\n";

($tail eq "\n") and print "\ttail equals \\n\n";
($tail eq "\r") and print "\ttail equals \\r\n";
($tail eq "\r\n") and print "\ttail equals \\r\\n\n";

print "\nchomp will FAIL and output will look garbled\n" unless ($tail eq
$/);

chomp $the_number;

print "\n\tResults of $the_number rolls of a fair die:\n\n";
print "The number $the_number was returned from get_input\n\n\n";
 
G

Gunnar Hjalmarsson

Suresh said:
I haven't yet figured out hot to use the suggestion:

if ($ENV{GATEWAY_INTERFACE})
{
require CGI;
import CGI qw:)standard);
}

since the code has lines such as the following:

print header; # executed when param()

which causes the compiler to complain.

You'd better say:

print header();

as long as CGI.pm is not always loaded in compile time.

Then you could for instance put that in the same block:

if ($ENV{GATEWAY_INTERFACE})
{
require CGI;
import CGI qw:)standard);
print header();
}

or in some other block that is only executed when the script is
invoked from shell.
 
L

Lukas Mai

Tad McClellan schrob:
[...]
You should not use modifiers that you don't understand. m//o is
useless for your pattern.
my $tail = $1 if $the_number =~ m/\d+(.*)/s;

Whoa! Don't do that! The behaviour of
`my $foo if bar;' is undefined (see perldoc perlsyn).

HTH
Lukas
 
A

Anno Siegel

Tad McClellan said:
It's just my personal style I guess.

I like if/else actions to look like it.

?: for me is an if/else value rather than an if/else action.




Too little typing for my tastes. :)

if ( x )
{ return y }
else
{ die z }

seems to communicate much more clearly what is going on in the flow.

I am generally willing to spend a little more effort upfront if I
get a lot of debugging benefit later on. I drop bread crumbs to
help me find my way if I should become lost.

I seem to get the "opportunity" to debug my code more often than
I feel is strictly necessary. When I do have to debug, I want it
to be over with as soon as possible. :)

If I can read and understand the code faster, I can fix the problem faster.

On the other hand, compactness has merits of its own when it comes to
organizing code. Sources can become drawn out in the name of clarity
(not to mention overloaded with stimuli like a plane cockpit).

I tend to write fresh code in the most compact style that is comfortable.
Yes, it is a write-only style, but that very fact helps avoid bugs in
the first place. When there's trouble, I don't hesitate to re-write the
critical part more explicitly. Typically, that means "map" and "grep" may
be replaced by loops, statement modifiers may be replaced by the full
form and "?:" by "if/else".

The re-writing takes some time, but some of that you have saved while
coding. It can also be seen as time spent understanding the code.
Finally, it's a skill, you become quite adept at it.

I rarely change it back, unless it really hurts the eye. The change in
style, plus comments and commented-out debugging statements mean "bumpy
road ahead", even to a reader other than myself.

Anno
 
T

Tad McClellan

Lukas Mai said:
Tad McClellan schrob:
[...]
You should not use modifiers that you don't understand. m//o is
useless for your pattern.
my $tail = $1 if $the_number =~ m/\d+(.*)/s;

Whoa! Don't do that!


Why not?

The behaviour of
`my $foo if bar;' is undefined


I believe that that is incorrect.

The docs themselves use that form twice that I can see:

perl -ne 'print "$ARGV: $_" if /^\s+my\b.*\bif\b/' *.pod

perltooc.pod: my $class = ref $self if $self;
perlwin32.pod: my @g = File::DosGlob::glob($_) if /[*?]/;

(see perldoc perlsyn).


Whereabouts in perlsyn, exactly?

I looked for every occurance of "my", "undef" and "defined"
in perlsyn.pod, and I didn't see that anywhere.

Please quote a bit of perlsyn that made you think that the behavior is
not defined.
 
B

Ben Morrow

Lukas Mai said:
Tad McClellan schrob:
[...]
You should not use modifiers that you don't understand. m//o is
useless for your pattern.
my $tail = $1 if $the_number =~ m/\d+(.*)/s;

The behaviour of
`my $foo if bar;' is undefined

I believe that that is incorrect.
(see perldoc perlsyn).

Whereabouts in perlsyn, exactly?

From perlsyn.pod of 5.8.2, at the end of the section "Statement
Modifiers":
| NOTE: The behaviour of a "my" statement modified with a statement
| modifier conditional or loop construct (e.g. "my $x if ...") is
| undefined. The value of the "my" variable may be "undef", any
| previously assigned value, or possibly anything else. Don't rely on
| it. Future versions of perl might do something different from the
| version of perl you try it out on. Here be dragons.

Presumably what is meant is 'The value of the "my" variable [if the
condition is false] may be...'

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top