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
orStatus
. 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
orPATH_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 commandeperl -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 commandeperl -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