How to Handle Null-Terminated Strings in CL

Article ID: 19284

Q: I'm trying to use the following command, but I'm having trouble:

    STRQSH CMD('find /path/to/files -name *.csv +
           -exec /qsys.lib/mylib.lib/mypgm.pgm {} \;')

The CL program is receiving a null-terminated path name. The null character causes errors, and some of the characters after it look like "garbage." How do I handle this?

A: There are two ways to handle this.

The first way is to search for the null-terminator and make a copy of the filename without it. It's important that the result be placed in a new variable. You should never change a parameter that you received from QShell.

The following program demonstrates this technique:

PGM    PARM(&PARM)

      DCL VAR(&PARM) TYPE(*CHAR) LEN(1000)
      DCL VAR(&FILE) TYPE(*CHAR) LEN(1000)
      DCL VAR(&X00)  TYPE(*CHAR) LEN(1) VALUE(X'00')
      DCL VAR(&POS)  TYPE(*DEC) LEN(4) VALUE(1)

/* FIND NULL-TERMINATOR */

LOOP:  IF (%SST(&PARM &POS 1) *NE &X00) DO
          CHGVAR VAR(&POS) VALUE(&POS + 1)
          GOTO LOOP
      ENDDO

/* MAKE A COPY WITHOUT THE NULL-TERMINATOR */

      CHGVAR VAR(&POS) VALUE(&POS - 1)
      CHGVAR VAR(&FILE) VALUE(%SST(&PARM 1 &POS))

/* RUN A COMMAND ON THIS FILENAME */

      CPYFRMIMPF FROMSTMF(&FILE) TOFILE(YOURFILE)

ENDPGM

That program should work well with the FIND command that you sent me; However, it will not be as fast as it could be.

You see, for each file that QShell finds, it'll submit a new job to batch to run the CL program on that file and will then wait until that batch job ends. This requires a lot of extra work for the computer, so it takes longer.

A faster way is to have QShell write the files that it finds into a physical file and then read that physical file in your CL program to do the CPYFRMSTMF. The following program demonstrates doing it that way:

PGM

      DCL VAR(&JOBNBR)   TYPE(*CHAR) LEN(6)
      DCL VAR(&LIB)      TYPE(*CHAR) LEN(10) VALUE('MYLIB')
      DCL VAR(&TEMPNAME) TYPE(*CHAR) LEN(10)
      DCL VAR(&EOF)      TYPE(*LGL)          VALUE('0')
      DCL VAR(&CMD)      TYPE(*CHAR) LEN(200)
      DCLF FILE(FILELIST)
/* CREATE A TEMPORARY FILE TO RECEIVE FILENAMES INTO */
/*  NOTE: QSHELL CANNOT ACCESS QTEMP!  */

      RTVJOBA NBR(&JOBNBR)
      CHGVAR VAR(&TEMPNAME) VALUE('TEMP' *CAT &JOBNBR)

      DLTF FILE(&LIB/&TEMPNAME)
      MONMSG CPF2105

      CRTPF FILE(&LIB/&TEMPNAME) RCDLEN(1000) LVLCHK(*NO)
/* TELL QSHELL TO WRITE FILENAMES TO THE TEMP FILE */
/*  Replace '/path/to/files' with the location of the files in */
/*  your IFS!     */

      CHGVAR VAR(&CMD) VALUE('find /path/to/files -name *.csv > +
                       /qsys.lib/' *CAT &LIB *TCAT '.lib/' +
                       *CAT &TEMPNAME *TCAT '.file/' +
                       *CAT &TEMPNAME *TCAT '.mbr')

      STRQSH CMD(&CMD)
/* READ FILENAMES FROM TEMP FILE */

      OVRDBF FILE(FILELIST) TOFILE(&LIB/&TEMPNAME)

LOOP:  RCVF
      MONMSG MSGID(CPF0864) EXEC(CHGVAR &EOF VALUE('1'))
      IF (&EOF *EQ '0') DO
          CPYFRMIMPF FROMSTMF(&FILELIST) TOFILE(YOURFILE)
          GOTO LOOP
      ENDDO

      DLTF FILE(&LIB/&TEMPNAME)

ENDPGM

ProVIP Sponsors

ProVIP Sponsors