× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.


  • Subject: Missing OS/400 command processing feature
  • From: Greg van Paassen <gregvp@xxxxxxxxxx>
  • Date: Tue, 22 Dec 1998 13:08:20 +1300

Some-one else may find this useful.

Command exccmdlst -- execute a sequence of commands, delimited by ;
(semicolon).

Intended to reduce the number of times one must write and compile a trivial
CL program, or write a REXX procedure.  The VM/CMS monitor had this
capability in 1983. (We won't mention what's possible with UNIX...)

I use it for:  PDM options, e.g.  to send an object from one AS/400 to
another, create a PDM  option SO:  

exccmdlst 'crtsavf qtemp/&n;  savobj &n &l *SAVF &t  savf(qtemp/&n)
updhst(*no)  dtacpr(*YES);  sndnetf qtemp/&n tousrid(( Myself OtherSystem
));  dltf qtemp/&n'

You could set up another PDM option to submit a network job to restore the
object from the save file on the other AS/400.

Also useful for one-off batch jobs:   SBMJOB  CMD( exccmdlst 'ovrdbf
custmast tofile(testcust) ovrscope(*JOB);  call testpgm1; call testpgm2' )

Limitations: Command string limited to 500 characters (easily changed).
Execution stops if one command fails.  Uses command CPYBAKMSGS to return
error messages. No command prompting, but since most programmers use PCs,
"cut and paste" ameliorates this.


source code: command source EXCCMDLST
/*$    DLTOBJ  NAME(*CURLIB/EXCCMDLST )   OBJTYP(*CMD)             */
/*$    CRTCMD  CMD(EXCCMDLST    )       +                          */
/*$            PGM(ZEXCCMDLST)  ALLOW(*ALL)                        */
/*-----------------------------------------------------------------*/
/*  Execute sequence of commands separated by a semicolon.         */
/*  Greg van Paassen,  1995                                        */ 
/*-----------------------------------------------------------------*/

    CMD        PROMPT('Exec list of commands')

    PARM       KWD(CMDS) TYPE(*CHAR)  LEN(500) VARY(*YES *INT2) +
                         CASE(*MIXED) CHOICE('separate commands by ;') +
                         PROMPT('Cmd1; Cmd2 (parms); Cmd3')


Command processing CL program  ZEXCCMDLST:

 /*$  CRTCLPGM ZEXCCMDLST  QCLSRC option(*NOXREF)                     */
 /*  Greg van Passen,  1995                                           */

             PGM        PARM(&LenCmds)

             DCL        &LenCmds   *CHAR    502
             DCL        &Len       *DEC   (  3 0 )
             DCL        &Cmds      *CHAR   500
             DCL        &Cmd       *CHAR   500     /*initial*/ value('*N')
             DCL        &Cmdlen    *DEC   ( 15 5 )
             DCL        &Char      *CHAR     1
             DCL        &Separator *CHAR     1      value(';')
             DCL        &Apost     *CHAR     1      value('''')
             DCL        &Apos      *LGL
             DCL        &Quote     *CHAR     1      value('"')
             DCL        &Quo       *LGL
             DCL        &Start     *Dec   (  3 0 )
             DCL        &I         *Dec   (  3 0 )

             DCL        &MSGID     *CHAR     7
             DCL        &MSGDTA    *CHAR   100
             DCL        &MSGF      *CHAR    10
             DCL        &MSGFLIB   *CHAR    10
             Dcl        &Error     *LGL


             MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))

             Chgvar  &Len   %Bin(&LenCmds 1   2 )
             Chgvar  &Cmds  %sst(&LenCmds 3 500 )

             If ( ( &len = 0 ) | ( &Cmds = ' ' ) ) Return
 Nextcmd:
             Chgvar &Start ( &I + 1 )
             If ( &Start > &len ) goto end
 NextChar:
             Chgvar &I     ( &I + 1 )
             If ( &I > &len ) goto endchar
             Chgvar &Char (%sst(&Cmds &I 1 ))
             If ( &Char = &Apost ) ( chgvar &Apos  (¬&Apos) )
             If ( &Char = &Quote ) ( chgvar &Quo   (¬&Quo) )
             If ( &Char = &Separator )  do
               /*In a string: */ If &Apos goto Nextchar
               /*In a string: */ If &Quo  goto Nextchar
               /*not in a string: */ goto Endchar
             Enddo
             goto Nextchar
endchar:
             If ( &I > &Start ) do
                Chgvar &CmdLen  ( &I - &Start )
                /*NB. the above will exclude the semicolon itself. */
                Chgvar &Cmd   %sst( &Cmds &Start &Cmdlen )
                call qcmdexc  parm(&Cmd &Cmdlen)
             Enddo
             goto Nextcmd

 End:
             RETURN

 ERROR:
             If &Error return
             Chgvar &Error '1'

             RCVMSG  MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF)  +
                     MSGFLIB(&MSGFLIB) msgtype(*EXCP)
             Cpybakmsgs

             IF   (&MSGID *NE '       ') (DO)
                SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
                          MSGDTA(&MSGDTA) msgtype(*ESCAPE)
                MONMSG MSGID(CPF0000)
             ENDDO

             ENDPGM

Command and command-processing program for CPYBAKMSGS:

        /*T: Copy messages on program's message queue back to caller   */
        /*$: CRTCMD CPYBAKMSGS PGM(ZCPYBAKMSG)  ALLOW(*BPGM *IPGM)     */
        /*   Greg van Paassen  1993                        */

        Cmd        Prompt('Copy pgm messages to caller')

----------

/*T: CPYBAKMSGS: copy messages on a program msgq to its caller    */
/*Z: CRTCLPGM ZCPYBAKMSG LOG(*NO)                                 */
/*H: Greg van Paassen,  1993                                      */

 PGM PARM( /* NONE */ +
         )

 DCL     &MSGID      *CHAR      (   7 )
 DCL     &MSGF       *CHAR      (  10 )
 DCL     &MSGFLIB    *CHAR      (  10 )
 DCL     &MSGDTA     *CHAR      ( 256 )
 DCL     &MSG        *CHAR      ( 512 )
 DCL     &Rtntype    *CHAR      (   2 )
 DCL     &Error      *LGL
 DCL     &Sender     *CHAR      (  80 )
 DCL     &Caller     *CHAR      (  10 )
 DCL     &Mstype     *CHAR      (   7 )

/* Message return types: +
|   01  Completion        _    +
|   02  Diagnostic        _    +
|   04  Information            +
|   05  Inquiry           ²    +
|   06  Copy                   +
|   08  Request           n    +
|   10  Request with prompting n +
|   14  Notify           _     +
|   15  Escape           _     +
|   21  Reply, not Vchecked    +
|   22  Reply, checked         +
|   23  Reply, msg dft         +
|   24  Reply, sys dft         +
|   25  Reply, SYSRPYL used    +
|  Notes: _ Only appear on program message queues +
|         ² Only appear on non-program message queues or *EXT +
|         n Must be an impromptu message (ie no msgid) +
*/
  Monmsg CPF0000
  If &Error (goto End_pgm)
  Chgvar &Error '1'
  Getmsg:
   Rcvmsg pgmq(*PRV *)  +
          msgid(&msgid) msgf(&msgf) msgflib(&msgflib) msgdta(&msgdta) +
          msg(&msg)  +
          rtntype(&Rtntype ) +
          sender(&Sender)
   If ( ( &msg = '  ' ) & ( &msgid = '   ' ) )  return
   Chgvar &Caller %SST( &Sender  56  10 )      /*Receiver of the message*/
   If (&Msgid ¬= '   ') do
      Chgvar &mstype '*INFO'
      If ( &Rtntype = '01' ) +
         (Chgvar &mstype '*COMP')
      If ( &Rtntype = '02' ) +
         (Chgvar &mstype '*DIAG')
      If ( &Rtntype = '04' ) +
         (Chgvar &mstype '*INFO')
      If ( &Rtntype = '05' )      /*inquiry*/  +
         (Chgvar &mstype '*INFO')
      If ( &Rtntype = '06' )      /*copy */ +
         (Chgvar &mstype '*INFO')
      If ( &Rtntype = '08' ) +
         (Chgvar &mstype '*RQS')
      If ( &Rtntype = '14' ) +
         (Chgvar &mstype '*NOTIFY')
      If ( &Rtntype = '15' ) +
         (Chgvar &mstype '*DIAG')   /* escape -> diag */
      sndpgmmsg Msgid(&Msgid) msgf(&msgflib/&msgf) msgdta(&msgdta) +
                msgtype(&Mstype)   topgmq(*PRV &Caller)
      Goto Getmsg
      enddo
   Else do
      sndpgmmsg msg(&msg) msgtype(*INFO) topgmq(*PRV &Caller)
      goto Getmsg
   Enddo

End_pgm:    Endpgm


* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This is the RPG/400 Discussion Mailing List!  To submit a new         *
* message, send your mail to "RPG400-L@midrange.com".  To unsubscribe   *
* from this list send email to MAJORDOMO@midrange.com and specify       *
* 'unsubscribe RPG400-L' in the body of your message.  Questions should *
* be directed to the list owner / operator: david@midrange.com          *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.