API QREXQ

Pulling and Pushing to the REXX Queue

A REXX queue is similar to a data queue, except that a REXX queue is associated with a job, not job independent. Using the QREXQ API a developer can store information for use at any time during the job process. The REXX external data queue provides a way to temporarily hold data which REXX, and any application programs with the proper interface, can use. The data on the queue is accessible by and visible to a user job as lines or as buffers. A buffer is a sub-grouping of lines within a queue, and lines are character strings of arbitrary lengths. Each line can contain up to 32,767 characters. Pulling and entry from the queue is simple. Just set the function to 'P' (pull from queue). If the return code (rCode) is zero, an entry was pulled from the queue.

Pulling Data from the REXX Queue

This is example is an illustration of using the REXX Queue. In this instance, the REXX queue has been loaded by a previous program on the invocation stack. This program reads the queue for the file list that was loaded into the queue.

       ctl-Opt DEBUG(*YES) OPTION(*SRCSTMT : *NODEBUGIO)
          DFTACTGRP(*NO) ACTGRP('CSGXMT') Main(CSG020RP) EXTBININT(*YES)
          BNDDIR('QC2LE') ;

      ****************************************************************
      * PROGRAM NAME - CSG020RP                                      *
      *                                                              *
      * FUNCTION     - Read IFS entries from REXXQ                   *
      *                                                              *
      * PROGRAMMER   - Steve Croy        06/21/17                    *
      ****************************************************************
      ****************************************************************
      *                   MODIFICATION LOG                           *
      *                                                              *
      *   DATE    PROGRAMMER      DESCRIPTION                        *
      *                                                              *
      ****************************************************************

      *-------------------------------------------------------------------
      * Procedure prototypes
      *--------------------------------------------------------------------
       Dcl-PR PullFromQueue   EXTPGM('QREXQ') ;
        FUNT                  char(1)         ;
        BUF                   char(200)       ;
        BUFLEN                int(10)         ;
        FLAG                  int(5)          ;
        RCODE                 int(5)          ;
       End-PR                                 ;

      *--------------------------------------------------------------------
      * Data Structures
      *--------------------------------------------------------------------

       Dcl-DS BFLDS                      ;
         BUFLEN              int(10)     ;
         FLAG                int(5)      ;
         RCODE               int(5)      ;
       End-DS                            ;

      *---------------------------------------------------------------------
      * Global Variables
      *---------------------------------------------------------------------

       Dcl-S BUF             char(200)                        ;
       Dcl-S FUNT            char(1)                          ;


       Dcl-Proc CSG020RP                                       ;

         Dcl-PI CSG020RP             extPgm('CSG020RP')        ;
           p$Path            char(200)                         ;
         END-PI                                                ;

        //*------------------------------------------------------------------
        //* Pull from REXX Queue
        //*------------------------------------------------------------------

          p$path = *blank                                      ;
          Clear BFLDS                                          ;
          buf = *blank                                         ;
          funt = 'P'                                           ;
          buflen = 256                                         ;

          PullFromQueue ( funt : buf : buflen : flag : rCode ) ; // Get Queue

          IF rCode = 0                                         ; // No error
             p$path = %trim(buf)                               ; // File name
          ELSE                                                 ; // Else signal
             p$path = '*****'                                  ; // End of list
          ENDIF                                                ;

          RETURN                                               ;

       End-Proc CSG020RP                                       ; 


Loading Data to the REXX Queue

