the REXX Files | - by Dr. Dirk Terrell |
Although Perl is much more frequently used as a Common Gateway Interface (CGI) scripting language, REXX is quite capable in this capacity. Once you do the work to set up a basic template file, you can create CGI scripts very quickly. I use REXX to do a variety of CGI functions such as customer registration and online ordering for a local scuba shop.
If you are running your web server on an OS/2 machine, then REXX is readily available. However if you are running the server on a Unix machine, you'll have to make sure that a REXX interpreter (such as REXX/imc or Regina) is available. It is possible, as we will see, to write a REXX script that will run on both systems with very little effort. With my basic template, I write the CGI scripts on my OS/2 machine, and then transfer them to the Unix server when I am done. The only difference is changing the first line of the file on the Unix machine to have it invoke the REXX interpreter, an unnecessary step on an OS/2 machine, of course.
I will assume that you have a basic understanding of HTML forms, and the ACTION attribute for the SUBMIT button, otherwise I suspect you would have already stopped reading. To use your REXX script, just point the ACTION attribute at your REXX script using either a GET or POST method. In general, it is probably better to use POST to avoid having huge URLs that might run into environment variable limits on the host operating system.
Information is passed to a REXX script via environment variables when it is invoked. The manner in which the environment variables are accessed depends on the host system. Under OS/2 you use the VALUE() function, whereas under Unix you use the GETENV() function. Fortunately, there is a way to determine what the underlying operating system is: PARSE SOURCE. The following call:
Parse Source OperatingSystem CallTypewill place a string in the variable OperatingSystem that identifies the operating system. The values will be either "OS/2" or "UNIX". It is then a simple matter to use a SELECT structure to do the operations necessary for each operating system:
Select When OperatingSystem="OS/2" then Do /* Perform OS/2-specific operations here */ End When OperatingSystem="UNIX" then Do /* Perform Unix-specific operations here */ End Otherwise /* Probably want some error handling code here */ EndFor the remainder of this article, I will assume that our host machine is an OS/2 machine. Consult the example script to see the minor differences for Unix.
The first thing to get is the request method, either POST or GET. This information is passed in the REQUEST_METHOD environment variable. Under OS/2, we would use the VALUE() function like this:
env = "OS2ENVIRONMENT" /* Saves us some typing */ method = value("REQUEST_METHOD",,env) /* either POST or GET */If the method used was GET, then we can get the query string (a string that contains the form information that we presumably want to process) from the QUERY_STRING environment variable with
query_string = value("QUERY_STRING",,env)If the POST method was used, we have to do just a little bit more work. With POST, the query string is passed on the standard input stream. Reading from standard input is easy enough with CHARIN(), but how do we know how many bytes to read? The answer awaits us in an environment variable: CONTENT_LENGTH. Using VALUE() again:
len = value("CONTENT_LENGTH",,env)Then we simply read the specified number of bytes for the query string:
query_string = charin(,,len)Now that we have our query string, we have to decode the information. The string at this point will have the form of Tag1=Value1&Tag2=Value2..., that is, tag names and values separated by equal signs, with tag/value groups separated by ampersands. But REXX is good at parsing strings of this sort. We just parse on the separator characters. First split the query strings at the ampersands to get the tag/value groups and then split the groups at the equal signs to get the tag names and values:
i = 1 do while ((query_string \= '') & (i < 1000)) Parse var quer_string Parms.Group.i '&' rest /* Split groups */ Parse var Parms.Group.i Parms.Tag.i '=' Parms.Value.i /* tag/value parse */ Parms.Tag.i = translate( Parms.Tag.i) Parms.XVal.i=DecodeKeyVal( Parms.Value.i) /* Decode hex codes */ query_string = rest i = i + 1 end NFields = i - 1 return NFieldsAfter executing this code, the stem variable Parms.Tag. will contain the names of the various form elements (i.e., the entry fields, check boxes, etc.) and Parms.XVal. will hold the values of those elements (i.e., the text of the entry field, check status of the checkbox, etc.). The variable NFields holds the number of form elements that were found.
In the above code we call a function DecodeKeyVal() to convert hex codes into characters. With the HTTP protocol, certain characters are transmitted in hex, so we have to convert them back when they are received. The REXX function X2C() (hex to character) does this very nicely. The hex values are separated by percent signs, making for easy parsing. One other thing to note is that spaces are passed as plus signs, and the REXX TRANSLATE() function can be used to convert the plus signs back into spaces. Here is the DecodeKeyVal() function from the example program:
DecodeKeyVal: procedure parse arg Code Text='' Code=translate(Code, ' ', '+') /* Convert + signs to spaces */ rest='%' do while (rest\='') Parse var Code T '%' rest Text=Text || T if (rest\='') then do ch = left( rest,2) c=X2C(ch) /* Hex to character conversion */ Text=Text || c Code=substr( rest, 3) end end return TextNow that you have the element names and values, you can do whatever processing is necessary for your application. Once you are done, you have to send information back to the person that submitted the form via the standard output stream (using SAY). The HTTP protocol requires that you send a line with "Content-type: text/html" followed by a blank line, and then your HTML document. If you don't get these first two lines right, the web browser will most likely report a server error.
The full example program simply returns the form's element names and the associated values. It is quite useful for testing forms as you build them. Use it as a template for creating more complicated scripts and you'll find that creating CGI scripts becomes quite painless.
[Our Sponsor: Keller Group Inc. - Developers of FaxWorks for OS/2 and PMfax.]
Copyright © 1996 - Falcon Networking
This page is maintained by Falcon Networking. We welcome your suggestions.