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

<CHAPTER>(CGI\chapter_scripting_cgi)

<P> 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.

<HEAD1>(CGI Environment Variables\head_cgi_env_variables)

<P> With the standard CGI environment variables are provided to the script via
DCL global symbols. Each CGI variable symbol name is prefixed with
<QUOTE>(WWW_) (by default, although this can be changed using the
<QUOTE>(/CGI_PREFIX) qualifier and the SET CGIPREFIX mapping rule, see
<QUOTE>(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).

<P> There are a number of non-<QUOTE>(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.

<NOTE>(Never, ever substitute)
the contents of CGI variables directly into the code stream using interpreters
that will allows this (e.g. DCL, Perl).  You run a very real risk of having
unintended content maliciously change the intended function of the code.  For
example, never use comma substitution of a CGI variable at the DCL command line
as in
<CODE_EXAMPLE>
  $ COPY 'WWW_FORM_SRC' 'WWW_FORM_DST'
<ENDCODE_EXAMPLE>
<CP>Always pre-process the content of the variable first, ensuring there has
been nothing inserted that could subvert the intended purpose (repeated here to
emphasize the significance of this rule).
<ENDNOTE>

<P> CGI variable capacity now varies significantly with VMS version.

<P> The total size of all CGI variable names and values is determined by the
value of [BufferSizeDclCommand] configuration directive, which determines the
total buffer space of a mailbox providing the script's SYS$COMMAND.  The
default value of 4096 bytes will be ample for the typical CGI script request,
however if it contains very large individual variables or a large number of
form fields, etc., it may be possible to exhaust this quantity.

<HEAD>(VMS V7.3-2 and later <HELLIPSIS>\head_cgi_limits_732)

<P> CGI variables may contain up to approximately 8150 characters (the full
8192 symbol capacity cannot be realized  due to the way the symbols are created
via the CLI).  This is a significant increase on earlier capacities.  Mailbox
buffer [BufferSizeDclCommand] may need to be increased if this capacity is to
be fully utilized.

<HEAD>(VMS V7.3-1 and earlier <HELLIPSIS>\head_cgi_limits_731)

<P> Values are limited to approximately 980 characters.  This should still be
sufficient for  most circumstances (if not consider using CGIplus or ISAPI,
extensions to CGI programming which remove this limitation).  Why such an odd
number and why a little rubbery?  A DCL command line with these versions is
limited to 255 characters so the symbols for larger variables are built up over
successive DCL commands with the limit of 980 characters determined by CLI
constraints.

<HEAD>(CGI Variables\head_cgi_variables)

<P> Remember, by default all variables are prefixed by <QUOTE>(WWW_) (though
this may be modified using the <EMPHASIS>(set CGIprefix=) mapping rule), and
not all variables will be present for all requests.

<P>
<CENTER_LINE>(<EMPHASIS>(CGI Environment Variables\BOLD))
<TABLE>
<TABLE_SETUP>(3\20\35)
<TABLE_HEADS>(Name\Description\Origin)
<TABLE_ROW>(AUTH_ACCESS\<QUOTE>(READ) or <QUOTE>(READ+WRITE)\WASD)
<TABLE_ROW>(AUTH_AGENT\used by an authorization agent (specialized use)\WASD)
<TABLE_ROW>(AUTH_GROUP\authentication group\WASD)
<TABLE_ROW>(AUTH_PASSWORD\plain-text password, only if EXTERNAL realm\WASD)
<TABLE_ROW>(AUTH_REALM\authentication realm\WASD)
<TABLE_ROW>(AUTH_REALM_DESCRIPTION\browser displayed string\WASD)
<TABLE_ROW>(AUTH_TYPE\authentication type (BASIC or DIGEST)\CGI)
<TABLE_ROW>(AUTH_USER\details of authenticated user\WASD)
<TABLE_ROW>(CONTENT_LENGTH\<QUOTE>(Content-Length:) from request header\CGI)
<TABLE_ROW>(CONTENT_TYPE\<QUOTE>(Content-Type:) from request header\CGI)
<TABLE_ROW>(DOCUMENT_ROOT\generally empty, configurable path setting\Apache)
<TABLE_ROW>(FORM_<EMPHASIS>(field-name)\query string <QUOTE>(&) separated form elements\WASD)
<TABLE_ROW>(GATEWAY_BG\device name of raw client socket (specialized use)\WASD)
<TABLE_ROW>(GATEWAY_EOF\End of request sentinal (specialized use)\WASD)
<TABLE_ROW>(GATEWAY_EOT\End of callout sentinal (specialized use)\WASD)
<TABLE_ROW>(GATEWAY_ESC\Callout escape sentinal (specialized use)\WASD)
<TABLE_ROW>(GATEWAY_INTERFACE\<QUOTE>(CGI/1.1)\CGI)
<TABLE_ROW>(GATEWAY_MRS\maximum record size of script SYS$OUTPUT\WASD)
<TABLE_ROW>(HTTP_ACCEPT\any list of browser-accepted content types\CGI)
<TABLE_ROW>(HTTP_ACCEPT_CHARSET\any list of browser-accepted character sets\CGI)
<TABLE_ROW>(HTTP_ACCEPT_LANGUAGE\any list of browser-accepted languages\CGI)
<TABLE_ROW>(HTTP_AUTHORIZATION\any from request header (specialized use)\CGI)
<TABLE_ROW>(HTTP_CACHE_CONTROL\HTTP/1.1 cache control directive\CGI)
<TABLE_ROW>(HTTP_COOKIE\any cookie sent by the client\CGI)
<TABLE_ROW>(HTTP_FORWARDED\any proxy/gateway hosts that forwarded the request\CGI)
<TABLE_ROW>(HTTP_HOST\host and port request was sent to\CGI)
<TABLE_ROW>(HTTP_IF_MODIFIED_SINCE\any last modified GMT time string\CGI)
<TABLE_ROW>(HTTP_PRAGMA\any pragma directive of request header\CGI)
<TABLE_ROW>(HTTP_REFERER\any source document URL for this request\CGI)
<TABLE_ROW>(HTTP_USER_AGENT\client/browser identification string\CGI)
<TABLE_ROW>(HTTP_X_FORWARDED_FOR\proxied client host name or address\Squid)
<TABLE_ROW>(HTTP_<EMPHASIS>(field-name)\any other unknown request header field\WASD)
<TABLE_ROW>(KEY_<EMPHASIS>(n)\query string <QUOTE>(+) separated elements\WASD)
<TABLE_ROW>(KEY_COUNT\number of <QUOTE>(+) separated elements\WASD)
<TABLE_ROW>(PATH_INFO\virtual path of data requested in URL\CGI)
<TABLE_ROW>(PATH_TRANSLATED\VMS file path of data requested in URL\CGI)
<TABLE_ROW>(QUERY_STRING\un-URL-decoded string following <QUOTE>(?) in URL\CGI)
<TABLE_ROW>(REMOTE_ADDR\IP host address of HTTP client\CGI)
<TABLE_ROW>(REMOTE_HOST\IP host name of HTTP client\CGI)
<TABLE_ROW>(REMOTE_USER\authenticated remote user name (or empty)\CGI)
<TABLE_ROW>(REQUEST_CHARSET\any server-determined request character set\WASD)
<TABLE_ROW>(REQUEST_METHOD\<QUOTE>(GET), <QUOTE>(PUT), etc.\CGI)
<TABLE_ROW>(REQUEST_SCHEME\<QUOTE>(http:) or <QUOTE>(https:)\WASD)
<TABLE_ROW>(REQUEST_TIME_GMT\GMT time request received\WASD)
<TABLE_ROW>(REQUEST_TIME_LOCAL\Local time request received\WASD)
<TABLE_ROW>(REQUEST_URI\full, unescaped request string\Apache)
<TABLE_ROW>(SCRIPT_DEFAULT\mapped default directory for script\WASD)
<TABLE_ROW>(SCRIPT_FILENAME\script file name
(e.g. CGI-BIN:[000000]QUERY.COM)\Apache)
<TABLE_ROW>(SCRIPT_NAME\script being executed (e.g. <QUOTE>(/query))\CGI)
<TABLE_ROW>(SERVER_ADDR\IP host name of server system\WASD)
<TABLE_ROW>(SERVER_ADMIN\email address for server administration\Apache)
<TABLE_ROW>(SERVER_CHARSET\server default character set\WASD)
<TABLE_ROW>(SERVER_GMT\offset from GMT (e.g. <QUOTE>(+09:30))\WASD)
<TABLE_ROW>(SERVER_NAME\IP host name of server\CGI)
<TABLE_ROW>(SERVER_PROTOCOL\HTTP protocol version (always <QUOTE>(HTTP/1.0))\CGI)
<TABLE_ROW>(SERVER_PORT\IP port request was received on\CGI)
<TABLE_ROW>(SERVER_SIGNATURE\server ID, host name and port\Apache)
<TABLE_ROW>(SERVER_SOFTWARE\software ID of HTTP server\CGI)
<TABLE_ROW>(UNIQUE_ID\unique 19 character string\Apache)
<ENDTABLE>

<P> 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.

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

<HEAD>(Query String Variables\head_cgi_query_string)

<P> In line with other CGI implementations, additional, non-compliant variables
are provided to ease CGI interfacing.  These provide the various components of
any query string.  A <EMPHASIS>(keyword) query string and a <EMPHASIS>(form)
query string are parsed into

<CODE_EXAMPLE>
  WWW_KEY_<EMPHASIS>(number) 
  WWW_KEY_COUNT
  WWW_FORM_<EMPHASIS>(form-element-name)
<ENDCODE_EXAMPLE>

<P> Variables named WWW_KEY_<EMPHASIS>(number) will be generated if the query
string contains one or more plus (<QUOTE>(+)) and no equate symbols
(<QUOTE>(=)).

<P> Variables named WWW_FORM_<EMPHASIS>(form-element-name) will be generated if
the query string contains one or more equate symbols.  Generally such a query
string is used to encode form-URL-encoded (MIME type
<EMPHASIS>(x-www-form-urlencoded)) requests.  By default the server will
report an incorrect encoding with a 400 error response.  However some scripts
use malformed encodings and so this behaviour may be suppressed using the
<EMPHASIS>(set script=query=relaxed) mapping rule.

<CODE_EXAMPLE>
   set /cgi-bin/script-name* script=query=relaxed
<ENDCODE_EXAMPLE>

<P> To suppress this decoding completely (and save a few CPU cycles) use the
following rule.

<CODE_EXAMPLE>
   set /cgi-bin/script-name* script=query=none
<ENDCODE_EXAMPLE>

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

<HEAD>(UNIQUE_ID Note\head_cgi_unique_id)

<P> The UNIQUE_ID variable is a mostly Apache-compliant implementation (the
<QUOTE>(_) has been substituted for the <QUOTE>(@) to allow it's use in file
names), 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 <QUOTE>(A)-<QUOTE>(Z), <QUOTE>(a)-<QUOTE>(z),
<QUOTE>(0)-<QUOTE>(9), <QUOTE>(_) and <QUOTE>(-) characters and is generated
using a combination of time-stamp, host IP address, server system process
identifier and counter, and is <QUOTE>(guaranteed) to be unique in (Internet)
space and time. 

<HEAD>(VMS Apache (CSWS) Compliance\head_cgi_apache)

<P> WASD v7.0 had it's CGI environment tailored slightly to ease portability
between VMS Apache (Compaq Secure Web Server) 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
(<REFERENCE>(head_cgilib)) has also been made CSWS V1.0-1 and later (Apache
1.3.12 and higher) compliant.

<HEAD>(CGI Variable Demonstration\head_cgi_variable_demo)

<P> The basic CGI symbol names are demonstrated here with a call to a script 
that simply executes the following DCL code:

<CODE_EXAMPLE>
  $ SHOW SYMBOL WWW_*
  $ SHOW SYMBOL *
<ENDCODE_EXAMPLE>

<CP> Note how the request components are represented for
<QUOTE>(ISINDEX)-style searching (third item) and a forms-based query (fourth
item). 

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

<COMMENT>(HTML=
<UL>
<LI> <A HREF="/cgi-bin/cgi_symbols">/cgi-bin/cgi_symbols</A>
<LI> <A HREF="/cgi-bin/cgi_symbols/ht_root/doc/htd">
     /cgi-bin/cgi_symbols/ht_root/doc/htd</A>
<LI> <A HREF="/cgi-bin/cgi_symbols/ht_root/doc/htd/*.*?string1+string2">
     /cgi-bin/cgi_symbols/ht_root/doc/htd/*.*?string1+string2</A>
<LI> <A HREF="/cgi-bin/cgi_symbols/ht_root/doc/htd?FirstField=for&SecondField=this">
     /cgi-bin/cgi_symbols/ht_root/doc/htd?FirstField=for&SecondField=this</A>
</UL>

<P> Script source:
<BLOCKQUOTE>
  <A HREF="/ht_root/src/other/cgi_symbols.com">HT_ROOT:[SRC.OTHER]CGI_SYMBOLS.COM</A>
</BLOCKQUOTE>
)

<COMMENT>(HTML/OFF)
<P><BOX>(online demonstration)
<COMMENT>(HTML/ON)

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

<HEAD1>(Script Output\head_script_output)

<P> This information applies to all non-DECnet based scripting, CGI, CGIplus,
RTE, ISAPI.  WASD uses mailboxes for script inter-process communication (IPC). 
These are efficient, versatile and allow direct output from all VMS
environments and utilities.  Like many VMS record-oriented devices however
there are some things to consider when using them.

<LIST>(UNNUMBERED)

<LE><EMPHASIS>(Record-Oriented\BOLD)

<P> The mailboxes are created record, not stream oriented.  This means records
output by standard VMS means (e.g. DCL, utilities, programming languages) are
discretely identified and may be processed appropriately by the server as text
or binary depending on the content-type.

<LE><EMPHASIS>(Maximum Record Size\BOLD)

<P> Being record oriented there is a maximum record size (MRS) that can
be output.  Records larger than this result in SYSTEM-F-MBTOOSML errors.  The
WASD default is 4096 bytes.  This may be changed using the
[BufferSizeDclOutput] configuration directive.  This allocation consumes
process BYTLM with each mailbox created so the account must be dimensioned
sufficiently to supply demands for this quota.  The maximum possible size for
this is a VMS-limit of 60,000 bytes.

<LE><EMPHASIS>(Buffer Space\BOLD)

<P> When created the mailbox has it's buffer space set.  With WASD IPC
mailboxes this is the same as the MRS.  The total data buffered may not exceed
this without the script entering a wait state (for the mailbox contents to be
cleared by the server).  As mailboxes use a little of the buffer space to
delimit records stored in it the amount of data is actually less than the total
buffer space.

<ENDLIST>

<P> To determine the maximum record size and total capacity of the mailbox
buffer between server and script WASD provides a CGI environment variable,
GATEWAY_MRS, containing an integer with this value.

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

<HEAD2>(CGI Compliant Output\head_cgi_output)

<P> Script response may be CGI or NPH compliant
(<REFERENCE>(head_nph_output)).   CGI compliance means the script's response
must begin with a line containing one of the following fields.

<LIST>(UNNUMBERED)

<LE><EMPHASIS>(Status: \BOLD) an HTTP status code and associated
explanation string

<LE><EMPHASIS>(Content-Type: \BOLD) the script body's MIME content-type

<LE><EMPHASIS>(Location: \BOLD) a redirection URL (either full or internal)

<ENDLIST>

<P> Other HTTP-compliant response fields may follow, with the response header
terminated and the response body begun by a single empty line.  The following 
is an example of a CGI-compliant response.

<CODE_EXAMPLE><LITERAL>(
  Content-Type: text/html
  Content-Length: 35

  <HTML>
  <B>Hello world!</B>
  </HTML>
)<ENDCODE_EXAMPLE>

<P> Strict CGI output compliance can be enabled and disabled using the
[CgiStrictOutput] configuration directive.  With it disabled the server will
accept any output from the script, if not CGI or NPH compliant then it
automatically generates plain-text header.  When enabled, if not a CGI or NPH
header the server returns a <QUOTE>(502 Bad Gateway) error.  For debugging
scripts generating this error introduce a <EMPHASIS>(plain-text) debug mode and
header, or use the WATCH facility's CGI item (see the Technical Overview).

<HEAD>(WASD Specifics\head_output_wasd_specifics)

<P> This section describes how WASD deals with some particular output issues.

<LIST>(UNNUMBERED)

<LE><EMPHASIS>(Content-Type: text/<HELLIPSIS>\BOLD)

<P> If the script response content-type is <QUOTE>(text/<HELLIPSIS>) (text
document) WASD assumes that output will be line-oriented and requiring HTTP
carriage-control (each record/line terminated by a line-feed), and will ensure
each record it receives is correctly terminated before passing it to the
client.  In this way DCL procedure output (and the VMS environment in general)
is supported transparently.  Any other content-type is assumed to be
<EMPHASIS>(binary) and no carriage-control is enforced.  This default behaviour
may be modified as described below.

<LE><EMPHASIS>(Carriage-Control\BOLD)

<P> Carriage-control behaviour for <UNDERLINE>(any) content-type may be
explicitly set using either of two additional response header fields.  The term
<EMPHASIS>(stream) is used to describe the server just transfering records,
without  additional processing, as they were received from the script.  This is
obviously necessary for binary/raw content such as images, octet-streams, etc.
The term <EMPHASIS>(record) describes the server ensuring each record it
receives has correct carriage-control - a trailing newline.  If not present one
is added.  This mode is useful for VMS textual streams (e.g. output from DCL
and VMS utilities).

<P> Using the Apache Group's proposed CGI/1.2 <QUOTE>(Script-Control:) field. 
The WASD extension-directives <EMPHASIS>(X-record-mode) and
<EMPHASIS>(X-stream-mode) sets the script output into each of the respective
modes (<REFERENCE>(head_output_script_control)).

<P> Examples of usage this field:

<CODE_EXAMPLE>
  Script-Control: X-stream-mode
  Script-Control: X-record-mode
<ENDCODE_EXAMPLE>

<LE><EMPHASIS>(Script Output Buffering\BOLD)

<P> By default WASD writes each record received from the script to the
client as it is received.  This can range from a single byte to a complete
mailbox buffer full.  WASD leaves it up to the script to determine the rate at
which output flows back to the client.

<P> While this allows a certain flexibility it can be inefficient.  There will
be many instances where a script will be providing just a body of data to the
client, and wish to do it as quickly and efficiently as possible.  Using the
proposed CGI/1.2 <QUOTE>(Script-Control:) field with the WASD extension
directive <EMPHASIS>(X-buffer-records) a script can direct the server to buffer
as many script output records as possible before transfering it to the client. 
The following should be added to the CGI response header.

<CODE_EXAMPLE>
  Script-Control: X-buffer-records
<ENDCODE_EXAMPLE>

<P> While the above offers some significant improvements to efficiency and
perceived throughput the best approach is for the script to provide records the
same size as the mailbox (<REFERENCE>(head_script_output) for detail on
determining this size if required).  The can be done explicitly by the script
programming  or if using the C language simply by changing <EMPHASIS>(stdout)
to a binary stream.  With this environment the C-RTL will control output,
automatically buffering as much as possible before writing it to the server.

<CODE_EXAMPLE>
  if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL)
     exit (vaxc$errno);
<ENDCODE_EXAMPLE>

<P> Also see the section describing <REFERENCE>(head_nph_c_script).

<ENDLIST>

<HEAD>(Script-Control:\head_output_script_control)

<P> The <EMPHASIS>(Apache Group) has proposed a CGI/1.2 that includes a
<EMPHASIS>(Script-Control:) CGI response header field.  WASD implements the
one proposed directive, along with a number of WASD extensions (those
beginning with the <QUOTE>(X-)).  Note that by convention extensions unknown by
an agent should be ignored, meaning that they can be freely included, only
being meaningful to WASD and not significant to other implementations.

<LIST>(UNNUMBERED)

<LE><EMPHASIS>(no-abort - \BOLD)
The server must not terminate the script during processing for either
no output or no-progress timeouts.  The script is to be left completely alone
to control it's own termination.  Caution, such scripts if problematic could
easily accumulate and <QUOTE>(clog up) a server or system.

<LE><EMPHASIS>(X-buffer-records - \BOLD)
Buffer records written by the script until there is [BufferSizeDclOutput] bytes
available then write it as a single block to the client.

<LE><EMPHASIS>(X-content-handler=<EMPHASIS>(keyword)  - \BOLD)
The output of the script is stripped of the CGI reponse header and the body is
given to the specified content handler.  Currently only the SSI engine is
supported using <QUOTE>(X-content-handler=SSI).

<LE><EMPHASIS>(X-crlf-mode - \BOLD)
The server should always ensure each record has trailing carriage-return then
newline characters (0x0d, 0x0a).  This is generally what VMS requires for
carriage control on terminals, printers, etc.

<LE><EMPHASIS>(X-error-line=<EMPHASIS>(integer) - \BOLD)
Source code module line number META in server generated error message
(optional).

<LE><EMPHASIS>(X-error-module=<EMPHASIS>(string) - \BOLD)
Source code module name META in server generated error message (optional).

<LE><EMPHASIS>(X-error-text=<QUOTE>(<EMPHASIS>(string)) - \BOLD)
Text of error message (mandatory, to trigger server message generation).  If
without a VMS status value this is the entire error explanation.  If with a VMS
status it becomes the context of the status.

<LE><EMPHASIS>(X-error-vms-status=<EMPHASIS>(integer) - \BOLD)
VMS status value in decimal or VMS hexadecimal (e.g. %X0000002C, optional).
Changes format of error message to detailed explanation of status.

<LE><EMPHASIS>(X-error-vms-text=<QUOTE>(<EMPHASIS>(string)) - \BOLD)
Context of a VMS status value (optional).  Usually a VMS file specification of
other text related to the status value (in commented content of error message).

<LE><EMPHASIS>(X-lifetime=<EMPHASIS>(value) - \BOLD)
The number of minutes before the idle scripting process is deleted by the
server.  Zero sets it back to the default, <QUOTE>(none) disables this
functionality. 

<LE><EMPHASIS>(X-record-mode - \BOLD)
The server should always ensure each record has a trailing newline
character (0x0a), regardless of whether the response is a <EMPHASIS>(text/...)
content-type or not.  This is what is usually required by browsers for
carriage-control in text documents.

<LE><EMPHASIS>(X-stream-mode - \BOLD)
The server is not to adjust the carriage-control of records regardless of
whether the response is a <EMPHASIS>(text/...) content-type or not.  What the
script writes is exactly what the client is sent.

<LE><EMPHASIS>(X-timeout-noprogress=<EMPHASIS>(value) -\BOLD)
The number of minutes allowed where the script does not transfer any data to
the server before the server deletes the process.  Zero sets it back to the
default, <QUOTE>(none) disables this functionality. 

<LE><EMPHASIS>(X-timeout-output=<EMPHASIS>(value) - \BOLD)
The number of minutes allowed before an active script is deleted by the server,
regardless of it still processing the request.  Zero sets it back to the
default, <QUOTE>(none) disables this functionality. 

<ENDLIST>

<P> The following is a simple example response where the server is instructed
not to delete the script process under any circumstances, and that the body
does not require any carriage-control changes.

<CODE_EXAMPLE>
  Content-Type: text/plain
  Script-Control: no-abort; X-stream-mode

  <EMPHASIS>(long, slowww script-output <HELLIPSIS>)
<ENDCODE_EXAMPLE>

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

<HEAD>(Example DCL Scripts\head_example_dcl_scripts)

<P> A simple script to provide the system time might be:

<CODE_EXAMPLE>
  $ say = "write sys$output"
  $! the next two lines make it CGI-compliant
  $ say "Content-Type: text/plain"
  $ say ""
  $! start of plain-text body
  $ show time
<ENDCODE_EXAMPLE>

<P> A script to provide the system time more elaborately (using HTML):

<CODE_EXAMPLE><LITERAL>
  $ 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>"
<ENDLITERAL>
<ENDCODE_EXAMPLE>

<HEAD2>(Non-Parsed-Header Output\head_nph_output)

<P> A script does not have to output a CGI-compliant data stream.  If it begins
with a HTTP header status line WASD assumes it will supply a
<EMPHASIS>(raw\BOLD) HTTP data stream, containing all the HTTP requirements. 
This is the same as or equivalent to the <EMPHASIS>(non-parsed-header), or
<QUOTE>(nph<HELLIPSIS>) scripts of many environments.  This is an example of
such a script response.

<CODE_EXAMPLE><LITERAL>(
  HTTP/1.0 200 Success
  Content-Type: text/html
  Content-Length: 35

  <HTML>
  <B>Hello world!</B>
  </HTML>
)<ENDCODE_EXAMPLE>

<P> Any such script must observe the HyperText Transfer Protocol, supplying a
<EMPHASIS>(full response header and body, including correct
carriage-control\BOLD).  Once the server detects the HTTP status header line it
pays no more attention to any response header fields or body records, just
transfering everything directly to the client.  This can be very efficient, the
server just a conduit between script and client, but does transfer the
responsibility for a correct HTTP response onto the script.

<HEAD>(NPH DCL Script\head_nph_dcl_script)

<P> The following example shows a DCL script.  Note the full HTTP header and
each line explicitly terminated with a carriage-return and line-feed pair. 

<CODE_EXAMPLE><LITERAL>
  $ lf[0,8] = %x0a
  $ crlf[0,16] = %x0d0a
  $ say = "write sys$output"
  $! the next line determines that it is raw HTTP stream
  $ say "HTTP/1.0 200 Success" + crlf
  $ say "Content-Type: text/html" + crlf
  $! response header separating blank line
  $ say crlf
  $! start of HTML script output
  $ say "<HTML>" + lf 
  $ say "Hello ''WWW_REMOTE_HOST'" + lf 
  $ say "<P>" + lf 
  $ say "Local time is ''WWW_REQUEST_TIME_LOCAL'" + lf 
  $ say "</HTML>" + lf 
<ENDLITERAL>
<ENDCODE_EXAMPLE>

<HEAD>(CGIUTL Utility\head_cgiutl)

<P> 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
(<REFERENCE>(head_cgi_cgiutl)).

<HEAD>(NPH C Script\head_nph_c_script)

<P> 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 results in the C Run-Time Library (C-RTL) buffering output up to the
maximum supported by the IPC mailbox.  This may be enabled using a code
construct similar to following to reopen <EMPHASIS>(stdout) in binary mode.

<CODE_EXAMPLE>
  if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL)
     exit (vaxc$errno);
<ENDCODE_EXAMPLE>

<P> 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 sent to the client at any stage using
the <EMPHASIS>(fflush()) standard library function.  Note that if the
<EMPHASIS>(fwrite()) function is used the current contents of the C-RTL buffer
are automatically flushed along the the content of the fwrite().

<CODE_EXAMPLE><LITERAL>
     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"));
<ENDLITERAL>
<ENDCODE_EXAMPLE>

<HEAD>(CGI Function Library\head_cgi_cgilib)

<P> A source code collection of C language functions useful for processing the
more vexing aspects of CGI/CGIplus programming (<REFERENCE>(head_cgilib)).

<HEAD1>(Raw HTTP Input (POST Processing)\head_nph_input)

<P> 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
<EMPHASIS>(stdin) stream) a user-mode logical may be defined immediately
before invoking the image, as in the example.

<CODE_EXAMPLE>
  $ EGSCRIPT = "$HT_EXE:EGSCRIPT.EXE"
  $ DEFINE /USER SYS$INPUT HTTP$INPUT
  $ EGSCRIPT
<ENDCODE_EXAMPLE>

<P> The HTTP$INPUT stream may be explicitly opened and read.  Note that this is
a raw stream, and HTTP <EMPHASIS>(lines) (carriage-return/line-feed terminated
sequences of characters) may have been blocked  together for network transport. 
These would need to be explicity parsed by the program.

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