sascgi sascgi: A SAS - WWW Gatewaysascgi

Version 1.10
Michael Friendly
York University

Introduction

sascgi is a Perl CGI script designed to provide a gateway between a web server and a SAS program which returns results to the web browser. The intention is to provide a relatively uncluttered, general protocol for running SAS on the web, so that the SAS application can be made as simple as possible. The script handles most of the interaction with the web server, making it much easier to write SAS applications to be run on the web.

It works like this. You have a SAS application you want to make accessible to users on the web. That application requires some input from the user, to select records or variables to be processed, or to set parameters for some computation.

You write an HTML form in which the user can enter the required information. When the user presses the SUBMIT button, the browser calls sascgi, passing the parameters defined in the form; sascgi retrieves the parameters, runs SAS, and returns the results to the user.

The script passes input parameters to the SAS program via the environment, which is much easier than trying to parse stdin in SAS. The SAS program is assumed to retrieve these parameters via %sysget(PARAM), or sysget('PARAM') in a data step. The SAS program can return results to the browser by one of three methods:

As of Version 1.10, the output from the program can be embedded in any arbitrary text by defining an OUTPUT_FORM, either in the sascgi script or in an application-specific configuration file.

The SAS program can communicate success or failure (with an error message) by writing a message to a .err file or by returning a message starting with 'ERROR:' to STDOUT. [Not yet implemented]

Examples

Here are a couple examples you can try:

Usage

The script is used in an HTML document by embedding a <form> ... </form> block in the document, referencing this script as the ACTION attribute, as follows:
<form method="POST" 
action="http://your.server.name/cgi-bin/sascgi"> 
   <input type="hidden" name="SASFILE" value="getlist.sas">
   <input type="hidden" name="CONFIG" value="getlist.cfg">
   <input type="hidden" name="TITLE" value="Page title">
   <input type="hidden" name="OUTPUT_METHOD" value="STDOUT|LST|IMAGE">
   <input type="hidden" name="REQUIRE" value="ITEMS LISTS">

	... other form elements ... 
</form>
See the NCSA tutorial for information about fill-out forms. The <input> tags define names of parameters/arguments which are passed to the SAS program (via setenv). Use type="hidden" when you don't want the user to select or change the value; otherwise, you can use any form element which generates a value. Multi-valued arguments (e.g., scrolling lists using <SELECT MULTIPLE>) are formatted as a comma-separated string, surrounded by braces (or as specified by the MULTIVALUE_FORMAT configuration parameter).

Parameters

All query parameters defined in the form are processed by sascgi; however, only those parameters which are given a value in the form (by default, or entered by the user) are placed in the SAS environment. (%sysget() will give a harmless warning if the SAS program references an unset (null) string.)

Note that the names of parameters passed from a form by the server are case-sensitive (e.g., name='SASFILE' rather than name='sasfile'). Use the upcase() function in your SAS program for string comparisons if you want to treat the values of these query parameters as case-insensitive.

Six form parameters have a special meaning to sascgi:

SASFILE | _PROGRAM
The value defines the name of the SAS program to be run. sascgisearches for this file in any of several locations:
  1. A filename starting with a '/' character is searched as an absolute pathname.
  2. A filename starting with '~name/' is searched for in public_html directory of user 'name'.
  3. The configuration block in sascgi can define pathname equivalents for any filename, or a set of one or more directories which are automatically searched.
CONFIG
Defines the name of a configuration file which can override parameters defined in the script itself. If supplied, the configuration file is searched using the same search order used to locate the SASFILE, with the addition of searching in the same directory containing the SASFILE itself.
TITLE
The value is used as a title for the output. Alternatively, the title can be defined in the CONFIG file.
OUTPUT_METHOD
The value tells sascgi how the SAS program intends to return results.
REQUIRE
Specifies a space-separated list of the names of form parameters which must have a value in the input from the form in order for the SAS program to be run. It is generally preferable to provide a default value in the form (e.g., <input type="text" name="ITEMS" value="10">) or to design the SAS program to provide a default.
DEBUG
If non-zero, turns on verbose output for debugging. If DEBUG>1, all environment variables and configuration variables are displayed as well.

