[Previous] [Contents] [Index] [Next]

slinger

Tiny webserver

Syntax:

slinger [-a administrator] [-c] [-d] [-e]
        [-i address] [-n] [-p port_number] [-s]

Options:

-a administrator
Contact information of the administrator of Slinger (e.g. -a my_admin@something.com). The information is stored in the SERVER_ADMIN environment variable. The default is nobody.
-c
Request that HTML files with SSI not be placed in the browser cache. Instead of using a previously downloaded version from its local cache, the browser contacts the server whenever it displays an HTML file containing SSI. Use this option when you'd like the browser to display the latest version of your dynamic SSI data.
-d
Write debugging info to the system log. In order to capture the log messages, you need to have syslogd running.
-e
Enable the SSI exec command.
-i address
The interface for slinger to listen on (e.g. 10.0.0.1). The default is any.
-n
Don't move to the background.
-p port_number
Set the port number.
-s
Enable the SSI commands.

Description:

The slinger utility is an HTTP server for resource-constrained environments. Slinger is compliant with the CGI 1.1 and HTTP 1.1 standards, and provides support for dynamic HTML via Server Side Includes (SSI).

Running Slinger

To run Slinger, type:

slinger &

The slinger server listens on the TCP port 80. Since this is under 1024, slinger needs to be run as root. As soon as it has attached to the HTTP port, it drops itself down to user -2 (setuid (-2)).

How dynamic HTML works

Slinger supports Server Side Include (SSI) commands to provide dynamic HTML. For example, Slinger uses the PATH and CMD_INT environment variables to provide information to the SSI command, exec. Using dynamic HTML, clients can offer interactive realtime features on their web pages.

Clients code dynamic HTML by placing SSI tokens in the HTML code of their web pages. The SSI token contains an SSI command that's handled by Slinger. While transmitting the HTML code, Slinger replaces a token with HTML data based on the tag contained in the SSI token.


Note: For Slinger to process SSI tokens, the HTML file must have .shtml as its file extension.

Syntax of an SSI token

The syntax of an SSI token is as follows:

<!--#tag [[variable_set[="value"]] ...] -->

where:

<!--
Starting delimiter of an SGML/HTML comment.
#
Tells Slinger the comment contains a command.
tag
SSI command.
variable_set
One or more arguments to the SSI command.
value
One or more values for the variable set.
-->
Ending delimiter of SGML/HTML comment.


Note: There must be a space before the ending comment delimiter.

There's no limit to the token size (other than memory).

SSI commands

The valid SSI commands are: break, config, echo, exec, if, goto, include, label, and qnxvar.

break

Terminate transmission of an HTML document at any point. The break command has no arguments, so the syntax is:

<!--#break -->

config

Set certain HTML output options. The syntax is:

<!--#config variable_set="value" -->

The variable_set may contain: cmdecho, cmdprefix, cmdpostfix, errmsg, onerr, timefmt. For details, see the "config commands" section.

echo

Insert data from an HTML form field or an environment variable onto an HTML page. The echo command has one argument, var. The syntax is:

<!--#echo var="string" -->

where string is the value of an HTML form field or an environment variable. For example:

<!--#echo var="Last name" -->

Or

<!--#echo var="DATE_LOCAL" -->

The echo command uses these SSI variables, as well as CGI environment variables (for more information, see the Environment variables section in this utility):

DATE_GMT
Current Greenwich Mean date and time.
DATE_LOCAL
Current local date and time.
DOCUMENT_NAME
Complete local pathname of the current web page.
DOCUMENT_URI
Local pathname of the current web page referenced to the base directory of the web space.
LAST_MODIFIED
Date and time of the last modification of the current web page.
QUERY_STRING_UNESCAPED
Unescaped query string sent by the remote client. All characters that are special to the shell are escaped with \.

exec

Spawn an external program and print the output at the location of the exec token on the HTML page. The external program is spawned to increase performance. The exec command takes the following arguments:

if

Conditionally execute SSI operations and conditionally print the HTML text. The syntax of the if command is:

<!--#if "op1" operator "op2" operation -->

where:

op1
A string that's the first operand of a logical comparison statement.
op2
A string that's the second operand of a logical comparison statement.
operator
One of == != < > !< !> hasstring
operation
Action to take if the logical comparison evaluates to TRUE, where the possible actions are: break, error, errorbreak, goto, print, and printbreak.

The hasstring operator returns TRUE if the character string in op2 is found in the op1 string.

If both operands are numbers, they're compared as numbers; otherwise, the comparison is based on the alphabetic order of the operands.

If the logical comparison evaluates to FALSE, nothing happens. For example:

<!--#if "5" != "10" goto thislabel -->

The NULL operand is defined by "". NULL may be used to check for the existence of data in a form field.

For example, if you have a form with the field Last name and you want to ensure the user doesn't leave it blank, then the token is:

<!--#if "Last name" == "" printbreak "<P>The Last
 name field cannot be blank; please resubmit the
 form." -->

If the field isn't empty, nothing happens. But if the field is empty, the message is displayed and the HTML document terminates.

goto

Jump to a labeled token (without printing skipped text or applying skipped tokens). The syntax of the goto command is:

<!--#goto ="label_name" -->

where label_name is defined in a subsequent label command on the HTML page.


Note: Remember to put a space before the equal sign.

Here's an example of how the goto and label commands are used together:

<!--#goto ="change_temp" -->
<!--Skip this part of the HTML page. -->
<!--#label ="change_temp" -->
<!--Slinger continues scanning -->
<!--the HTML code here. -->

include

Insert the contents of a file into an HTML page. The include command takes these arguments:

The include command is recursive; each file inserted may contain include tokens.


Note: Although the inserted file can't be a CGI script, it can contain a reference to a CGI script.

label

When Slinger encounters a goto command, jump to the label token on the HTML page. The syntax of the label command is:

<!--#label ="label_name" -->

Note: The maximum length of label_name is 60 characters. Remember to put a space before the equal sign.

For example:

<!--#label ="change_temp" -->

qnxvar

Get data or change data on the data server process. The qnxvar command takes the following arguments:


Note: The maximum length of var_name is 60 characters. Don't omit the space after the var_name.

config commands

cmdecho [ON | OFF]
Set the output option of subsequent exec tokens. The default is OFF, meaning the output isn't parsed or printed. The cmdecho command doesn't apply to the output of CGI scripts.
cmdprefix
Set a prefix to each line output from subsequent exec tokens. The syntax is:
<!--# config cmdprefix="string" -->
      

where string is any character string or HTML format tag.

If cmdecho is set to ON, the output is prefixed with string. Otherwise, the output isn't parsed or printed.

cmdpostfix
Set the string appended to the end of each line output from exec tokens. The syntax is:
<!--# config cmdpostfix="string" -->
      

where string is any character string or HTML format tag.

If cmdecho is set to ON, the output is appended with string. Otherwise, the output isn't parsed or printed.

For example, to make the output of the exec command appear on separate lines:

<!--# config cmdpostfix="<BR>" -->
      
errmsg
Compose an error message and print it when Slinger encounters an SSI error, such as a parsing error or unavailable required data. The syntax is:
<!--# config errmsg="string" -->
      

where string is any character string or HTML format tag. For example:

<!--# config errmsg="<P><CENTER>*ERROR*</CENTER>" -->
      

The error message remains in effect until the next errmsg is configured.

onerr
Set the action to be taken when Slinger encounters an error. The syntax is:
<!--#config onerr="action" -->
      

The possible values of action are:

timefmt
Set the format of the date and time. The syntax is:
<!--#config timefmt ="string" -->
      

where string is compatible with the ANSI C library function, strftime(). The default string is %a %b %d %T %Y.

