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

I'm new to Perl and I have a question about launching an application from a webpage. I'm using Lighttpd on Windows. Basically here is my code.
#!/Perl/bin -w use strict; use Thread; use CGI; use CGI::Carp qw(fatalsToBrowser); print "Before CGI creation"; my $q = new CGI; print $q->header( "text/plain" ); print "Before second system call"; system 'cmd.exe /c notepad.exe' || die "Cannot execute notepad.exe";
Basically it seems to just not launch the system command. I can run the script externally and it works great but when its used in a browser. It doesn't do anything and seems to skip over the line completely. Thanks in advance.

Replies are listed 'Best First'.
Re: Executing an application in Perl/CGI
by blazar (Canon) on May 22, 2007 at 19:18 UTC
    system 'cmd.exe /c notepad.exe' || die "Cannot execute notepad.exe";

    Do you really want to launch notepad on the machine running the webserver? Why so?!?

    Update: anyway, you got system's return value and ||'s precedence wrong, please read the docs.

      Its just a proof of concept.
Re: Executing an application in Perl/CGI
by naikonta (Curate) on May 22, 2007 at 19:19 UTC
    Use and/&& to test againsts system since it returns 0 for successful and true value on failure.
    system('some_command') && die 'cannot execute some_command'; # or system 'some_command' and die 'cannot execute some_command';

    Update: Fixed precedence and added another example with and. Thanks, kyle and blazar :-)


    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

      system 'some_command' && die 'cannot execute some_command';

      Really, both this and the OP's attempt get it wrong due to precedency issues. In fact I find myself repeating once again that as a rule of thumb, high precedence logical operators are for values and low precedence ones are for flow control. In particular, the OP's code appears to work because the die is never actually reached, while yours is the same as

      system(die('cannot execute some_command'));

      So the program dies before calling system.

        Even with the fix the program still dies on the system call. It works perfectly fine but run in a web browser, it dies.

      system 'some_command' && die 'cannot execute some_command';

      This will always die because it's interpreted as:

      system( 'some_command' && die 'cannot execute some_command' );

      Since the string 'some_command' is a true value, the die always executes. To fix this, use and, which has a lower precedence:

      system 'some_command' and die 'cannot execute some_command';
Re: Executing an application in Perl/CGI
by jettero (Monsignor) on May 22, 2007 at 19:20 UTC
    It feels like notepad and/or cmd isn't in your path. If it were in X, I'd guess it was a missing $ENV{DISPLAY}. Either way, you want system() == 0 or die, not ||. There are interesting security problems with almost everything in that CGI, but one thing that might help a smallish amount (maybe none) is system("cmd.exe", "/c", "notepad.exe") — where it might help is if there were ever a filename argument.

    The obvious DoS is to make your system open notepad.exe a hilarious number of times, simultaneously using up your webserver's MaxChildren. exec "notepad" unless fork might help with the children, but not with the hilarious number of notepads.

    -Paul

Re: Executing an application in Perl/CGI
by Crackers2 (Parson) on May 22, 2007 at 23:20 UTC

    Just a thought, but perhaps the user that the web server is running as does not have enough permissions to affect the desktop of the user that's logged into the server?

Re: Executing an application in Perl/CGI
by kyle (Abbot) on May 22, 2007 at 19:28 UTC

    Your call to system needs to have parentheses for the die to work (aside from the fact that system returns "false" on success).

    system 'cmd.exe /c notepad.exe' || die 'no notepad'; # is the same as system( 'cmd.exe /c notepad.exe' || die 'no notepad' ); # but you want system( 'cmd.exe /c notepad.exe' ) && die 'no notepad'; # or you could do system 'cmd.exe /c notepad.exe' and die 'no notepad';

    You could also get a little more explicit about what you expect from system:

    0 == system 'cmd.exe /c notepad.exe' or die 'no notepad';
      This works for the error, it doesn't launch. However why does this not work on a server end put works alright locally executed. Is this an issue with the path? Thanks for the suggestions.
        This works for the error, it doesn't launch. However why does this not work on a server end put works alright locally executed. Is this an issue with the path?

        It may be. However, to quote from perldoc -f system:

        You can check all the failure possibilities by inspecting $? like this: if ($? == -1) { print "failed to execute: $!\n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; } else { printf "child exited with value %d\n", $? >> 8; }