Writing your SAS application

Your SAS application should be written to
  1. retrieve any required parameters from the environment, using the %sysget() macro function or the sysget() datastep function.
  2. produce results which are to be returned to the browser according to the OUTPUT_METHOD specified in the form.
  3. Write any error information to a '.err' file in the current directory to signal that an error occurred in the application.

%include files

If your application uses %include statements to include SAS program files, dataset, or macros, you can simplify your applications by defining an autocall library, or by appropriate filename statements in the config.sas file which is used by sascgi. For example, if your config.sas contains
filename macros 
	('~web/sasuser/macros',
	 '~web/sasuser/webmacros');
an application could use
%include macros(htmltab); 
Alternatively, specify the full pathname to the file on the include statement.

Testing your application

You should be able to test your application from the command line by itself, by placing any required parameters in the environment:
	setenv LISTS 1
	setenv ITEMS 20
	sas getlist

sascgi is also designed so that it can be run from the command line for debugging, e.g.,

	setenv DEBUG 1
	./sascgi 'SASFILE=getlist.sas&LISTS=1&ITEMS=20'
or, if you simply invoke sascgi with no parameters, it will prompt for name-value pairs until you type ^D:
  ./sascgi
  (offline mode: enter name=value pairs on standard input)
   LISTS=1
   ITEMS=10
   ^D
The parameters DEBUG, SASFILE, TITLE, and OUTPUT_METHOD may all be passed to this script via the form or the environment.

Limitations

sascgi is designed for situations where an application needs only a relatively small number of user-specified parameters. It does not at present provide the ability for the user to supply an input dataset to be analyzed. (In SAS 6.11, SAS itself can access remote datasets and files using the WWW-based URL method provided by the filename statement.)

Sample Application: Word List Generator

An example of the use of sascgi is this Word List Generator, which selects word lists randomly from a database, subject to restrictions on certain variables describing the properties of each word.

The HTML file contains a form to allow the user to enter the number of words/list and number of lists. The SASFILE and TITLE parameters are entered as hidden input elements, and so are not visible on the form.

<form method="POST" 
action="http://euclid.psych.yorku.ca/cgi/sascgi"> 
	<input type="hidden" name="sasfile" value="getlist.sas">
	<input type="hidden" name="title" value="Word List Generator">

<center>
<table cellpadding=2>
<tr>
<td>Number of Items/list</td>
	<td><input type="text" name="ITEMS" size=4></td>
</tr>

<tr>
<td>Number of Lists</td>
	<td><input type="text" name="LISTS" size=4 value="1"></td>
</tr>
</table>
</center>
Other elements within this form allow the user to select the minimum and maximum values of variables associated with each word, as well as the desired output format (HTML table, or preformatted text). In this application, each variable-selection field is accompanied by a small graphic image, and the fields are formatted as an HTML TABLE.
Enter minimum and/or maximum values to restrict the range of any
variable.  Leave these fields empty to use the entire range.

<center> 
<table cellpadding=2>

<tr>
<th>Variable</th>
<th>Range</th>
<th>Minimum</th>
<th>Maximum</th>
<th>Distribution</th>
</tr>

<tr><td>Number of syllables</td>          <td>1 - 5</td>
	<td><input type="text" name="SYL_MIN" size=5></td>
	<td><input type="text" name="SYL_MAX" size=5></td>
	<td><IMG  WIDTH=224 HEIGHT=107 SRC="paivdens1.gif"></td>
</tr>
	
<tr><td>Number of letters</td>            <td>3 - 14</td>
	<td><input type="text" name="LET_MIN" size=5></td>
	<td><input type="text" name="LET_MAX" size=5></td>
	<td><IMG  WIDTH=224 HEIGHT=106 SRC="paivdens2.gif"></td>
</tr>
	...(more blocks like this) ....
	
</table>

<p>
Output format: <select name="OUTPUT_FORMAT">
	<option value="TABLE"> HTML table
	<option value="PRE"> HTML Text
</select>
<p>

