NAME

ePerl - Embedded Perl 5 Language

VERSION

@V@

SYNOPSIS

eperl [-d name=value] [-D name=value] [-B begin_delimiter] [-E end_delimiter] [-m mode] [-o outputfile] [-k] [-x] [-c] [inputfile]

eperl [-r] [-l] [-v] [-V]

DESCRIPTION

Abstract

ePerl interprets an ASCII file bristled with Perl 5 program statements by evaluating the Perl 5 code while passing through the plain ASCII data. It can operate both as a standard Unix filter for general file generation tasks and as a powerful Webserver scripting language for dynamic HTML page programming.

Introduction

The eperl program is the Embedded Perl 5 Language interpreter. This really is a full-featured Perl 5 interpreter, but with a different calling environment and source file layout than the default Perl interpreter (usually the executable perl or perl5 on most systems). It is designed for general ASCII file generation with the philosophy of embedding the Perl 5 program code into the ASCII data instead of the usual way where you embed the ASCII data into a Perl 5 program (usually by quoting the data and using them via print statements). So, instead of writing a plain Perl script like

#!/path/to/perl
print "foo bar\n";
print "baz quux\n";
for ($i = 0; $i < 10; $i++) { print "foo #${i}\n"; }
print "foo bar\n";
print "baz quux\n";

you can write it now as an ePerl script:

#!/path/to/eperl
foo bar
baz quux
<: for ($i = 0; $i < 10; $i++) { print "foo #${i}\n"; } :>
foo bar
baz quux

Although the ePerl variant has a different source file layout, the semantic is the same, i.e. both scripts create exactly the same resulting data on STDOUT.

Intention

ePerl is simply a glue code which combines the programming power of the Perl 5 interpreter library with a tricky embedding technique. The embedding trick is this: it converts the source file into a valid Perl script which then gets entirely evaluated by only one internal instance of the Perl 5 interpreter. To achieve this, ePerl translates all plain code into (escaped) Perl 5 strings placed into print constructs while passing through all embedded native Perl 5 code. As you can see, ePerl itself does exactly the same internally, a silly programmer had to do when writing a plain Perl generation script.

Due to the nature of such bristled code, ePerl is really the better attempt when the generated ASCII data contains really more static as dynamic data. Or in other words: Use ePerl if you want to keep the most of the generated ASCII data in plain format while just programming some bristled stuff. Do not use it when generating pure dynamic data. There it brings no advantage to the ordinary program code of a plain Perl script. So, the static part should be at least 60% or the advantage becomes a disadvantage.

ePerl in its origin was actually designed for an extreme situation: as a webserver scripting-language for on-the-fly HTML page generation. Here you have the typical case that usually 90% of the data consists of pure static HTML tags and plain ASCII while just the remaining 10% are programming constructs which dynamically generate more markup code. This is the reason why ePerl beside its standard Unix filtering runtime-mode also supports the CGI/1.1 and NPH-CGI/1.1 interfaces.

Runtime Modes

ePerl can operate in three different runtime modes:

Stand-alone Unix filter mode

This is the default operation mode when used as a generation tool from the Unix shell or as a batch-processing tool from within other programs or scripts:

$ eperl [options] - < inputfile > outputfile
$ eperl [options] inputfile > outputfile
$ eperl [options] -o outputfile - < inputfile
$ eperl [options] -o outputfile inputfile

As you can see, ePerl can be used in any combination of STDIO and external files. Additionally there are two interesting variants of using this mode. First you can use ePerl in conjunction with the Unix Shebang magic technique to implicitly select it as the interpreter for your script similar to the way you are used to with the plain Perl interpreter:

#!/path/to/eperl [options]
foo
<: print "bar"; :>
quux

Second, you can use ePerl in conjunction with the Bourne-Shell Here Document technique from within you shell scripts:

#!/bin/sh
...
eperl [options] - <<EOS
foo
<: print "quux"; :>
quux
EOS
...
CGI/1.1 compliant interface mode

This is the runtime mode where ePerl uses the CGI/1.1 interface of a webserver when used as a Server-Side Scripting Language on the Web. ePerl enters this mode automatically when the CGI/1.1 environment variable PATH_TRANSLATED is set and the scripts filename does not begin with the NPH prefix ``nph-''. In this runtime mode it prefixes the resulting data with HTTP/1.0 (default) or HTTP/1.1 (if identified by the webserver) compliant response header lines.

ePerl also recognizes HTTP header lines at the beginning of the scripts generated data, i.e. for instance you can generate your own HTTP headers like

<? $url = "..";
   print "Location: $url\n";
   print "URI: $url\n\n"; !>
<html>
...

But notice that while you can output arbitrary headers, all webservers restrict the headers which are accepted via the CGI/1.1 interface. Usually you can provide only a few specific HTTP headers like Location or Status. If you need more control you have to use the NPH-CGI/1.1 interface mode.

