Stuff
OS/400 Edition
Volume 1, Number 21 -- November 21, 2002

RPG Programs for Qshell


by Ted Holt

[The code for this article is available for download.]

display

To accomplish some feat in Qshell, look for a utility or sequence of utilities that will serve your purpose. If no utility is available, write a Qshell script. If the Qshell language cannot do what you need, write a program in a high-level language. In C, this is easy. But if you hate C as much as I do, and love RPG as much as I do, you'll want to write your program in RPG. This article tells you how.

Requirements

For a program to run under Qshell, it must be able to do four things:

  • Read from the standard input device (stdin)
  • Write to the standard output device (stdout)
  • Write to the standard error device (stderr)
  • Return an exit status to Qshell

That doesn't seem like a lot to ask for, does it?

The C language is built for this sort of work. C has plenty of library functions that do these tasks; scanf, printf, gets, puts, perror, and exit are some of them. RPG has none of that stuff, but it can link to the C library functions. I have played with this method, and it works.

I also wrote some RPG programs that used the QtmhRdStin and QtmhWrStout APIs, which are stored in the QTMHCGI library and are used for CGI programming. That also works.

But then I stumbled upon a short RPG program that was written by Scott Klement, and I knew I'd found what I'd been looking for. Scott used the Unix-type APIs. (Click here to see Scott's code.)

It did my heart good to see those APIs in his code. They are old friends to me, since I started using them to access the IFS from RPG in late 1997.

My Solution

The APIs are slightly messy. Some of the parameters require pointers, which I know how to use but avoid whenever possible. I developed a service program to simplify the programming interface to the APIs. I call my service program stdio. It is built from three source members:

  • QRPGLESRC/STDIO--the service program source code
  • PROTOTYPES/STDIO--the procedure prototypes
  • QSRVSRC/STDIO--the binding language

I have written four subprocedures to handle the I/O and define the exit function. I call my subprocedures stdin, stdout, stderr, and exit. They are easier to use than the APIs. The I/O subprocedures require one variable-length character parameter. I consider that an improvement over the read and write APIs, which require three parameters, one of which is a pointer.

Subprocedure stdin is a function subprocedure; it returns the number of bytes read from the stdin device. The other three subprocedures do not return values.

Here's the service program source code.

This is the procedure prototype.

Here is the binder language.

Place the service program source code in member STDIO of file QRPGLESRC. Place the prototype source code in a source physical file member of your choosing. I use member STDIO of file PROTOTYPES. Place the binder language in member STDIO of file QSRVSRC. The library, of course, is up to you.

An Example

Now you need a program that you can play with, and I have just the thing. This program, which I call EKOR4 (don't ask me why), reads stdin and writes to stdout, reversing the order of words in the process. If, for example, you feed it the sentence "I like cheese," it produces "cheese. like I". If you include a -b option when you call the program, it leaves in all the blanks. If you don't include the -b option, the program leaves only one blank between each word pair.

Running the Example

Once you've compiled everything, you'll want to run the EKOR4 example.

First, make sure you have some test data. I suggest you create an IFS file with text data in it. Anything will do, as long as it has spaces here and there. For this example, I assume your file is mydata.txt. Here's my mydata.txt file:

Reading List                                 
============================================ 
Title                    Author              
============================================ 
Anna Karenina            Leo Tolstoy         
Moby Dick                Herman Melville     
1984                     George Orwell       
Breakfast of Champions   Kurt Vonnegut, Jr.  
The Republic             Plato               

Next, use the qsh command to crank up Qshell. Use the cd command to change to the directory from which you intend to work.

Then call the program. Qshell doesn't use the call command to start a program. Instead, you can type the program's name, in IFS style. If your program object is stored in library MYLIB, type the following:

/qsys.lib/mylib.lib/ekor4.pgm  < /home/mydir/mydata.txt

If all goes well, Qshell lists your file, with the words reversed, on the display:

List Reading                                 
============================================ 
Author Title                                 
============================================ 
Tolstoy Leo Karenina Anna                    
Melville Herman Dick Moby                    
Orwell George 1984                           
Jr. Vonnegut, Kurt Champions of Breakfast    
Plato Republic The                           

Once that is working, run the command with the -b option.

/qsys.lib/mylib.lib/ekor4.pgm  -b  < /home/mydir/mydata.txt

Qshell should respond with something like this:

List Reading                                 
============================================ 
Author                    Title              
============================================ 
Tolstoy Leo            Karenina Anna         
Melville Herman                Dick Moby     
Orwell George                     1984       
Jr. Vonnegut, Kurt   Champions of Breakfast  
Plato             Republic The               

A Better Way to Run the Example

You shouldn't have to type all that /qsys.lib garbage every time you want to run this program. To avoid that, create a symbolic link in the IFS to point to the program object. You can create the link in either of two ways. You can use CL's Add Link (ADDLNK) command or Qshell's ln command.

Let's say you want to refer to the program as reverse. Here's the CL command to create the link:

ADDLNK OBJ('/qsys.lib/tholts.lib/ekor4.pgm') +
   NEWLNK('/home/tholt/reverse') +
   LNKTYPE(*SYMBOLIC) 

Here's the Qshell command:

ln -s /qsys.lib/tholts.lib/ekor4.pgm reverse

Now use the symbolic link to run the program within Qshell:

reverse < /home/mydir/mydata

Empowered

Now you are empowered to write RPG programs to enhance Qshell. I use a good bit of PC software, and I often feel frustrated because I can't modify the way the program works or add a nifty feature. I like to write programs to make the computer do what I want it to do, rather than "make do" with what someone else has decided I needed. So I was glad to find a way to write programs to overcome Qshell's limitations.

I hope that the ability to write RPG programs to run in Qshell excites you as much as it does me. I am just getting started. I will continue to work on the stdio service program, and I have several more projects in mind to tackle as soon as I can find the time.

Be aware that these programs are new and I haven't used them in production yet. Use them at your own risk. If you find bugs or have suggestions for improvement, please email me at tholt@itjungle.com.


Sponsored By
PROFOUND LOGIC SOFTWARE

Don't be left behind!

Thousands of programmers have adopted RPG-Alive, and are now able to read and understand RPG code 2 to 3 times faster.

To try RPG-Alive on your system, visit http://www.RPGAlive.com/now

"I am very happy with RPG-Alive! It's a terrific productivity booster!" says Brian Johnson of Help/Systems.

See other user testimonials at http://www.rpgalive.com/testimonials.html


THIS ISSUE
SPONSORED BY:

ASNA
Teamstudio
Profound Logic Software
WorksRight Software


BACK ISSUES

TABLE OF
CONTENTS
AS/400 Reports On The Fly, From Any Database

Data Is Served: A VARPG Data Server

RPG Programs for Qshell

Back to Basics: Homegrown OS/400 Commands


Editors
Shannon O'Donnell
Kevin Vandever

Managing Editor
Shannon Pastore

Contributing Editors:
Howard Arner
Joe Hertvik
Ted Holt
David Morris
Richard Shaler

Publisher and
Advertising Director:

Jenny Thomas

Advertising Sales Representative
Kim Reed

Contact the Editors
Do you have a gripe, inside dope or an opinion?
Email the editors:
editors@itjungle.com



Last Updated: 11/21/02
Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.