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

Hi,

I have never really used Perl, and before I spend lots of time trying to learn it, I'd like to know if it will be able to do what I need.

I have a .c file that I have compiled into an executable. The user would like to be able to run this from the command line (not a problem) or from a web-based interface (uh-oh!). So, I guess I want to be able to:

1. Pass an executable a couple of parameters gathered from an HTML form (using a POST method?)
2. Wait for the .exe to generate the new HTML code
3. Load the newly generated html page back into the browser

Does this sound like a good candidate for a Perl script? As a novice Perl programmer, would I be getting in over my head? I have about 5 days to figure out and implement this. If Perl isn't the right answer, can anyone suggest another scripting language that could accomplish this?

I'm a ColdFusion programmer by trade, but have to write this script to run on a W2K server, running Apache and CygWin. Woe is me... ;)

Thanks,

-DJ

Replies are listed 'Best First'.
Re: Can Perl do this...?
by jonadab (Parson) on Oct 14, 2003 at 13:53 UTC

    What you're talking about is known in web development circles as CGI programming, and it's generally much easier to do in Perl than in C or most other languages. There are assorted ready-made modules available to make it even easier still. For example, you might want to look at CGI or CGI::Lite. As far as Apache, that's good news: Apache is generally very easy to work with. The first time I ever played around with CGI programming, I downloaded and installed Apache, configured it, wrote my Perl script, and had it working all in one afternoon. It wasn't the most elegant script ever (I was pretty new to Perl at the time), but it worked.

    Here's what you need to know, then...

    • Your input will come either in the QUERY_STRING environment variable (for GET requests) or on standard input (for POST), but some characters will be encoded (like %20 for space), so it is generally easiest to retrieve the input using a module, like CGI::Lite or CGI. Some of us roll our own routines for this, but that is a more involved exercise; given your five-day deadline, you probably want to use a module.
    • Your script will be expected to print (on standard output) the content to be sent to the browser; this may include HTTP headers and MUST at least include the Content-Type header. After the headers you print a blank line, followed by your content (e.g., the HTML that the browser will show).
    • If security is a concern, you should familiarize yourself with Taint checking.

    Here is a very minimal CGI script that you can use to test your setup to see that it's working:

    #!C:\wherever\Perl.exe print "Content-type: text/html <html><head><title>test</title></head> <body><h1>It works.</h1></body></html> ";

    update: Other monks' posts have made me look again at your request, and I think maybe you wanted to get the output from an external executable (written in C) and send _that_ to the user. This also is quite possible (maybe even easy, depending on how the executable takes its input). In the trivial case where the external program doesn't need any input but only generates output, this will work:

    #!C:\wherever\Perl.exe open FOO, "C:\wherever\program.exe |"; # The | is a pipe; we're running program.exe and # reading its output from the FOO filehandle: print "Content-type: text/plain\n\n"; while (<FOO>) { print }

    If the C script takes command-line arguments, that the user needs to specify, then you'll need to have an HTML form that lets the user specify this input, and your Perl script will take that input and massage it into command-line arguments for the external program. You can insert those arguments directly into the commandline, as in,

    open FOO, "C:\wherever\program.exe @args |";

    If the external program expects input in standard input, then post a reply saying so and we'll go into how to do that too.

    It is also a good idea to make sure the program in question can't do anything destructive that you don't want, before turning loose a web interface straight to it. If possible, you should try to arrange for it to run as an unprivileged user, but I don't know enough about Windows 2000 to tell you how to do that.

    If what the C program does is very simple, you may want to just rewrite it in Perl.


    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
Re: Can Perl do this...?
by Ovid (Cardinal) on Oct 14, 2003 at 13:59 UTC

    Yes, Perl can do this. The question is whether or not you can do this. You could try gathering the data from the form and passing it to the CGI script with backticks, the qx// operator, or a number of other possibilities. An alternative, if you know C, is to use Inline to hook Perl directly into the C code. Another possibility is to use cgic (or something similar), a CGI library written in C that you could simply link to the program and have everything handled in C.

    If you have 5 days to figure this out, it shouldn't be too hard. Depending upon what you really need, this is really only a couple of hours worth of work, at most (for the first option or two). Heck, if the parameters are simple enough, it's a 10 minute job so you should have no problems getting it done. Good luck!

    Cheers,
    Ovid

    New address of my CGI Course.

      Oh, does he want to still use the compiled C program for generating the HTML? (jonadab rereads the original post.) Huh, maybe he does. I was assuming he meant he wanted to replace the C program with Perl, but upon closer inspection I'm not at all sure that's the case.


      $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
Re: Can Perl do this...?
by hardburn (Abbot) on Oct 14, 2003 at 13:54 UTC

    Perl will handle that job fine. Just make sure to carefully check the input you get from the client, as it's really easy to allow bad characters through. Be sure your Perl shabang (#!) line has the -T (taint) switch, which will force you to check your input before doing anything particularly dangerous with it (note that this won't stop you from doing dangerous things if you really try, but it will stop some common mistakes).

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

Re: Can Perl do this...?
by theguvnor (Chaplain) on Oct 14, 2003 at 13:57 UTC

    Perl and the WWW? Perish the thought! ;-)

    Perl has a long history of use with the web, including what you described.

    You could definitely write a wrapper script in perl to do what you want - passing HTML form variables to the exe and scooping up the output and pushing to the browser, but then again you could do the whole thing with perl. It's flexible and powerful and a whole lot of pre-written code and examples await you.

    [Jon]

Re: Can Perl do this...?
by Corion (Patriarch) on Oct 14, 2003 at 14:02 UTC

    As you already have Apache, most of the hard work is already done for you. The module CGI.pm solves the rest of your worries, and all should work more or less together in the following, untested fashion:

    #!perl -wT use strict; use CGI qw(fatalsToBrowser); my $generator = 'c:/path/to/html/generator.exe'; my $filename = "c:/path/to/generated/html/page.html"; my $q = CGI->new(); my @generator_arguments; # The parameter "start_page" must contain a number: if ($q->param('start_page') =~ /^(\d+)$/) { push @generator_arguments, "--page_start", $1; }; # The parameter "text_string" must contain a string # with only characters a-zA-Z and blank: if ($q->param('text_string') =~ /^([a-zA-Z ])$/) { push @generator_arguments, "--text_string", $1; }; system($generator,@generator_arguments) == 0 or die "Couldn't start $generator: $! /$?"; # now read the generated HTML: open HTML,"<",$filename or die "Couldn't open $filename : $!"; my $html = do { local $/; <HTML> }; close HTML; print CGI::header(); print $html;
    perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
Re: Can Perl do this...?
by Abigail-II (Bishop) on Oct 14, 2003 at 14:17 UTC
    This should not be a problem in either Perl, or almost any other language. I've a hard time coming up with a language where this problem would not be a rather trivial task.

    Abigail

      Brainfuck?
Re: Can Perl do this...?
by pg (Canon) on Oct 14, 2003 at 13:48 UTC

    Look into HTTP::Daemon, it saves you lots of time, as it does the basic tcp connection, handles http requests and responses, and even forms the basic http header for you.

    One sentence, you can easily use it to make a simple web server.

    See , this is perl, one module, fits most of your needs (in this case, almost all of your needs).

    (Strike HTTP::Daemon part per jonadab's comment)

    Oh, also use CGI module to help you generate the html you send back, if you don't want to worry about html formatting things.

      Look into HTTP::Daemon

      This would be great advice if he were creating a standalone web-serving app, but he specifically mentions that he's using Apache, so he doesn't need to handle any HTTP stuff at all, just take the input Apache gives him and print content.


      $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/