Additionally ePerl provides a useful feature in this mode: It can switch its UID/GID to the owner of the script if it runs as a Unix SetUID program (see below under Security and the option ``u+s'' of chmod(1)).

There are two commonly known ways of using this CGI/1.1 interface mode on the Web. First, you can use it to explicitly transform plain HTML files into CGI/1.1 scripts via the Shebang technique (see above). For an Apache webserver just put the following line as the first line of the file:

#!/path/to/eperl -mc

Then rename the script from file.html to file.cgi and set its execution bit via

$ mv file.html file.cgi
$ chmod a+rx file.cgi

Now make sure that Apache accepts file.cgi as a CGI program by enabling CGI support for the directory where file.cgi resides. For this add the line

Options +ExecCGI

to the .htaccess file in this directory. Finally make sure that Apache really recognizes the extension .cgi. Perhaps you additionally have to add the following line to your httpd.conf file:

AddHandler cgi-script .cgi

Now you can use file.cgi instead of file.html and make advantage of the achieved programming capability by bristling file.cgi with wanted Perl blocks (or the tranformation into a CGI script was useless).

Alternatively (or even additionally) a webmaster can enable ePerl support in a more seemless way by configuring ePerl as a real implicit server-side scripting language. This is done by assigning a MIME-type to the various valid ePerl file extensions and forcing all files with this MIME-type to be internally processed via the ePerl interpreter. You can accomplish this for Apache by adding the following to your httpd.conf file

AddType      application/x-httpd-eperl  .phtml .eperl .epl
Action       application/x-httpd-eperl  /internal/cgi/eperl
ScriptAlias  /internal/cgi              /path/to/apache/cgi-bin

and creating a copy of the eperl program in your CGI-directory:

$ cp -p /path/to/eperl /path/to/apache/cgi-bin/eperl

Now all files with the extensions .phtml, .eperl and .epl are automatically processed by the ePerl interpreter. There is no need for a Shebang line or any locally enabled CGI mode.

One final hint: When you want to test your scripts offline, just run them with forced CGI/1.1 mode from your shell. But make sure you prepare all environment variables your script depends on, e.g. QUERY_STRING or PATH_INFO.

$ export QUERY_STRING="key1=value1&key2=value2"
$ eperl -mc file.phtml
NPH-CGI/1.1 compliant interface mode

This runtime mode is a special variant of the CGI/1.1 interface mode, because most webservers (e.g. Apache) provide it for special purposes. It is known as Non-Parsed-Header (NPH) CGI/1.1 mode and is usually used by the webserver when the filename of the CGI program is prefixed with ``nph-''. In this mode the webserver does no processing on the HTTP reponse headers and no buffering of the resulting data, i.e. the CGI program actually has to provide a complete HTTP response itself. The advantage is that the program can generate arbitrary HTTP headers or MIME-encoded multiblock messages.

So, above we have renamed the file to file.cgi which restricted us a little bit. When we alternatively rename file.html to nph-file.cgi and force the NPH-CGI/1.1 interface mode via option -mn then this file becomes a NPH-CGI/1.1 compliant program under Apache and other webservers. Now our script can provide its own HTTP response (it need not, because when absent ePerl provides a default one for it).

#!/path/to/bin/eperl -mn
<? print "HTTP/1.0 200 Ok\n";
   print "X-MyHeader: Foo Bar Quux\n";
   print "Content-type: text/html\n\n";
<html>
...

As you expect this can be also used with the implicit Server-Side Scripting Language technique. Put

AddType      application/x-httpd-eperl  .phtml .eperl .epl
Action       application/x-httpd-eperl  /internal/cgi/nph-eperl
ScriptAlias  /internal/cgi              /path/to/apache/cgi-bin

into your httpd.conf and run the command

$ cp -p /path/to/eperl /path/to/apache/cgi-bin/nph-eperl

from your shell. This is the preferred way of using ePerl as a Server-Side Scripting Language, because it provides most flexibility.

Security

When you are installing ePerl as a CGI/1.1 or NPH-CGI/1.1 compliant program (see above for detailed description of these modes) via

$ cp -p /path/to/eperl /path/to/apache/cgi-bin/eperl
$ chown root /path/to/apache/cgi-bin/eperl
$ chmod u+s  /path/to/apache/cgi-bin/eperl

or

$ cp -p /path/to/eperl /path/to/apache/cgi-bin/nph-eperl
$ chown root /path/to/apache/cgi-bin/nph-eperl
$ chmod u+s  /path/to/apache/cgi-bin/nph-eperl

i.e. with SetUID bit enabled for the root user, ePerl can switch to the UID/GID of the scripts owner. Although this is a very useful feature for script programmers (because one no longer need to make auxiliary files world-readable and temporary files world-writable!), it can be to risky for you when you are paranoid about security of SetUID programs. If so just don't install ePerl with enabled SetUID bit! This is the reason why ePerl is per default only installed as a Stand-Alone Unix filter which never needs this feature.

