<COMMENT>(--------------------------------------------------------------------)

<CHAPTER>(Perl\chapter_scripting_perl)

<P> WASD supports Perl scripting in the CGI, CGIplus and RTE environments. 
Generally no source changes are required to use standard CGI Perl scripts!
Information in this section pertains specifically to VMS Perl 5.6 and
following.  Earlier versions may have some limitations. VMS Perl 5.6 is a
relatively complete Perl implementation and standard distributions contain
some VMS-specific functionality.  In particular the VMS::DCLsym and VMS::Stdio
can make life simpler for the VMS perl developer.

<P> Users of VMS Perl are directed to the <QUOTE>(VMS Perl FAQ (Unofficial))

<COMMENT>(....................................................................)

<COMMENT>(HTML=
<A HREF="http://w4.lns.cornell.edu/~pvhp/perl/VMS.html">http://w4.lns.cornell.edu/~pvhp/perl/VMS.html</A>,
)

<COMMENT>(HTML/OFF)
http://w4.lns.cornell.edu/~pvhp/perl/VMS.html,
<COMMENT>(HTML/ON)

<COMMENT>(....................................................................)

an extensive and detailed resource, and to <QUOTE>(Perl on VMS) at

<COMMENT>(....................................................................)

<COMMENT>(HTML=
<A HREF="http://www.sidhe.org/vmsperl/">http://www.sidhe.org/vmsperl/</A>,
)

<COMMENT>(HTML/OFF)
http://www.sidhe.org/vmsperl/,
<COMMENT>(HTML/ON)

<COMMENT>(....................................................................)

providing access to the latest release of Perl for VMS.

<NOTE>(Please Note)
The author is very much the Perl novice and this chapter  probably reflects
that.  Additional material and improved code always gratefully received.
<ENDNOTE>

<COMMENT>(--------------------------------------------------------------------)

<HEAD1>(Activating Perl\head_cgi_perl_activating)

<P> There are a number of ways to activate a Perl script under VMS.  Any of
these may be used with the WASD server.  If the script file is accessable via
the <EMPHASIS>(exec) or <EMPHASIS>(script) rules of the HTTPD$MAP configuration
file it can be activated by the server.  The simplest example is to place the
scripts somewhere in the CGI-BIN:[000000] path and execute via /cgi-bin/,
although in common with other scripts it may be located anywhere a rule
provides a path to access it (see <REFERENCE>(head_script_mapping)).

<HEAD>(Directly\head_cgi_perl_activating_source)

<P> When Perl is available from the command-line, either as a DCLTABLES defined
verb, a DCL$PATH available verb, or as a <EMPHASIS>(foreign) verb.  The script
(the file containg the Perl source) is provided to the Perl interpreter as a
parameter to the Perl verb.

<CODE_EXAMPLE>
  $ PERL <EMPHASIS>(perl-script-file-name)
<ENDCODE_EXAMPLE>

<HEAD>(DCL Procedure Wrapped\head_cgi_perl_activating_wrap)

<P> If DCL pre-processing, or some other specific environment needs to be set
up, the activation of the Perl script can be placed inside a DCL
<EMPHASIS>(wrapper) procedure.  This is often used to allow the transparent
activation of Perl scripts via the DCL$PATH mechanism.

<CODE_EXAMPLE>
  $ PERL = "$PERL_ROOT:[000000]PERL.EXE"
  $ DEFINE /USER PERL_ENV_TABLES CLISYM_GLOBAL,LNM$PROCESS
  $ PERL <EMPHASIS>(perl-script-file-name)
<ENDCODE_EXAMPLE>

<HEAD>(DCL Procedure Embedded\head_cgi_perl_activating_embed)

<P> The Perl source is embedded as in-line data within a DCL procedure.

<CODE_EXAMPLE>
  $ DEFINE /USER PERL_ENV_TABLES CLISYM_GLOBAL,LNM$PROCESS
  $ PERL
  $ DECK /DOLLARS="__END__"
  # start of Perl script
  print "Hello \"$ENV{'WWW_REMOTE_HOST'}\"\n";
  __END__
<ENDCODE_EXAMPLE>

<HEAD1>(CGI Environment\head_cgi_perl_cgi_env)

<P> Due to changes in environment handling sometime between versions 5.0 and
5.6 it was impossible to access DCL symbols via the %ENV hash, making CGI-based
scripts impossible to use under VMS Web servers without modification.  Version
5.6 addresses this issue by providing a versatile mechanism for controlling
where the environment variables are manipulated.  The logical name
PERL_ENV_TABLES specifies this location, or if defined as a search list, the
locations.

