The information in this chapter merely outlines the WASD implementation
details, which are in general very much vanilla CGI and WWW CGI (Common
Gateway Interface) compliant, based the INTERNET-DRAFT authored by D.Robinson
(drtr@ast.cam.ac.uk), 8 January 1996.
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.
CGI variable values are limited to approximately 980 characters (regardless of the version of VMS in use). This should be sufficient for most circumstances. 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!).
Remember, all variables are prefixed by "WWW_", and not all variables will be present for all requests.
|
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).
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.5 - 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.6 - 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].