IBM Support

Example of Using QzshSystem() to Run a Qshell Command in an ILE RPG IV Program

Troubleshooting


Problem

The information in this document will illustrate how to use the QzshSystem() in an ILE RPG IV program.

Resolving The Problem

Caution: This is an example only. IBM accepts no responsibility for its correctness.

Note: To use the QzshSystem() API, you need to first open three temporary files and verify that those files get descriptor numbers 0, 1, and 2 before calling the API. You must close the files before the program ends.

The following is the source for RPG program OPENSTDIO to open the three standard I/O file descriptors stdin (0), stdout (1), and stderr (2).

You should call this program as the first step in your job. If any other activity in the job opens one of these file descriptors incorrectly, this program will fail and your Java or QSHELL call might not work correctly.

Create the ILE RPG program called OPENSTDIO. The following is the ILE RPG IV source code, source member type RPGLE. You can compile it using Option 14 in PDM or by using the CRTBNDRPG command.

The main procedure of the program ends with some rudimentary code to report the error; it uses a DSPLY operation and then it calls the *PSSR subroutine with ENDSR *CANCL which causes an exception to be sent to the program's caller. You may want to replace this code with a better mechanism for reporting the error.


Here is the ILE RPG IV program that will open the three standard I/O file descriptors:
**FREE
Ctl-Opt thread(*serialize) bnddir('QC2LE') dftactgrp(*no);

Dcl-C O_CREAT         x'00000008';
Dcl-C O_TRUNC         x'00000040';
Dcl-C O_RDONLY        x'00000001';
Dcl-C O_WRONLY        x'00000002';
Dcl-C O_RDWR          x'00000004';

Dcl-C O_ACCMODE       %BITOR(O_RDONLY
                    : %BITOR(O_WRONLY
                    : O_RDWR));

Dcl-C S_IRUSR         x'0100';
Dcl-C S_IROTH         x'0004';
Dcl-C S_IWUSR         x'0080';
Dcl-C S_IWOTH         x'0002';

Dcl-Pr chk Ind;
  descriptor      Int(10)         value;
  mode            Int(10)         value;
  aut             Int(10)         value;
  other_valid_mode Int(10)        value;
End-Pr;

Dcl-S ok              Ind;

// Validate or open descriptors 0, 1 and 2
ok = chk (0
        : 0 + O_CREAT + O_TRUNC + O_RDWR
        : 0 + S_IRUSR + S_IROTH
        : 0 + O_RDONLY)
and  chk (1
        : 0 + O_CREAT + O_TRUNC + O_WRONLY
        : 0 + S_IWUSR + S_IWOTH
        : 0 + O_RDWR)
and  chk (2
        : 0 + O_CREAT + O_TRUNC + O_WRONLY
        : 0 + S_IWUSR + S_IWOTH
        : 0 + O_RDWR);

// If the descriptors were not all correct,
// signal an exception to our caller
if not ok;
   // !!! Additional coding required:
   // !!!   At this point, the code should signal an error condition,
   // !!!   or a parameter could be added to return the fact that
   // !!!   this program did not open the descriptors correctly
   // !!! For now, it will use DSPLY and then call the *PSSR ending with
   // !!! *CANCL to signal an exception
   dsply ('Descriptors 0, 1 and 2 not opened successfully.');
   exsr *pssr;
endif;
*inlr = '1';

begsr *pssr;
   // endsr *cancl will signal an exception to the caller
endsr '*CANCL';

Dcl-Proc chk;
  Dcl-Pi chk Ind;
    descriptor      Int(10)         value;
    mode            Int(10)         value;
    aut             Int(10)         value;
    other_valid_mode Int(10)        value;
  End-Pi;

  Dcl-Pr open Int(10) extproc('open');
    filename        Pointer         value options(*string);
    mode            Int(10)         value;
    aut             Int(10)         value;
    unused          Int(10)         value options(*nopass);
  End-Pr;

  Dcl-Pr closeFile Int(10) extproc('close');
    handle          Int(10)         value;
  End-Pr;

  Dcl-Pr fcntl Int(10) extproc('fcntl');
    descriptor      Int(10)         value;
    action          Int(10)         value;
    arg             Int(10)         value options(*nopass);
  End-Pr;

  Dcl-C F_GETFL         x'06';

  Dcl-S flags           Int(10);
  Dcl-S new_desc        Int(10);

  Dcl-S actual_acc      Int(10);
  Dcl-S required_acc    Int(10);
  Dcl-S allowed_acc     Int(10);
   flags = fcntl (descriptor : F_GETFL);
   if flags < 0;
      // no flags returned, attempt to open this descriptor
      new_desc = open ('/dev/null' : mode : aut);
      if new_desc <> descriptor;
         // we didn't get the right descriptor number, so
         // close the one we got and return '0'
         if new_desc >= 0;
            closeFile (new_desc);
         endif;
         return '0';
      endif;
   else;
      // check if the file was opened with the correct
      // access mode
      actual_acc = %bitand (flags : O_ACCMODE);
      required_acc = %bitand (mode : O_ACCMODE);
      allowed_acc = %bitand (other_valid_mode : O_ACCMODE);
      if  actual_acc <> required_acc
      and actual_acc <> allowed_acc;
         return '0';
      endif;
   endif;

   return '1';
End-Proc chk; 
Here is the RPG ILE code to call the API.

Note: You must first compile it as a module using the 15 option in PDM or CRTRPGMOD command. Then you need to issue a CRTPGM command similar to the following:

CRTPGM PGM(libraryname/TEST) MODULE(libraryname/TEST) BNDSRVPGM((QSHELL/QZSHAPI))

You must change the command field. For example, instead of /home/test.txt, you need to put a directory that exists on your system. After running the program, you will have a spooled file named QPRINT which has the same data in it as the /home/test.txt has in it.

Example
**FREE
Ctl-Opt DEBUG(*YES);
Dcl-Pr QzshSystem Int(10) ExtProc('QzshSystem');
  *n              Pointer         value Options(*String);
End-Pr;
Dcl-S Command         Char(44);
Dcl-S rc_qzsh         Int(10);
 Command = 'pr -t ' + '/home/test.txt' + ' | ' +
 'Rfile -wQ qprint';
 rc_qzsh = QzshSystem(Command);
*INLR = '1'; 

   

[{"Type":"MASTER","Line of Business":{"code":"LOB68","label":"Power HW"},"Business Unit":{"code":"BU070","label":"IBM Infrastructure"},"Product":{"code":"SWG60","label":"IBM i"},"ARM Category":[{"code":"a8m0z0000000CHtAAM","label":"Programming ILE Languages"},{"code":"a8m0z0000000CHQAA2","label":"Qshell"}],"ARM Case Number":"","Platform":[{"code":"PF012","label":"IBM i"}],"Version":"All Versions"}]

Historical Number

557008957

Document Information

Modified date:
15 November 2024

UID

nas8N1012360