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

not very used to using strict... having a simple scoping problem. for some reason i cant get the value of the @command in my IF statement. But i can get the value of another array (valid_commands) in there with no problem... any ideas. (The sub at the way bottom)

#!/usr/bin/perl require 5.002; use Socket; use strict; use Carp; if ($ARGV[0] eq "--debug") { print "Warnings are enabled.\n"; use warnings; } $| = 1; my ($hostname,$port,$iaddr,$paddr,$proto,$line,$name); $hostname= 'localhost'; $port = 2424; $proto = getprotobyname('tcp'); $iaddr = inet_aton($hostname) or die "no host: $hostname\n"; $paddr = sockaddr_in($port, $iaddr) or die "port: $port - iaddr: $iadd +r\n"; socket(SOCKETH, PF_INET, SOCK_STREAM, $proto) or die "$!\n"; setsockopt(SOCKETH, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die "se +tsockopt: $!"; bind(SOCKETH, sockaddr_in($port, INADDR_ANY)) or die "bind: $!"; listen(SOCKETH, SOMAXCONN) or die "listen: $!"; print "Mercedes Server Open on port $port\n\n"; for ( ; $paddr = accept(Client,SOCKETH); close Client) { my($port,$iaddr) = sockaddr_in($paddr); $name = gethostbyaddr($iaddr,AF_INET); &spawn; } sub spawn { my $coderef = shift; my $pid; if (!defined($pid = fork)) { print "Cannot fork: $!"; return; } elsif ($pid) { return; } open(STDIN, "<&Client") or die "can't dup client to stdin"; open(STDOUT, ">&Client") or die "can't dup client to stdout"; ################################################################ ##### Per Connection Code ######### print "The Mercedes Project - 0.0.1 Pre-Alpha\n"; print "Copyright 2004 - Dan Casey\n\n"; while (1) { my ($clientreq); print ">"; $clientreq = <STDIN>; chomp $clientreq; if (valid_req($clientreq) == 0) { print "OK\n"; }else{ print "Will not execute $clientreq\n"; } } ################################################################ } sub valid_req() { my (@valid_commands,@command); @valid_commands = ("login","bye"); @command = (@_); print "validating request for $command[0]\n"; for (my $i=0;$i<@valid_commands;$i++) { if ($command[0] eq $valid_commands[$i]) { print "$command[0] is a valid command\n"; }else{ print "$command[0] is NOT $valid_commands[$i]\ +n"; } } }
#############################################
The output::
############
telnet 192.168.3.222 2424 Trying 192.168.3.222... Connected to 192.168.3.222. Escape character is '^]'. The Mercedes Project - 0.0.1 Pre-Alpha Copyright 2004 - Dan Casey >sdf validating request for sdf is NOT login is NOT bye OK

theorbtwo: Added readmore tags.

Replies are listed 'Best First'.
Re: Scoping Issue
by ambrus (Abbot) on May 16, 2004 at 19:07 UTC

    sub valid_req() {

    Remove the (), please!

•Re: Scoping Issue
by merlyn (Sage) on May 16, 2004 at 19:15 UTC
Re: Scoping Issue
by BrowserUk (Patriarch) on May 16, 2004 at 19:15 UTC

    The problem is the empty set of parens in your sub declaration.

    sub valid_req() { # ^^

    In perl, that is called an empty prototype, and it basically says "This sub never takes any arguments". Which means that

    @command = (@_);

    will always result in @command being empty, regardless of what you try to pass in when calling the sub.

    If you had strict & warnings* enabled, then you would have been informed of your error with the message

    Too many arguments for main::valid_req at ...

    The short term answer is to remove the parens completely, and never use a prototype in perl unless you know that you need to.

    The better, long term, answer is to make the transition to using strict and warnings* in your code. It only takes a little while to get used to the few easy steps required to satisfy them.

    It just makes life easier.

    *References to the warnings pragma added after ambrus's correction below.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail

      I think it's warnings you're speaking about, not strict. Agreed, otherwise.

        Probably. I always use both, so I'm rarely aware of exactly which messages are as a result of which pragma.

        I'll update:)


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail

      Actually, that's not the problem at all. If you look at the OP, the first line of output after the "sdf" line shows that @command is in fact being set correctly. I was surprised too, but removing the parentheses and adding use warnings doesn't actually fix the problem.

      The real problem, as best I can tell, has to do with connecting to this server using telnet(1) as your client. Somehow telnet is sending some special escapes which your program is choking on. Try adding the following line in "spawn" and you'll see what I mean: print "***$clientreq***\n";

      Also, within your while loop you need to add this line, or else it will start spinning forever as soon as your first client disconnects:

      last if !defined $clientreq;

      Update: By the way, the --debug option in your code won't work the way you think it will. use warnings is lexically scoped, so in fact it will have no effect at all the way you've written it. To see what I mean, try this:

      if (1) { use warnings; } print undef;

      Note that you don't get an "uninitialized value" warning like you might expect to. One way you can work around this is with:

      BEGIN { if ($ARGV[0] eq '--debug') { require warnings; warnings->import(); } }
        There's no somehow about it, telnet is defined as having a bunch of internal commands which anyone using it should consider. It uses the 255 character to indicate that one or more following characters will be telnet options. (An actual 255 char is sent doubled.) See telnet protocol.

        (I've actually written a module to allow telnet options to be ignored/dealt with on any socket, but not gotten around to documenting/finishing it .. )

        C.