[Take Control of your OS/2 System]
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 CallType
will 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 */
End
For 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 NFields
After 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 Text
Now 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.


Dr. Dirk Terrell is an astronomer at the University of Florida specializing in interacting binary stars. His hobbies include cave diving, martial arts, painting and writing OS/2 software such as HTML Wizard.

[Index]  [® Previous] - [Feedback] - [Next ¯]

[Our Sponsor: Keller Group Inc. - Developers of FaxWorks for OS/2 and PMfax.]


This page is maintained by Falcon Networking. We welcome your suggestions.

Copyright © 1996 - Falcon Networking