# Writing scripts

## Introduction

This document describes how to write basic scripts for the DECthreads HTTP server. A script may be either a DCL command procedure or an executable image. It must reside in a script directory defined in the server's configuration file via an 'exec' rule or 'htbin' rule. The execution of your script is directly managed by the DECnet task object WWWEXEC.COM, which locates your script and invokes/runs it with the follow command line:

       $ script-cmd method translated-path protocol-version

Your script runs in 2 phases:

1. Dialog phase: In the dialog phase, your script queries the server for additional data not included on the command line. If all the necessary information has been provided on the command line (i.e. method, path), your script may go directly to the output phase. For CGI (Common Gateway Interface) style scripts, the dialog phase is handled internally by the cgi_init() routine or cgi_symbols.exe program.

2. Output phase: In the output phase, your script generates the response to be sent to the client. Once a script enters the output phase, no other dialog commands can be sent. The output phase has 3 different modes: text, raw, and CGI. The format of the output you need generate is different for each of the modes.

## Command line arguments (parameters)

The following 3 items are passed to your script via the command line, i.e. as DCL parameter symbols (if script is a command procedure) or as command line arguments:

  argv[1]/P1
    This argument/parameter holds the method (e.g. GET) specified in the client's request.

  argv[2]/P2
    This argument/parameter holds the path portion (ident) of the URL that triggered the execution of the script, truncated to 255 characters. Note that this argument is the translated path, i.e. the string that results after all the configuration file translations. Note also that string includes the exec directory prefix and is not the same as the CGI PATH_TRANSLATED variable.

  argv[3]/P3
    This argument/parameter holds the HTTP protocol that the client is using, either "HTTP/1.0" or null.

## Network connection

A script communicates with the server via a DECnet logical link which is open by DCL as logical name net_link. You write commands and data to this link and read server responses to your commands on this link. When your script is a program, the scriptlib and cgilib routines handle the reading and writing to the net_link connection. Since this link is opened in supervisor mode by WWWEXEC.COM, it remains open until your script returns (i.e. it is a process permanent file).

## Dialog phase

In dialog phase, your script writes commands over the net_link to the server and read the response sent by the server. The particular commands are described in the scriptserver protocol documentation.

## Output Modes

Text mode (<DNETTEXT>)
  Text mode is used to send simple text data and messages (i.e. error messages) to the client. In text mode, the first line of output is the HTTP status line followed by lines of text. Do not include the protocol-version (HTTP/1.0) on the status line as it will be prepended by the server if needed.

  In text mode, the server automatically appends a CR/LF record delimiter after each record sent over the network line. This make text mode convenient for returning DCL command output (e.g. HELP) to the client.

Raw mode (<DNETRAW>)
  Raw mode is used in situations where you want your script to have complete control over the HTTP response (status and headers) sent back to the client.

  Note that unless you send a <DNETRECMODE> dialog command in the dialog phase, your output must explicitly include the carriage control characters (CR/LF) for delimiting lines.

CGI mode (<DNETCGI>)
In CGI mode the server interprets your output according to the CGI (Common Gateway Interface) specification. The first line of output is either a 'Content-type:' header line or 'location: ' header line followed by a blank line and the output data. If a 'Content-type:' header is sent, you can include additional header lines to be returned to the client before the blank line (e.g. last-modified header). If you include a 'Status:' header line, the header argument overrides the default HTTP status returned.

Note that unless you send a <DNETRECMODE> dialog command in the dialog phase, your output must explicitly include the carriage control characters (CR/LF) for delimiting lines.

## Example

    $!
    $! Demonstrate use of scripts.  P1: Method,  P2: path, P3: protocol-version
    $!
    $ write net_link "<DNETARG2>"		! get search argument (part after ?)
    $ read/end=done net_link search_arg
    $ if search_arg .eqs. ""
    $ then
    $!    Request doesn't have a search argument, redirect to HTML document that
    $!    explains what you are supposed to do.
    $!
    $    crlf = f$fao("!/")
    $    write net_link "<DNETCGI>"
    $    write net_link "location: /demo/vmshelp.html",crlf,crlf
    $    write net_link "</DNETCGI>"
    $    exit
    $ endif
    $!
    $! Decode encoded characters in search argument.
    $!
    $ search_arg = f$extract(1,255,search_arg)	! Trim "/"
    $ num = 0
    $ help_list = ""
    $ help_list_raw = ""
    $ next_keyword:
    $    keyword = f$element(num,"+",search_arg)
    $    if keyword .eqs. "+" then goto decode_escape
    $    help_list_raw = help_list_raw + keyword + " "
    $    num = num + 1
    $    goto next_keyword
    $ decode_escape:
    $    percent = f$locat("%",help_list_raw)
    $    help_list = help_list + f$extract(0,percent,help_list_raw)
    $    if percent .ge. f$length(help_list_raw) then goto do_help
    $    help_list[f$length(help_list)*8,8] = -
    		%x0'f$extract(percent+1,2,help_list_raw)'
    $    help_list_raw = f$extract(percent+3,f$length(help_list_raw),help_list_raw)
    $    goto decode_escape
    $!
    $! Generate output using text mode.
    $ do_help:
    $ write net_link "<DNETTEXT>"
    $ write net_link "200 Sending document"
    $ write sys$output "help_list = ", help_list
    $ define sys$Output net_link:
    $ type sys$input
    VMSHELP output:
    $ if help_list .eqs. "? " then help_list = ""
    $ helpcmd = "help" + " " + help_list
    $ helpcmd
    $ write net_link "</DNETTEXT>"
    $!
    $ done:
    $ exit