<input type="submit" value="Do it!">
<input type="reset" value="Clear & Retry"> 
<IMG  WIDTH=159 HEIGHT=39 SRC="../../icons/NeXT.gif"alt="[NeXT]"> &
<IMG WIDTH=32 HEIGHT=32 SRC="../../icons/SAShome.gif" alt="[SAS]">
</center>

</form>
Thus, in addition to the (hidden) SASFILE and TITLE parameters, the application-specific parameters passed to sascgi are named LISTS, ITEMS, SYL_MIN, SYL_MAX, LET_MIN, LET_MAX, ... and OUTPUT_FORMAT. The sascgi OUTPUT_METHOD parameter is not specified in the form, and so defaults to STDOUT.

getlist.sas

When the user presses the SUBMIT button, sascgi runs the getlist.sas program. This program retrieves the values of the parameters using the %sysget() macro function:
%let items = %sysget(ITEMS);
%let lists = %sysget(LISTS);
The selection of items from the database is handled by a macro %select (not shown), which is invoked as follows
%select(
	out=sample,
	items=&items,
	lists=&lists,
	let_min=%sysget(LET_MIN),	let_max=%sysget(LET_MAX),
	syl_min=%sysget(SYL_MIN),	syl_max=%sysget(SYL_MAX),
	freq_min=%sysget(FREQ_MIN),	freq_max=%sysget(FREQ_MAX),
	imag_min=%sysget(IMAG_MIN),	imag_max=%sysget(IMAG_MAX),
	conc_min=%sysget(CONC_MIN),	conc_max=%sysget(CONC_MAX),
	mean_min=%sysget(MEAN_MIN),	mean_max=%sysget(MEAN_MAX),
	print=NO
	);	
Note that any parameters which are not specified in the input form are given null values. (The %select macro is designed so that the only required parameter is the number of items.) The items selected are placed in a dataset, SAMPLE. The dataset is printed to STDOUT as either an HTML TABLE or as PREformatted text using the %htmltab macro.
%macro outtab;
   %let outform = %sysget(OUTPUT_FORMAT);
   %if &outform = TABLE %then %let ver=3;
      %else %let ver=2;
   %htmltab(data=sample,out=STDOUT, 
      id=Word, vars=freq imag conc meaning, by=list, 
      caption=Word List, tabid=list, htmlver=&ver, 
      ls=80, tmpfile=getlist);
%mend;
%outtab;

A graphic example

The Word List Distribution example uses sascgi to generate a PostScript or GIF image of the non-parametric density estimate of one of the Paivio Word Pool Variables.

The form allows the user to choose the variable to be displayed (VAR) from a pop-up <SELECT > list, and an optional value for the window-width (bandwidth) parameter of the %density macro. A pop-up list allows the selection of IMAGE/GIF or IMAGE/PS for the OUTPUT_METHOD parameter.

<form method="POST" 
action="http://euclid.psych.yorku.ca/cgi/sascgi"> 
	<input type="hidden" name="SASFILE" value="wwwdens.sas">
	<input type="hidden" name="TITLE" value="Word List Distributions">

<table cellpadding=2>
<tr>
<td>Variable to display:</td>
<td><select name="VAR">
	<option value="FREQ">Word Frequency
	<option value="CONC">Concreteness Rating
	<option value="IMAG">Imagery Rating
	<option value="MEANING">Meaningfulness Rating
	<option value="LET">Number of Letters
</select></td><br>
</tr>
<td>Window Width:</td>
<td>	<input type="text" name="WINDOW" size=6></td>
</tr>

<tr>
<td>Output format:</td> 
<td><select name="OUTPUT_METHOD">
	<option value="image/gif"> GIF image
	<option value="image/ps"> PostScript
</select></td><br>
</tr>
</table>

<p>
<input type="submit" value="Do it!">
<input type="reset" value="Clear & Retry"> 
</form>

wwwdens.sas

wwwdens.sas retrieves the GSASFILE filename of the output PostScript file (GIF translation is handled internally in sascgi), sets device and graph GOPTIONS, and retrieves the name of the plot variable (VAR).
*-- Retrieve specified output file name for the graph;
%let gsasfile =%SYSGET(GSASFILE); 
filename gsasfile  "&gsasfile";