For those of us who decided that this feature is essential for them ePerl tries really hard to make it secure. The following steps have to be successfully passed before ePerl actually switches its UID/GID (in this order):

1. The script has to match the following extensions:
   .html, .phtml, .ephtml, .epl, .pl, .cgi
2. The UID of the calling process has to be a valid UID,
   i.e. it has to be found in the systems password file
3. The UID of the calling process has to match the 
   following users: root, nobody
4. The UID of the script owner has to be a valid UID,
   i.e. it has to be found in the systems password file
5. The GID of the script group has to be a valid GID,
   i.e. it has to be found in the systems group file
6. The script has to stay below or in the owners homedir

IF ONLY ONE OF THOSE STEPS FAIL, NO UID/GID SWITCHING TAKES PLACE! You can only disable some steps at compile time. See eperl_global.h.

Also remember that ePerl always eliminates the effective UID/GID, independent of the runtime mode and independent if ePerl has switched to the UID/GID of the owner. For security reasons, the effective UID/GID is always destroyed before the script is executed.

OPTIONS

-d name=value

Sets a Perl variable in the package main which can be referenced via $name or more explicitly via $main::name. The command

eperl -d name=value ..

is actually equivalent to having

<? $name = value; !>

at the beginning of inputfile.

-D name=value

Sets a environment variable which can be referenced via $ENV{'variable'} inside the Perl blocks. The command

eperl -D name=value ..

is actually equivalent to

export name=value; eperl ...

but the advantage of this option is that it doesn't manipulate the callers environment.

-B begin_delimiter

Sets the Perl block begin delimiter string. Use this in conjunction with -E to set different delimiters when using ePerl as an offline HTML creation-language while still using it as an online HTML scripting-language. Default delimiters are <? and !> for CGI modes and <: and :> for standalone Unix filtering mode.

There are a lot of possible variations you could choose: "<:" and ":>" (the default ePerl stand-alone filtering mode delimiters), "<?" and "!>" (the default ePerl CGI interface mode delimiters), "<script language='ePerl'>" and "</script>" (standard HTML scripting language style), "<!--#eperl code='" and "' -->" (NeoScript and SSI style) or even "<?" and ">" (PHP/FI style; but this no longer recommended because it can lead to parsing problems. Should be used only for backward compatibility to old ePerl versions 1.x).

-E end_delimiter

Sets the Perl block end delimiter string. See also option -B.

-m mode

This forces ePerl to act in a specific runtime mode. See above for a detailed description of the three possible modes: Stand-alone filter (mode=f, i.e. option -mf), CGI/1.1 interface mode (mode=c, i.e. option -mc) or the NPH-CGI/1.1 interface mode (mode=n, i.e. option -mn).

-o outputfile

Forces the output to be written to outputfile instead of stdout. Use this option when using ePerl as a filter. The outputfile ``-'' sets stdout as the output handle explicitly. Notice that this file is relative to the source file directory when the runtime mode is forced to CGI or NPH-CGI.

-k

Forces ePerl to keep the current working directory from where it was started. Per default ePerl will change to the directory where the file to be executed stays. This option is useful if you use ePerl as an offline filter on a temporary file.

-x

This sets debug mode where ePerl outputs the internally created Perl script to the console (/dev/tty) before executing it. Only for debugging problems with the inputfile conversion.

-c

This runs a pure syntax check which is similar to ``perl -c''.

-r

This prints the internal ePerl README file to the console.

-l

This prints the internal ePerl LICENSE file to the console.

-v

This prints ePerl version information to the console.

-V

Same as option -v but additionally shows the Perl compilation parameters.

ENVIRONMENT

Used Variables

PATH_TRANSLATED

This CGI/1.1 variable is used to determine the source file when ePerl operates as a NPH-CGI/1.1 program under the environment of a webserver.

Provided Variables

SCRIPT_SRC_SIZE

The filesize of the script, in bytes.

SCRIPT_SRC_MODIFIED

The last modification time of the script, in seconds since 0 hours, 0 minutes, 0 seconds, January 1, 1970, Coordinated Universal Time.

SCRIPT_SRC_MODIFIED_CTIME

The last modification time of the script, in ctime(3) format (``WDAY MMM DD HH:MM:SS YYYY\n'').

SCRIPT_SRC_MODIFIED_ISOTIME

The last modification time of the script, in ISO format (``DD-MM-YYYY HH:MM'').

SCRIPT_SRC_OWNER

The username of the script owner.

VERSION_INTERPRETER

The ePerl identification string.

VERSION_LANGUAGE

The identification string of the used Perl interpreter library.

AUTHOR

Ralf S. Engelschall
rse@engelschall.com
www.engelschall.com

SEEALSO

ePerl:  http://www.engelschall.com/sw/eperl/
Perl:   perl(1),  http://www.perl.com/perl/
Apache: httpd(8), http://www.apache.org/

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 294:

You forgot a '=back' before '=head2'

Around line 343:

=back without =over