The information in this chapter merely outlines the WASD implementation
details, which are in general very much vanilla CGI and NCSA CGI (Common
Gateway Interface) compliant, originally based the INTERNET-DRAFT authored by
D.Robinson (drtr@ast.cam.ac.uk), 8 January 1996, and confirmed against the
latest INTERNET-DRAFT authored by Ken A.L.Coar (drtr@etrade.co.uk), 12 June
1999.
2.1 - CGI Environment Variables
Environment variables are provided to the script via DCL global symbols. Each CGI variable symbol name is prefixed with "WWW_" (by default, although this can be changed using the "/CGI_PREFIX" qualifier and the SET CGIPREFIX mapping rule, see "Technical Overview", this is not recommended if the WASD VMS scripts are to be used, as they expect CGI variable symbols to be prefixed in this manner).
In line with other CGI implementations, additional, non-compliant variables are provided to ease CGI interfacing. These provide the various components of the query string. A keyword query string and a form query string are parsed into separated variables, named
WWW_KEY_number WWW_KEY_COUNT WWW_FORM_form-element-name
plus a number of non-"standard" CGI variables to assist in tailoring
scripts for the WASD environment. Do not make your scripts dependent on any of
these if portability is a goal. See the table below.
VMS Apache Compliance
WASD v7.0 had it's CGI environment tailored slightly to ease portability
between VMS Apache and WASD. This included the provision of an APACHE_INPUT:
stream and several Apache-specific CGI variables (see the table below). The
CGILIB C function library (see 1.7 - Scripting Function Library) has also been made
Apache compliant.
VMS Limits
CGI variable values are limited to approximately 980 characters (regardless
of the version of VMS in use). This should be sufficient for most
circumstances (if not consider using CGIplus, a small extension to CGI
programming which removes this limitation). Why such an odd number and why a
little rubbery? With standard CGI, DCL symbols are used for the CGI variables.
A DCL command line is limited to 255 characters so the symbols for larger
variables are built up over successive DCL commands. The limit of 980
characters is set by what can actually be achieved this way (still,
it's much better than a limit of 255 or less!).
CGI Variables
Remember, all variables are prefixed by "WWW_", and not all variables will be present for all requests.
|
If the request path is set to provide them, there are also be variables
providing information about a Secure Sockets Layer transported request's SSL
environment.
CGI Variable Demonstration
The basic CGI symbol names are demonstrated here with a call to a script that simply executes the following DCL code:
$ SHOW SYMBOL WWW_* $ SHOW SYMBOL *Note how the request components are represented for "ISINDEX"-style searching (third item) and a forms-based query (fourth item).
The UNIQUE_ID variable is a fully Apache-compliant implementation,
for each request generating a globally and temporally unique 19 character
string that can be used where such a identifier might be needed. This string
contains only "A"-"Z", "a"-"z",
"0"-"9", "@" and "-" characters and is generated
using a combination of time-stamp, host IP address, server system process
identifier and counter, and is "guaranteed" to be unique in (Internet)
space and time.
2.2 - CGI Compliant Output
Script output must behave in a CGI-compliant fashion (by way of contrast, see 2.3 - Raw HTTP Output). That is, a CGI script may redirect the location of the document, using a Location: header line, or may supply a data stream beginning with a Content-Type: or Status: header line.
If the script output begins with a CGI-compliant "Content-Type:
text/..." (text document) the HTTPd assumes that output will be
line-oriented and requiring HTTP carriage-control (each record/line terminated
by a line-feed), and will thereafter ensure each record it receives is
correctly terminated before passing it to the client. In this way DCL
procedure output (and the VMS CLI in general) is supported transparently. Any
other content-type is assumed to be binary and no carriage control
is enforced.
Example DCL Scripts
A simple script to provide the system time might be:
$ say = "write sys$output" $! the next two lines make it CGI-compliant $ say "Content-Type: text/plain" $ say "" $! start of plain-text script output $ show time
A script to provide the system time more elaborately (using HTML):
$ say = "write sys$output" $! the next two lines make it CGI-compliant $ say "Content-Type: text/html" $ say "" $! start of HTML script output $ say "<HTML>" $ say "Hello ''WWW_REMOTE_HOST'" !(CGI variable) $ say "<P>" $ say "System time on node ''f$getsyi("nodename")' is:" $ say "<H1>''f$cvtime()'</H1>" $ say "</HTML>"
A script does not have to output a CGI-compliant data stream. If it begins with a HTTP header status line (e.g. "HTTP/1.0 200 Success"), HTTPd assumes it will supply a raw HTTP data stream, containing all the HTTP requirements. This is the equivalent of the no-parse-header, or "nph..." named scripts of some environments.
Any such script must observe the HyperText Transfer Protocol, supplying a
full header and body with correct carriage-control.
Raw HTTP DCL Script
The following example show a DCL script. Note the full HTTP header and each line explicitly terminated with a carriage-return and line-feed pair.
$ lf[0,8] = %x0a $ say = "write sys$output" $! the next line determines that it is raw HTTP stream $ say "HTTP/1.0 200 Success" + lf $ say "Content-Type: text/html" + lf $! response header separating blank line $ say lf $! start of HTML script output $ say "<HTML>" $ say "Hello ''WWW_REMOTE_HOST'" $ say "<P>" $ say "Local time is ''WWW_REQUEST_TIME_LOCAL'" $ say "</HTML>"
This assists with the generation of HTTP responses, including the transfer
of binary content from files (copying a file back to the client as part of the
request), and the processing of the contents of POSTed requests from DCL. See
1.6 - DCL Processing of Requests.
Raw HTTP C Script
When scripting using the C programming language there can be considerable efficiencies to be gained by providing a binary output stream from the script. This may be simply provided using a code construct similar to following to reopen <stdout> in binary mode.
/* reopen output stream so that the '\r' and '\n' are not filtered */ #ifdef __DECC if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL) exit (vaxc$errno); #endif
This is used consistently in WASD scripts. Carriage control must be supplied as part of the C standard output (no differently to any other C program). Output can be be explicitly fflush()ed at any stage to overtly send output buffered by the C RTL to the client. If the fwrite() library function is used then to maintain the buffering efficiency an additional reopen() parameter is required following the "ctx=bin", "ctx=xplct".
The full HTTP header can be supplied (as in the following example) or just a CGI-compliant header output.
fprintf (stdout, "HTTP/1.0 200 Success\r\n\ Content-Type: text/html\r\n\ \r\n\ <HTML>\n\ Hello %s\n\ <P>\n\ System time is %s\n\ </HTML>\n", getenv("WWW_REMOTE_HOST"), getenv("WWW_REQUEST_TIME_LOCAL"));
A source code collection of C language functions useful for processing the
more vexing aspects of CGI/CGIplus programming. See
1.7 - Scripting Function Library.
2.4 - Plain Text Output
If a script output stream begins with neither a CGI-compliant header or a
full HTTP output stream it is considered to be plain text. The server
automatically generates an appropriate HTTP response header and the output
appears via a browser as a plain-text page.
2.5 - Raw HTTP Input (POST Processing)
For POST and PUT HTTP methods (e.g. a POSTed HTML form) the body of the request may be read from the HTTP$INPUT stream. For executable image scripts requiring the body to be present on SYS$INPUT (the C language <stdin> stream) a user-mode logical may be defined immediately before invoking the image, as in the example.
$ EGSCRIPT = "$HT_EXE:EGSCRIPT.EXE" $ DEFINE /USER SYS$INPUT HTTP$INPUT $ EGSCRIPT
The HTTP$INPUT stream may be explicitly opened and read. Note that this is a raw stream, and HTTP lines (carriage-return/line-feed terminated sequences of characters) may have be blocked together for network transport. These would need to be explicity parsed by the program.
NOTE: Versions of the server prior to 4.3 supplied the full request (header then body) to the script. This was not fully CGI-compliant. Versions 4.3 and following supply only the body, although the previous behaviour may be explicitly selected using the configuration parameter [DclFullRequest].