*-- Device options;
goptions device=pscolor gaccess=sasgaedt gsfname=gsasfile 
	gsflen=80 gsfmode=replace gprolog='2521'x;	

*-- Graph options;
goptions vsize=4in hsize=7.5in htext=3 
	ftext=hwpsl009 hpos=120 vpos=100 lfactor=5;

*-- Define the data library;
libname  pools '/Users/friendly/sasuser/pools/';

*-- Retrieve plot variable name;
%let var = %sysget(VAR);
%put Graphing variable = &var;
The graph is produced using the %density and %boxaxis macros (from The SAS System for Statistical Graphics). The WINDOW parameter is passed directly to the %density macro (which provides a default computation if the value is null).
%include macros(boxanno);
%include macros(density);

axis1 label=(a=90 'Density')
		offset=(3,);
pattern1 v=solid c=red;
symbol1 v=none i=join c=black;

%boxaxis(data=pools.paivio, out=boxanno, var=&var, pos=96, boxwidth=5);
%density(data=pools.paivio,
	var=&var,
	out=densplot,
	window=%sysget(WINDOW), 
	vaxis=axis1, haxis=axis2, symbol=symbol1,
	anno=boxanno,  
	plotopt=%str(areas=1));

Installing sascgi

Requirements

You must have the following installed on your system for this gateway to work:
  1. An HTTP (Web) server that supports CGI scripts.
  2. sascgi is a Perl5 script, so you need to have Perl, Version 5.001 or greater installed on your system.
  3. It uses the CGI.pm module by Lincoln Stein (lstein@genome.wi.mit.edu), so you'll need to obtain this, and place it in your perl5 library directory, most commonly /usr/local/lib/perl5.
  4. Of course, you need sascgi as well. Copy it to your http/cgi-bin (or equivalent) directory. Make sure it is executable by your server. You'll need to modify some items in the configuration section of the script, as described below.
  5. For SAS/GRAPH output returned as OUTPUT_METHOD=IMAGE/GIF. I use the pstogif script, obtained from the latex2html package by Nikos Drakos (nikos@cbl.leeds.ac.uk), which in turn uses ghostscript and the netpbm utilities. If you are running SAS Version 6.11 or greater, sascgi can use the IMGGIF device driver directly to produce GIF images.

Create a Server-Writable Directory

When sascgi runs SAS, listing, log, and other files are written in a temporary directory which must be writable by the HTTP userid (usually, user 'nobody').
cd /usr/etc/httpd/htdocs
mkdir tmp
chmod +w tmp

You may want to add a line to your crontab.local to cleanup this directory periodically. I use:

10,30,50 * * * *  root /usr/local/bin/find /usr/local/etc/httpd/htdocs/tmp/ -cmin +10  -exec rm -f {} \;
which runs 3 times/hour to remove all files older than 10 minutes

Modify the Configuration section of sascgi

There are a few configuration options in sascgi that may need to be adjusted for your system. The most important of these is the very top line that reads:
      #!/usr/local/bin/perl
This defines the path to the perl interpreter. Adjust this as necessary and make sure that it points to perl version 5.001 or higher.

Other configuration parameters are at the bottom of sascgi following a line that reads __END__. They define default values for the output form, the name and e-mail address of the application author, and such things as the title of the output page and other output formatting preferences. Any of these values can be changed on the fly in the CONFIG file but you will probably want to set some reasonable defaults here.

The most important of these is the OUTPUT_FORM, which defines a template into which the SAS output is substituted before being returned to the browser. The default value is:

OUTPUT_FORM=
The following output was produced:
<br>
<center>
@OUTPUT@
</center>
View the saslog: @HREF_SASLOG@
.
In the OUTPUT_FORM, '@OUTPUT@' stands for whatever output is produced by the SAS program; '@HREF_SASLOG@' is a link to the SAS log file produced when the program is run.

SAS Tools

%htmltab macro

The htmltab macro is useful for producing an HTML table from a SAS dataset. It supports where-clause observation selection, by-variable processing, HTML Level 2 ( <PRE> ... </PRE>) or Level 3 (<TABLE> ... </TABLE>) styles, and output to a listing, a file, or STDOUT.
Michael Friendly
friendly@yorku.ca
My home page