Fun with QShell

One thing that a lot of people fail to realise is that the IBM i includes a command environment based on POSIX and X/Open standards. This environment is known as QShell and consistes of two parts:

  • The shell interpreter (qsh) reads commands from an input source, interprets each command, and then runs the command using the services of the operating system.
  • The ulilities – external programs that provide additional functions.

You can use the QShell interactively, but the fun begins when you start integrating it with CL.

The below example is used in an interface that retrieves an FTP file from one location, processes it, and then sends the results on to another location. We wanted to retain the FTP logs and, for reasons best left unexamined, the powers that be decreed that these logs should accumulate in a database file. And they should have a timestamp.

Capturing the FTP log is a straightforward case of overriding the Output file to the log file/member. Including a timestamp is where the Qshell fun comes in.

/* Subroutine: Initialise FTPLOG Member                                     */
Subr SrFTPLOG                                                                   
   AddEnvVar EnvVar(QIBM_QSH_CMD_OUTPUT) Value(NONE) Replace(*YES)              
   Clrpfm FTPLOGFILE FTPLOG                                                     

   RtvMbrD File(FTPLOGFILE) Mbr(FTPLOG) RtnLib(&Library)                        
   ChgVar &SessionLib Value('db2 "Create Alias TMPFTPLOG for ' *Cat            + 
                            &Library *TCat '.FTPLOGFILE(FTPLOG)"')              

   RtvSysVal QDATETIME &Timestamp                                               
   ChgVar &SessionTop Value('db2 "Insert into TMPFTPLOG Values(''New Session ' +
                            *Cat %Sst(&Timestamp 1 4) *Cat '-'                 +
                            *Cat %Sst(&Timestamp 5 2) *Cat '-'                 +
                            *Cat %Sst(&Timestamp 7 2) *Cat ' '                 +
                            *Cat %Sst(&Timestamp 9 2) *Cat ':'                 +
                            *Cat %Sst(&Timestamp 11 2) *Cat ':'                +
                            *Cat %Sst(&Timestamp 13 2) *Cat ':'                +
                            *Cat %Sst(&Timestamp 15 6) *Cat ''')"')             
   Qsh Cmd(&SessionLib)                                                         
   Qsh Cmd(&SessionTop)                                                         
   Qsh Cmd('db2 "Drop Alias TMPFTPLOG"')                                         
   RmvEnvVar EnvVar(QIBM_QSH_CMD_OUTPUT)                                        

Member FTPLOG in file FTPLOGFILE is where the FTP logging data will be captured. This member is then copied to the permanent member as decreed by the PHB.

The example should speak for itself but what I am doing is creating an alias to the FTPLOG member, writing a single line to that member with a timestamp retirieved from the DateTime System value, and then dropping the alias.

If you want to get started with QShell, the best approach is to type Strqsh from a command line and then type help.