For example:

<!--#config timefmt ="%A %B %d %Y" -->
      

Ways to achieve dynamic HTML

You can dynamically generate HTML in order to support changing systems. The main components in such a system are:

There are three ways to provide dynamic HTML:

The data server

The data server process, ds, stores global data. External applications can modify or read this global state through the use of the data server API. Slinger can modify or read the global state via the qnxvar SSI command.

Here's a conceptual view of a device monitored and controlled by both an external application and a remote client of Slinger:


Figure showing dataserver example.


Using the data server.


To use dynamic HTML:

  1. Use the SSI tokens to manipulate the HTML page.
  2. Use the qnxvar tokens to query and manipulate the global data.
  3. Write an application to manipulate the global state using the data server library functions. See the examples in the ds utility.

Executing CGI scripts

If you want your CGI script to be executed, then the script must be requested with the URL:

http://hostname/cgi-bin/scriptfile

where:

hostname
Name of the host or the IP address of the host running Slinger.
cgi-bin
Execute the CGI script file specified.
scriptfile
Name of the CGI script to be executed. Slinger uses the environment variable HTTPD_SCRIPTALIAS to locate the pathname of the CGI script file.

When Slinger executes a CGI script, it parses the output of the script for HTTP header directives. Slinger must buffer the header directives, before transmitting the script data, in case a header directive is passed that'll affect the format of the default header directives. Up to 1K of header information can be buffered. CGI scripts must provide a valid header.

Slinger identifies the end of the header as a blank line, lines are terminated with a <LF> or a <CR><LF>. A common HTTP header directive to provide specifies the type of data that the CGI script provides. The default Content-Type is "text/html." For example:

Content-Type: text/html<LF>
<LF>
CGI script data...

Slinger supports the following CGI header directives:

Directive Description Example
Content-Type Type of data being sent back to the client. Content-Type: text/html
Location Reference a file by a URL. Location: http://www.qnx.com
Status Pass a status code and explanation back to the client. If Slinger executes the script successfully, it passes a status of 200 OK (unless the script changes the status). Status: 200 OK

Any other directives are just added to the HTTP header.


Note: A script with the filename prefix nph- (e.g. nph-myscript.cgi) won't be parsed by Slinger; only the raw data from the script is sent. Because Slinger doesn't add any HTTP header content, any script that isn't parsed must provide the entire HTTP header in its script output.

Security precautions

When you choose the directory for your data files:

If you configure Slinger to support CGI:

Don't expose your machine to undue risk. Make sure that:

These precautions prevent somebody from giving your machine a new password file or tampering with your web pages.

Examples:

The right way

We recommend that you put your documents and scripts in separate directories. In this example, the documents are in the /usr/webdoc directory, the root document is foo.html, and the CGI scripts are in /usr/web/cgi:

export HTTPD_ROOT_DIR=/usr/webdoc
export HTTPD_ROOT_DOC=foo.html
export HTTPD_SCRIPTALIAS=/usr/web/cgi
slinger &

The "wrong" way

In this example, anyone can download the scripts because the documents and scripts are in the same directory:

export HTTPD_ROOT_DIR=/usr/web
export HTTPD_ROOT_DOC=foo.html
export HTTPD_SCRIPTALIAS=/usr/web
slinger &

Files:

The slinger webserver requires a TCP/IP stack (e.g. npm-tcpip.so) and the libsocket.so shared libraries.

Environment variables:

Slinger configuration

Slinger uses the following environment variables to set its configuration:

PATH
The pathname of the command interpreter and shell executable command used in the SSI command, exec. For more information, see the exec cmd description.
CMD_INT
The pathname or name of the shell program used to interpret the string passed to the SSI command, exec cmd (e.g. /bin/sh). If the pathname isn't given, Slinger searches the pathname in PATH for the shell program.
HTTPD_ROOT_DIR
The name of the directory where Slinger looks for data files. The default is /usr/local/httpd.
HTTPD_ROOT_DOC
The name of the root document (e.g. index.html). When a web client requests the root document, HTTPD_ROOT_DOC is appended to HTTPD_ROOT_DIR to build the full pathname of the root document. The default is index.html.