<LINE>
<TABLE>
<TABLE_SETUP>(2\20\)
<TABLE_HEADS>(Name\Location)
<TABLE_ROW>(CRTL_ENV\C run-time environment array (i.e. getenv()))
<TABLE_ROW>(CLISYM_LOCAL\get DCL symbols, set local)
<TABLE_ROW>(CLISYM_GLOBAL\get DCL symbols, set global)
<TABLE_ROW>(<EMPHASIS>(logical name table)\any logical name table, including
LNM$FILE_DEV)
<ENDTABLE>

<P> For WASD Perl scripting it is recommended that this be defined as
CLISYM_GLOBAL,LNM$PROCESS.  The CLISYM_GLOBAL allows access to the CGI variable
environment, and LNM$PROCESS to significant logical name definitions for the
subprocess (e.g. HTTP$INPUT and callout sequences).  This can be done on a
system-wide basis (i.e. for all Perl scripting) using

<CODE_EXAMPLE>
  $ DEFINE /SYSTEM PERL_ENV_TABLES CLISYM_GLOBAL,LNM$PROCESS
<ENDCODE_EXAMPLE>

<CP> during system startup, or by defining a user-mode logical in a DCL
procedure <EMPHASIS>(wrapper) immediately before activating the Perl
interpreter (as show in the examples in this section).

<COMMENT>(--------------------------------------------------------------------)

<HEAD1>(POSTed Requests\head_cgi_perl_posted)

<P> Requests using the POST method contain all the content in the body of the
request.  In particular, requests generated via HTML <LITERAL>(<FORM>)
contructs do not deliver the form data via the request query string, it is
provided in a URL-form-encoded body.  This requires some explicit processing
to recover the form elements.  A number of Perl CGI modules exist to ease this
chore, including the most popular CGI.pm.  All of these should work in the VMS
environment, and of course then with WASD.

<P> For POSTed requests it is necessary for the script to have access to the
request body.  In Unix environments this is available via the
<LITERAL>(<stdin>) stream, and under Perl via STDIN, <LITERAL>(<>), etc.  This
equates to SYS$INPUT under VMS.

<P> With WASD, when activating the .PL script file directly via a
[DclScriptRunTime] entry (i.e. without a DCL procedure wrapper) STDIN is
directly available without further issues.

<P> If the script has a DCL wrapper procedure the DCL CLI has control of the
SYS$INPUT stream and it becomes  necessary to temporarily redirect this for the
duration of the script.  WASD provides the HTTP$INPUT process-level logical
name to identify the script body stream (along with WWW_IN and APACHE$INPUT
names for easing script portability).  The redirection is simply done, as shown
in the following example.

<CODE_EXAMPLE>
  $ DEFINE /USER PERL_ENV_TABLES CLISYM_GLOBAL,LNM$PROCESS
  $ DEFINE /USER SYS$INPUT HTTP$INPUT
  $ PERL <EMPHASIS>(perl-script-file-name)
<ENDCODE_EXAMPLE>

<P> If the script is embedded in a DCL procedure the DCL CLI is using SYS$INPUT
to provide the script source to the Perl interpreter and so is completely
unavailable for use.  The request body is still available to the script however
but must be explicitly read from HTTP$INPUT.  This example provides the basics.

<CODE_EXAMPLE><LITERAL>
  $ DEFINE /USER PERL_ENV_TABLES CLISYM_GLOBAL,LNM$PROCESS
  $ PERL
  $ DECK /DOLLARS="__END__"
  # start of Perl script
  print "HTTP method is \"$ENV{'WWW_REQUEST_METHOD'}\"\n";
  # read POSTed body stream
  open (HTTPIN, $ENV{"HTTP\$INPUT"})
     or die "Could not open $ENV{'HTTP\$INPUT'}\n";
  while (<HTTPIN>)
  {
    chop;  # remove trailing newline
    print "<HTTPIN> |$_|\n";
  }
  __END__
<ENDLITERAL><ENDCODE_EXAMPLE>

<COMMENT>(--------------------------------------------------------------------)

<HEAD1>(Reducing Latency\head_cgi_perl_latency)

<P> Perl is an interpreter, meaning scripts are provided and activated as
source form, the interpreter processing the program <QUOTE>(on-the-fly). Perl
actually translates the entire script into an intermediate form before
beginning execution.  This has the advantage of discovering and reporting
syntax errors before beginning any actual processing, and also improves the
final run-time performance.

<P> While having Perl an interpreter eases development and portability it does
incur a performance penalty, particularly in activation latency, due to both
interpreter image activation, and script  and associated Perl module
preprocessing.  With standard CGI, where each request processed is handled as
an autonomous activation, this becomes quite noticable and can have significant
system impact.

<P> WASD provides two solutions for this and other persistent scripting issues.

