Porting Perl CGI Script From Linux Apache To Windows IIS

I am a linux guy. I mean, my laptop is windows based and all, but all the development is done on Linux. I prefer Java and Swing for desktop applications and Perl or Java for Web applications. I have a perl cgi script that I had to port it to IIS because a potential customer wanted it on Windows 2003 Server with IIS.

I have a laptop with Windows Vista Home Premium and so I wanted to try and figure out how to make the cgi script to work on IIS. After a lot of searching and researching, I figured out enabling IIS, installing ActivePerl, configuring to run the perl scripts and all. This article is not about how that can be done, but about what issue I ran into when porting the script.

First I thought I had to change the “#!/usr/bin/perl” to the appropriate perl interpreter path on Windows, but the way it works in IIS is that a specific url pattern can be mapped to a handler and program of that handler is configured. So, “*.pl” can be mapped to a specific program and windows will execute that program passing the script as input. This makes life easier, no need to maintain two separate versions of the program one for each platform.

However, the key issue I ran into is the error in loading the shipped modules. In Apache, a perl script is run with the current working directory set to the directory where the script is located. So, all the other modules of the program are resolved with respect to the current working directory and as a result there is no need for any special include path setting. But in IIS, this isn’t the case. The script is executed with the current working directory (BTW, pwd in linux and chdir in Windows) set to the virtual directory of the script. So, if the script is within a folder within the virtual directory, all the modules packaged with the script won’t be found.

So, I ended up doing the following to make it work with both Apache and IIS.

At the very beginning of the script, even before the modules are loaded, I have the following code.

BEGIN {
  $SCRIPT_PATH = $ENV{PATH_TRANSLATED}; # this env variable is available in IIS and not Apache
  if($SCRIPT_PATH) {
     $SCRIPT_PATH =~ s/[^\\\/]+$//;
     push @INC,$SCRIPT_PATH;
  }
  else {
     $SCRIPT_PATH = ".";
  } 
}

That’s it. This code will include the directory of the script into the include path so that the subsequent “use” and “require” statements are resolved appropriately.

One last note. If you have file opening logic in the script using a relative path, that should also be changed to resolve it w.r.t the $SCRIPT_PATH.

Advertisements

2 Comments

Filed under Apache, IIS, perl

2 responses to “Porting Perl CGI Script From Linux Apache To Windows IIS

  1. First I should note that the regexp contains a bug, a slash is missing. It should be:

    $SCRIPT_PATH =~ s/[^\\\/]+$//;

    The next comment concerns perl scripts in Apache in Linux. The working directory is the directory of the script only if running as a normal CGI script, not if running under mod_perl. Although “.” is listed in @INC, modules residing in the script’s directory are not found. Since my scripts may be used on another server in a different directory and will also be deployed in IIS, I finally added the following to the beginning of my script:

    our $SCRIPT_PATH;
    BEGIN {
    $SCRIPT_PATH = $ENV{SCRIPT_FILENAME};
    if($SCRIPT_PATH) {
    $SCRIPT_PATH =~ s/[\\\/][^\\\/]+$//;
    push @INC,$SCRIPT_PATH;
    }
    else {
    $SCRIPT_PATH = “.”;
    }
    }

    I have not tried the script on IIS so far but I hope that SCRIPT_FILENAME is defined.

    If you need to override system modules, use unshift instead of push.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s