7

I am writing a Perl script that can run both from command line and from a web page. The script receives a couple of parameters and it reads those parameters through $ARGV if it started from command line and from CGI if it started from a web page. How can I do that?

my $username;
my $cgi = new CGI;
#IF CGI
$username = $cgi->param('username');
#IF COMMAND LINE
$username = $ARGV[0];
raz3r
  • 3,071
  • 8
  • 44
  • 66
  • 1
    The standard-compliant variable to check against is called `GATEWAY_INTERFACE`: http://stackoverflow.com/questions/1914966/how-can-i-determine-if-a-script-was-called-from-the-command-line-or-as-a-cgi-scr http://stackoverflow.com/questions/3086655/in-perl-how-to-distiniguish-between-cli-cgi-mode http://stackoverflow.com/questions/4853948/how-can-i-tell-if-a-perl-script-is-executing-in-cgi-context – daxim Nov 21 '11 at 18:15

4 Answers4

9

With CGI.pm you can pass params on the command line with no need to change your code. Quoting the docs:

If you are running the script from the command line or in the perl debugger, you can pass the script a list of keywords or parameter=value pairs on the command line or from standard input (you don't have to worry about tricking your script into reading from environment variables)

Wrt your example, it's a matter of doing:

perl script.cgi username=John
larsen
  • 1,431
  • 2
  • 14
  • 26
6

Mojolicious framework uses battle-proven environment autodetection that works on different servers (not Apache only).

So you can use following code:

if (defined $ENV{PATH_INFO} || defined $ENV{GATEWAY_INTERFACE}) {
    # Go with CGI.pm
} else {
    # Go with Getopt::Long or whatever
}
yko
  • 2,710
  • 13
  • 15
4

The cleanest way might be to put the meat of your code in a module, and have a script for each interface (CGI and command line).

You could test for the presence of CGI environment variables ($ENV{SERVER_PROTOCOL}) to see if CGI is being used, but that would fail if the script is used as a command-line script from another CGI script.

If all you want to pass via @ARGV are form inputs, keep in mind that CGI (the module) will check the @ARGV for inputs if the script is not called as a CGI script. See the section entitled "DEBUGGING" in the documentation.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I guess you're right, in fact I am going to create a core module and two separate interfaces, thank you to all of you guys :) – raz3r Nov 22 '11 at 07:41
3

When invoked through CGI your script will additional environment variables set. You can use them in your if condition.

For example, you could use HTTP_USER_AGENT

if ( $ENV{HTTP_USER_AGENT} )
{
   #cgi stuff
}
else
{
   #command line
}

But if your real need is to test a CGI script stand alone, Try ActiveState Komodo, The debugger lets to Simulate CGI Environment

parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85