tags:

views:

67

answers:

2

I have written a Perl script to read the configuration file and create CGI scripts. This works fine and I get the output of CGI script on terminal and I can execute that CGI scripts on web pages. Below is my sample script.

#!/usr/bin/perl -w

use strict;
use Text::Template;

my $conf = "test.cfg";

open CFG, $conf or die "Could not open config file";
my @rawConfig = <CFG>;
my $config = eval "{".join("",@rawConfig)."}";

my $template = Text::Template->new(TYPE => 'FILE',  SOURCE => 'test.cgi.tmpl');
my $result = $template->fill_in(HASH => $config);
print $result;

By using this I have to save each of the CGI and execute separately. I need help to modify this code so that I can directly execute this script on web and display the output on webpage.

+6  A: 

This is a very, very scary thing to do and I would generally advise against doing anything that creates new programs and lets the world run them without a human in there somewhere.

I suspect, however, that you might be doing this because the CGI scripts you are creating merely need different configuration data, and you've stored that right in the script itself. It's just a guess, but it's the usual motivator for this sort of thing. The answer is to not store configuration data in the script. I have an entire chapter in Mastering Perl about not storing configuration in code.

I'd work really hard to avoid the situation that you are describing.

(Does SO have a spoiler tag?)

If you really needed to do this for a good reason (and that's almost never the case), you'd create the file from the original process then issue an internal redirect to the new CGI script. How you do that is your homework assignment since I'm not going to put the bullets in the gun for you.

brian d foy
+1  A: 

Multiple template based scripts is (almost) never the right answer.

Use data structures from a config file and control structures to get the behaviors you need.

Instead of using a template to create code like:

sub foo {
    my $thing = shift;

    return blarg( $thing ) * feemb( $thing );
}

sub bar {
    my $thing = shift;

    return crag( $thing ) * forg( $thing );
}

sub baz {
    my $thing = shift;

    return chomb( $thing ) * veezle( $thing );
}

Do this:

# Get this from a config file.  YAML perhaps
my $cfg = {
    foo => [ \&blarg, \&feemb  ],
    bar => [ \&crag,  \&forg   ],
    baz => [ \&chomb, \&veezle ],
};

sub calculate_product {
    my $cfg   = shift;
    my $type  = shift;
    my $thing = shift;

    my @subs_to_call = @{ $cfg->{$type} || [] };

    my $result = {shift @subs_to_call}->($thing};

    $result *= $_->($thing) for @subs_to_call;

    return $result;
}
# Call like so:
my $foo_prod = calculate_product($cfg, 'foo', 15);

You can bind config info to a subroutine (that is 'curry your functions') by generating closures with config info:

# Get this from a config file.  YAML perhaps
my $cfg = {
    foo => [ \&blarg, \&feemb  ],
    bar => [ \&crag,  \&forg   ],
    baz => [ \&chomb, \&veezle ],
};

my %calculate_product;
for my $product ( keys %$cfg ) {

    my @stored_subs_to_call = @{$cfg->{$product} || [] };

    $calculate_product{$prod} = sub {
        my $thing = shift;

        my @subs_to_call = @stored_subs_to_call;

        my $result = {shift @subs_to_call}->($thing};

        $result *= $_->($thing) for @subs_to_call;

        return $result;
    }
}

# Call generated code like so:
my $foo_prod = $calculate_product{foo}->(15);
daotoad