3

Is there a good way to detect if the Perl script is called from terminal/DOS or called from a web server.

I currently have this code:

sub cli {
    # return 1 if called from browser, 0 if called from command line
    if  (defined $ENV{GATEWAY_INTERFACE} ||  exists $ENV{HTTP_HOST}){
        return 0;
    }
    return 1;
}

but read that these ENV variables are not set by all servers.

The reason for this if the script run from terminal I will print text/plain formatted messages, if run from browser I will print HTML formatted messages.

daliaessam
  • 1,636
  • 2
  • 21
  • 43
  • 1
    As demonstrated in [this question](http://stackoverflow.com/questions/25049985/cgi-commandline-args-disappearing), perhaps check for `$ENV{REQUEST_METHOD}` as that's how `CGI` determines the difference between a web request and a command line invocation. – Miller Aug 01 '14 at 01:32
  • Is your terminal on a web server? – vol7ron Aug 01 '14 at 03:32
  • 1
    possible duplicate of [How can I determine if a script was called from the command line or as a cgi script?](http://stackoverflow.com/questions/1914966/how-can-i-determine-if-a-script-was-called-from-the-command-line-or-as-a-cgi-scr) – vol7ron Aug 01 '14 at 03:33
  • @vol7ron I see the accepted answer there is checking `$ENV{GATEWAY_INTERFACE}`, so still no one method is confirmed by everyone, but it is a good you pointed to this answer it has many new ideas – daliaessam Aug 01 '14 at 03:53
  • Personally my technique would be to move the bulk of your script into a module which provides `to_text` and `to_html` functions/methods. Then have **two scripts** - one which calls `to_text`, and one which calls `to_html`. Access the HTML-outputting script via your web browser, and run the text-outputting script at the command line. Simples. – tobyink Aug 01 '14 at 10:54
  • According to spec (and the answer in the other post) it says the `GATEWAY_INTERFACE` must be set. You can't account for when a server doesn't conform to spec, unless it's something you are going out of your way to accommodate, or it is a matter of security. In either case, you should submit an update request to the designers of that server that doesn't conform to spec. – vol7ron Aug 03 '14 at 18:35
  • @vol7ron then it is almost the best approach is the one I used above besides I added @Miller comment checking `$ENV{REQUEST_METHOD}` also. – daliaessam Aug 03 '14 at 20:30
  • @daliaessam yeah, I think that seems like you're doing it right – vol7ron Aug 03 '14 at 20:36

2 Answers2

5

I usually do:

if (-t STDIN) {
    //This is running from a terminal
}

Edit after reading comments : I found this other question that details a different solution : How do I check if a Perl script is running in a terminal?.

OlivierLi
  • 2,798
  • 1
  • 23
  • 30
  • 3
    That will tell you if STDIN is connected to a terminal. But what about, say, `echo "foo" | perl myscript.pl`. STDIN is no longer attached to the terminal, but we're still running the script from the command line; not via the web server. – tobyink Aug 01 '14 at 10:51
3

The following is a quick example and may not be the most accurate, but serves to demonstrate that you could check the process's parent command.

my $parent_process  = `ps -o ppid= -p $$ | xargs ps -o command= -p`;
if ($parent_process =~ /httpd/) {
   say q{CGI};
} else {
   say q{Terminal};
}

Basically, we retrieve the search for the current process, and pipe that parent process into another look up so that we can get the parent's command that was run. From the terminal it should be the shell name (e.g., -bash), but if it was run by the server, it should be the server daemon httpd (depending on the web server).

It would be much easier to have the server set an environment variable and check for the existence of that variable. This all depends on where you're running the command and who you're running the command as.

This could further be condensed into something like:

my $is_server = `ps -o ppid= -p $$ | xargs ps -o command= -p | grep httpd -q && echo "1" || echo "0"`; chomp $is_server;
if ($is_server) { ... } else { ... }
vol7ron
  • 40,809
  • 21
  • 119
  • 172