<HEAD2>(CGIplus\head_cgi_perl_latency_cgiplus)

<P> CGIplus substantially eliminates the overhead associated with CGI
processing by allowing the subprocess and any associated image/application to
continue executing between uses.  For detailed information see
<REFERENCE>(chapter_scripting_cgiplus).  The good news is, CGIplus is
relatively simple to support, even using Perl.  The great news is,
<EMPHASIS>(CGIplus can reduce latency and improve performance by some
twenty-fold!!\BOLD)

<P> With CGIplus the Perl script remains active for the life of the subprocess. 
That is it persists!  Read the general philosphy and implementation details in
the above reference.  Note that it is still substantially CGI!  The notable
differences are two.  CGI variables are obtained by reading a stream, not using
the %ENV hash.  The end-of-script is indicated by writing a special byte
sequence (detected and used by the server).  Of course the request body is
still available via the usual stream.

<P> Using the basic principles described in the CGIplus Chapter a Perl CGIplus
script would be relatively simple to build from scratch.  To assist in
deploying CGIplus Perl scripting a CGIplus.pm Perl module has been provided. 
This allows a function reference to be passed to a module function and
then using the module's own <EMPHASIS>(environment) hash CGI variables may be
simply accessed.  The module also provides other functionality to ease the
sending of binary response streams (which can be a problem with the VMS perl
interpreter).

<P> Examples for this may be found in the

<COMMENT>(....................................................................)

<COMMENT>(HTML=
<A HREF="/ht_root/src/perl/">HT_ROOT:[SRC.PERL]</A>
)

<COMMENT>(HTML/OFF)
HT_ROOT:[SRC.PERL]
<COMMENT>(HTML/ON)

<COMMENT>(....................................................................)

directory.

<HEAD2>(Run-Time Environment\head_cgi_perl_latency_rte)

<P> A Run-Time Environment (RTE) is almost identical to CGIplus.  It allows an
environment to persist between requests, substantially improving response
latency and reducing system impact.  For information see
<REFERENCE>(chapter_scripting_rte). There is a significant difference between
RTE and CGIplus scripts.  With CGIplus the script itself persists between uses,
retaining all of it's state.  With an RTE the script does not persist or retain
state, only the RTE itself.

<P> WASD provides an RTE Perl interpreter.  This contains an embedded Perl
engine and an associated Perl module that allows multiple scripts to be
activated, preprocessed once and remain loaded <EMPHASIS>(read-to-run).  This
eliminates the overhead associated with activating the interpreter and Perl
script with each request.  This mechanism parallels the Apache
<EMPHASIS>(perl_mod) module and works on substantially unmodified CGI scripts. 
<EMPHASIS>(The test-bench indicates an improvement of some twenty-five
fold!\BOLD)

<P> Examples for RTE Perl may be found in the

<COMMENT>(....................................................................)

<COMMENT>(HTML=
<A HREF="/ht_root/src/perl/">HT_ROOT:[SRC.PERL]</A>
)

<COMMENT>(HTML/OFF)
HT_ROOT:[SRC.PERL]
<COMMENT>(HTML/ON)

<COMMENT>(....................................................................)

directory.

<NOTE>
The Perl RTE is new to WASD 7.1 and to this extent has not received any wide
and general deployment.  There may still be issues to be resolved, particularly
with script isolation within the interpreter.  Please experiment with this
environment - it's potential for improving performance is substantial - and
provide feedback to the author on any successes or problems in use.
<ENDNOTE>

<COMMENT>(--------------------------------------------------------------------)

<HEAD1>(Requirements\head_cgi_perl_requirements)

<P> These are the basic configuration requirements for using Perl.

<LIST>(UNNUMBERED)

<LE> HTTPD$CONFIG configuration file.

<CODE_EXAMPLE>
  [DclScriptRunTime]
  .PL PERL
  .CGI PERL
<ENDCODE_EXAMPLE>

<COMMENT>(HTML=<P>)

<LE> The following content types are configured, also in HTTPD$CONFIG. 

<CODE_EXAMPLE>
  [AddType]
  .PL  text/plain  -  Perl source
  .POD  text/plain  -  Perl documentation
  .CGI  text/plain  -  Perl source
<ENDCODE_EXAMPLE>

<LE> Some mapping is required to use the Perl RTE interpreter.  Something like
the following will provide a Perl RTE path for development purposes. 

<CODE_EXAMPLE>
  exec /plrte/* (cgi-bin:[000000]perlrte.exe)/ht_root/src/perl/*
<ENDCODE_EXAMPLE>

<P> For further information see <REFERENCE>(head_rte_config).

<ENDLIST>

<COMMENT>(--------------------------------------------------------------------)