For example, let's say HTTPD_ROOT_DOC is defined as index.html and HTTPD_ROOT_DIR is defined as /usr/www. Slinger appends index.html to /usr/www to build /usr/www/index.html.

HTTPD_SCRIPTALIAS
The directory where Slinger looks for the CGI executables.

Note that if you define HTTPD_SCRIPTALIAS, anybody can run scripts or processes that reside in this directory on your machine. Not defining HTTPD_SCRIPTALIAS turns CGI off, causing all CGI requests to fail.

For example, suppose HTTPD_SCRIPTALIAS contains /cgi/bin as the name of the directory. If Slinger gets a request for the resource www.qnx.com/cgi-bin/get_data.cgi/foo, the get_data.cgi script found in /cgi/bin is executed, and foo is sent as pathname information to get_data.cgi. The foo directory is stored in the PATH_INFO environment variable (described below).


Caution: Don't use /bin or /usr/bin as your CGI directory.

Available to CGI scripts

Slinger sets the following environment variables, which can be used by CGI scripts:

ACCEPT_LANGUAGE
The languages that can be read by the remote client.
CONTENT_LENGTH
Length of attached information in the case of a POST.
CONTENT_TYPE
Type of attached information in the case of a POST.
DOCUMENT_ROOT
Location of data files. (Same as HTTP_ROOT_DIR.)
FORWARDED
Name of the proxy server through which the web page is being processed.
FROM
Name of the remote client user.
GATEWAY_INTERFACE
Name and version of the Common Gateway Interface served on Slinger.
HTTP_ACCEPT
MIME types that the client accepts, as given by HTTP headers.
HTTP_USER_AGENT
The browser that the client is using to send requests.
PATH
Pathname of the command interpreter and shell executable command used in the SSI command, exec.
PATH_INFO
Extra path information sent.
PATH_TRANSLATED
Append the pathname in PATH_INFO to the pathname in HTTPD_ROOT_DIR.
QUERY_STRING
Raw query string sent from the remote client.
REFERER
URL of the HTML page that referred the remote client to this web page.
REMOTE_ADDR
IP address of the remote client.
REMOTE_HOST
Hostname of the remote client.
REMOTE_IDENT
Remote username if supporting RFC 931 identification.
REMOTE_PORT
Port of the remote client.
REMOTE_USER
Username used to validate authentication from the remote client.
REQUEST_METHOD
Method by which the current web page was requested (GET or POST).
SCRIPT_NAME
Name of the script being executed.
SERVER_ADMIN
Contact information of the administrator of Slinger specified by Slinger's -a option.
SERVER_NAME
Name of the computer where Slinger is running.
SERVER_PORT
IP port that Slinger is answering on.
SERVER_PROTOCOL
Name and version of HTTP served on Slinger.
SERVER_SOFTWARE
Name of Slinger software.
SERVER_ROOT
Current working directory of Slinger.
TZ
Time zone.

Caveats:

The slinger webserver communicates over TCP sockets, so you need to have socket runtime support. This means you need to have a TCP/IP stack running.

When configuring slinger, take care not to expose your machine to undue risk:

These precautions prevent somebody from giving your machine a new password file, or tampering with your web pages.

If you configure slinger to support CGI, keep the following in mind:

Besides these precautions, you should also keep your documents and scripts in separate areas. This prevents people from either reading or modifying your scripts.

See also:

ds, npm-tcpip.so, npm-ttcpip.so

Setting Up an Embedded Web Server in the Neutrino User's Guide

HTTP://hoohoo.ncsa.uiuc.edu/cgi/

RFC 2068


[Previous] [Contents] [Index] [Next]