Here is the code that loaded the information to the REXX queue in the first place. The program reads a directory, and the name of each file in the directory will be pushed to the queue with the QREXQ API. It is a simple and fast method of passing a subset of data from one program to another, without writing and reading a database file.

       ctl-Opt DEBUG(*YES) OPTION(*SRCSTMT : *NODEBUGIO)
          DFTACTGRP(*NO) ACTGRP('CSGXMT') Main(CSG010RP) EXTBININT(*YES)
          BNDDIR('QC2LE') ;

      ****************************************************************
      * PROGRAM NAME - CSG010RP                                      *
      *                                                              *
      * FUNCTION     - Read IFS folder and push to REXQ              *
      *                                                              *
      * PROGRAMMER   - Steve Croy        06/21/17                    *
      ****************************************************************

      *-------------------------------------------------------------------
      * Procedure prototypes
      *--------------------------------------------------------------------

       Dcl-PR PushToQueue     EXTPGM('QREXQ') ;
        FUNT                  char(1)         ;
        BUF                   char(200)       ;
        BUFLEN                int(10)         ;
        FLAG                  int(5)          ;
        RCODE                 int(5)          ;
       End-PR                                 ;

       Dcl-PR opendir         pointer EXTPROC('opendir')  ;
          dirname             pointer VALUE               ;
       End-PR                                             ;

       Dcl-PR closedir        int(10) EXTPROC('closedir') ;
          dirname             pointer VALUE               ;
       End-PR                                             ;

       Dcl-PR readdir         pointer EXTPROC('readdir')  ;
          dirp                pointer VALUE               ;
       End-PR                                             ;

       Dcl-PR stat            int(10) EXTPROC('stat')     ; // Retrieve status information
          dirp                pointer VALUE               ;
          buffer              pointer VALUE               ;
       End-PR                                             ;

       Dcl-PR chdir           int(10) EXTPROC('chdir')    ; // Change current directory
          dirp                pointer Value               ;
       End-PR                                             ;

       Dcl-PR strerror        pointer EXTPROC('strerror') ; // Retrieve run error message
          errnum              int(10)                     ;
       End-PR                                             ;

      *--------------------------------------------------------------------
      * Data Structures
      *--------------------------------------------------------------------

       Dcl-DS BFLDS                      ;
         BUFLEN              int(10)     ;
         FLAG                int(5)      ;
         RCODE               int(5)      ;
       End-DS                            ;

       Dcl-DS dirent                 based(p_dirent) ALIGN ;
         d_reserv1           char(16)                      ;
         d_fileno_gen        uns(10)                       ;
         d_fileno            uns(10)                       ;
         d_reclen            uns(10)                       ;
         d_reserv3           int(10)                       ;
         d_reserv4           char(8)                       ;
         d_nlsinfo           char(12)                      ;
           nls_ccsid         int(10) OVERLAY(d_nlsinfo:1)  ;
           nls_cntry         char(2) OVERLAY(d_nlsinfo:5)  ;
           nls_lang          char(3) OVERLAY(d_nlsinfo:7)  ;
           nls_reserv        char(3) OVERLAY(d_nlsinfo:10) ;
         d_namelen           uns(10)                       ;
         d_name              char(640)                     ;
       End-DS dirent                                       ;

      * Data structure for Stat()...

       Dcl-DS  statds                BASED(p_stat) ALIGN   ;
         st_mode              uns(10)                      ;
         st_ino               uns(10)                      ;
         st_nlink             uns(5)                       ;
         st_uid               uns(10)                      ;
         st_gid               uns(10)                      ;
         st_size              int(10)                      ;
         st_atime             int(10)                      ;
         st_mtime             int(10)                      ;
         st_ctime             int(10)                      ;
         st_dev               uns(10)                      ;
         st_blksize           uns(10)                      ;
         st_allocsize         uns(10)                      ;
         st_objtype           char(11)                     ;
         st_codepage          uns(5)                       ;
         st_reserved          char(62)                     ;
         st_ino_gen_i         uns(10)                      ;
       End-DS statds                                       ;


      *-----------------------------------------------------------------
      * Global Constants
      *-----------------------------------------------------------------

       Dcl-C decalage         const(18000)                 ;
       Dcl-C #ROOT            '/'                          ;
       Dcl-C #UP              'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
       Dcl-C #LO              'abcdefghijklmnopqrstuvwxyz' ;

      *-----------------------------------------------------------------
      * Global Variables
      *-----------------------------------------------------------------

       Dcl-S  errno          int(10)                       ;
       Dcl-S  error_p        pointer                       ;
       Dcl-S  errmsg         char(80)                      ;
       Dcl-s p_dirent        pointer                       ;
       Dcl-S p_stat          pointer                       ;
       Dcl-S dh              pointer                       ;
       Dcl-S p$Path          char(256)                     ;
       Dcl-S Name            char(256)                     ;
       Dcl-S rc              int(10)                       ;

       Dcl-S w$inam          char(256)                     ;
       Dcl-S w$pos           zoned(3:0)                    ;
       Dcl-S w$len           zoned(3:0)                    ;
       Dcl-s w$path          LIKE(p$path : +1 )            ;
       Dcl-s tpath           LIKE(p$path : +1 )            ;
       Dcl-S tFile           char(128)                     ;

       Dcl-S w$date          zoned(8:0)                    ;
       Dcl-S C$date          Date   inz                    ;
       Dcl-S M$date          Date   inz                    ;
       Dcl-S x$date          Date                          ;
       Dcl-S epochv          char(26) INZ('1970-01-01-00.00.00.000000') ;

       Dcl-S BUF             char(256)                     ;
       Dcl-S FUNT            char(1)                       ;
       Dcl-S CloseError      int(10)                       ;

       Dcl-Proc CSG010RP ;

         Dcl-PI CSG010RP             extPgm('CSG010RP')        ;
           pathIN            char(200) CONST options(*NOPASS)  ;
         END-PI;

        //*------------------------------------------------------------------
        //* Set the path statement
        //*------------------------------------------------------------------

         If %parms < 1     ;
           p$path = '/'    ;
         Else              ;
           p$path = pathIn ;
         ENDIF             ;

         IF p$path = *BLANKS;
            p$path = '/';
         ENDIF;

         IF %subst(%trim(p$path):1:1) <> '/';
            p$path = '/' + %trim(p$path);
         ENDIF;
         w$path = p$path;
         w$len = %len(%trim(p$path));
         IF %subst(p$path:w$len:1) <> '/';
            p$path = %trim(p$path) + '/';
         ENDIF;

         p_stat = %alloc(512);
         w$path = %trim(w$path) + x'00';

        //*------------------------------------------------------------------
        //* Open Specified Directory. If not found exit the program.
        //* Read Each Directory Entry...
        //*------------------------------------------------------------------

         dh = opendir(%addr(w$path));

         IF dh <> *NULL;

            DOU p_dirent = *NULL;
               p_dirent = readdir(dh);
               IF p_dirent <> *NULL;

            //*------------------------------------------------------------------
            //* Push to REXX Queue
            //*------------------------------------------------------------------

                  IF d_namelen < 1024;
                     Name = %subst(d_name: 1: d_namelen);
                     IF %trim(name) <> '.'
                        and %trim(name) <> '..'
                        and name <> *blanks ;
                        w$inam = name;
                     //* get object status
                       buf = %trim(p$path) + %trim(Name);
                       tpath = %trim(p$path) + %trim(Name) + x'00';
                       rc = stat(%addr(tpath):p_stat);

                       funt   = 'A';
                       buflen = 256;
                       flag   = 1;
                       rcode  = 0;

                       PushToQueue (funt : buf : buflen : flag : rcode ) ;

                     ENDIF;
                  ENDIF;
               ENDIF;
            ENDDO;

            error_p = strerror(errno);
            errmsg  = %str(error_p);

         ENDIF;

         CloseError = closedir(dh);

         RETURN;

       END-PROC; 

The programs, CSG010RP and CSG020RP reference the REXX queue. CSG010RP is used to read the files in a specified directory and push the name of the file onto the REXX queue. CSG020RP will read the entries from the REXXQ and pass the name of the file to a CL program for action on the individual file, i.e. rename, or move the file from the directory.