AS400 - SBMJOB with command prompter

Posted on 2016-11-02
Last Modified: 2016-11-06
I have tried two options.

Option 1. With passing the cmd value as RSTOBJ ?*RSTLIB(ABCLIB).

 DCL  &CMD          *CHAR  1024                      
 DCL  &CMDLEN       *INT      4   VALUE(1024)        
 DCL  &OPTIONS      *CHAR    20                      
 DCL  &OPTIONSLEN   *INT      4   VALUE(20)          
 DCL  &OPTIONS      *CHAR    20                      
 DCL  &NEWCMD       *CHAR  1024                      
 DCL  &NEWCMDLENA   *INT      4   VALUE(1024)        
 DCL  &NEWCMDLENC   *INT      4   VALUE(1024)        
  CHGVAR  %SST(&OPTIONS  1 4) VALUE(X'00000001')      
  CHGVAR  %SST(&OPTIONS  5 1) VALUE('0')              
  CHGVAR  %SST(&OPTIONS  6 1) VALUE('1')              
  CHGVAR  %SST(&OPTIONS  7 1) VALUE('0')              
  CHGVAR  %SST(&OPTIONS 12 4) VALUE(X'00000000')    
CHGVAR  %SST(&OPTIONS 16 5) VALUE(X'0000000000')

                   'CPOP0100' &NEWCMD &NEWCMDLENA &NEWCMDLENC +
 MONMSG  CPF6801  EXEC(RETURN)                                      
            SBMJOB     CMD(CALL PGM(QCMDEXC) PARM(&NEWCMD +          
                         &NEWCMDLENA)) JOB(RSTOBJ#) JOBQ(QBATCH)

After calling above program, below is the prompt, which only displays "restore to library" parameter. All other input parameters are not displayed.

                             Restore Object (RSTOBJ)                  
 Type choices, press Enter.                                          
 Restore to library . . . . . . . > ABCLIB    Name, *SAVLIB      

Option 2. With passing the cmd value will all parameters.

 DCL  &CMD          *CHAR  1024                          
 DCL  &CMDLEN       *INT      4   VALUE(1024)            
 DCL  &OPTIONS      *CHAR    20                          
 DCL  &OPTIONSLEN   *INT      4   VALUE(20)              
 DCL  &OPTIONS      *CHAR    20                          
 DCL  &NEWCMD       *CHAR  1024                          
 DCL  &NEWCMDLENA   *INT      4   VALUE(1024)            
 DCL  &NEWCMDLENC   *INT      4   VALUE(1024)            
  CHGVAR  %SST(&OPTIONS  1 4) VALUE(X'00000001')        
  CHGVAR  %SST(&OPTIONS  5 1) VALUE('0')                
  CHGVAR  %SST(&OPTIONS  6 1) VALUE('1')                
  CHGVAR  %SST(&OPTIONS  7 1) VALUE('0')                
  CHGVAR  %SST(&OPTIONS 12 4) VALUE(X'00000000')        

CHGVAR  %SST(&OPTIONS 16 5) VALUE(X'0000000000')

CHGVAR  &CMD     VALUE('RSTOBJ            +  
                        ??OBJ()               +  
                        ??SAVLIB()            +  
                        ??DEV()               +  
                        ??OBJTYPE(*FILE)      +  
                        ??VOL()               +  
                        ??SEQNBR()            +  
                        ??POSITION()          +
                        ??LABEL()             +    
                        ??ENDOPT()            +    
                        ??SAVF()              +    
                        ??OPTION(*NEW)        +    
                        ??FILEMBR()           +    
                        ??MBROPT(*NEW)        +    
                        ??SPLFDTA()           +    
                        ??SAVDATE()           +    
                        ??SAVTIME()           +    
                        ??ALWOBJDIF(*ALL)     +    
                        ??FRCOBJCVN()         +    
                        ?*RSTLIB(ABCLIB)      +    
                        ??OUTPUT(*PRINT)      +    
                        ??MEDDFN()            +    
                        ??OPTFILE()           +    
                        ??RSTASPDEV()         +    
                        ??RSTASP()            +    
                        ??OUTFILE()           +  
                       ??OUTMBR()            +    
                       ??INFTYPE()           +    
                       ??OMITLIB()           +    
                    'CPOP0100' &NEWCMD &NEWCMDLENA &NEWCMDLENC +    
 MONMSG  CPF6801  EXEC(RETURN)                                      
            SBMJOB     CMD(CALL PGM(QCMDEXC) PARM(&NEWCMD +          
                         &NEWCMDLENA)) JOB(RSTOBJ#) JOBQ(QBATCH)

For this option2. we get the prompt for all paramters, however, it fails with below error.

Message . . . . :  -CALL PGM(QCMDEXC) PARM('RSTOBJ ??OBJ(F0001)              
  ??POSITION(*N) ??LABEL(*N) ??ENDOPT(*N) ??SAVF(*N) ??OPTION(*NEW)          
  ??OUTMBR(*N) ??INFTYPE(*N) ??OMITLIB(*N) ??OMITOBJ(*N)' 1024)              
   02/11/16  04:40:49.603159  QCANPARS     QSYS        094F     QCMD        QSYS
Message . . . . :   String '          ' contains a character that is not      
Question by:Anand K
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
LVL 35

Expert Comment

by:Gary Patterson
ID: 41871021
Most likely some of the falues you've promted are conditional, and you haven't supplied a value for the parameter that they are based on.

Assuming you want to protect the RSTLIB() parameter, but allow the user to specify any other values, then I suggest you try this:

LVL 27

Accepted Solution

tliotta earned 500 total points
ID: 41875057
There are a couple issues with the procedure.

First the QCAPCMD API can have too many possibilities to work through and understand for someone who's not used it before. If generating a command-string by using selective prompting, I recommend using the QCMDCHK API instead (for now). Far simpler and more straightforward. After all the prompting rules are clear, then learning QCAPCMD is a reasonable step for a more experienced developer. Prompting rules are very different from the rules for the QCAPCMD API interface. Learning both sets of rules at the same time only makes things harder. Focus on one set of concepts at a time.

Those both compound also learning how SBMJOB works, and it has a mistake that's not obvious. (Actually, one mistake plus one probably inappropriate usage.)

The mistake is in using the CMD() parameter. In this case, it shouldn't be specified at all. Leave it empty and unspecified. The parameter that should be used instead is RQSDTA(). And the "probably inappropriate usage" is in specifying CALL QCMDEXC. There's no reason to use QCMDEXC at all here. Just use RQSDTA( &NEWCMD ) and no more.

An explanation of how the CMD() and RQSDTA() parameters are related and why there are two parameters that seem to do almost the same thing is tricky. It goes way back to R1.2 (before OS/400 even had "versions", but only "releases" and "mod levels".

I'll only discuss a small part of it.

Originally, the SBMJOB command didn't have a CMD() parameter. Of the two parameters, only RQSDTA() was there. Every use of SBMJOB that submitted a command had to specify the command-string directly as a "request data" string. This caused numerous problems because many CL programmers couldn't seem to grasp the rules of "quoting" in CL variables. It's necessary to construct a "request data" string completely in program code. When the construction logic requires concatenating multiple string parts together, and some parts may contain quoted strings with embedded quotes (i.e., apostrophes), the embedded quotes need to be doubled up.

This 'doubling' logic still gives trouble for many developers in any number of CL cases. But somewhere around version 2 of OS/400, IBM took care of most SBMJOB issues with it by introducing the CMD() parameter. (Unfortunately, most developers are now no longer aware that RQSDTA() is where the real command is processed when SBMJOB does the work. Most don't know the history nor understand its implications.)

The actual command that gets submitted comes from RQSDTA() and not from the CMD() parameter. If you look at the defaults, you'll see RQSDTA( *CMD ), and the help text gives a small hint. When a command is used as input to CMD(), the system's command analyzer processes it to generate a resulting command-string. That result replaces "*CMD" in RQSDTA() at run-time, and it is what finally gets submitted.

When you build a command-string in a CL variable for SBMJOB, it should go straight into RQSDTA(). The processing to build that string is an alternative to using CMD(). It's not intended to be used in conjunction with CMD().

And that's about as far as I should go with this for now. Try using the QCMDCHK API and SBMJOB RQSDTA( &NEWCMD ) and see how far you can get. If errors still show up, it'll be far easier to deal with them. We might need to continue this thread at that time.

Author Closing Comment

by:Anand K
ID: 41876247
This is the Best explanation i have seen for my question.  Thanks a ton !!

I used the QCMDCHK, this API solved the problem.

Here is my modified code.

 DCL        VAR(&CMD) TYPE(*CHAR) LEN(4024)                        
 DCL        VAR(&CMDLEN) TYPE(*INT) LEN(4) VALUE(1024)              
 DCL        VAR(&OPTIONS) TYPE(*CHAR) LEN(20)                      
 DCL        VAR(&OPTIONSLEN) TYPE(*INT) LEN(4) VALUE(20)            
 DCL        VAR(&OPTIONS) TYPE(*CHAR) LEN(20)                      
 DCL        VAR(&NEWCMD) TYPE(*CHAR) LEN(4024)                      
 DCL        VAR(&NEWCMDLENA) TYPE(*INT) LEN(4) VALUE(4024)          
 DCL        VAR(&NEWCMDLENC) TYPE(*INT) LEN(4) VALUE(4024)          
 CHGVAR     VAR(%SST(&OPTIONS 1 4)) VALUE(X'00000001')              
 CHGVAR     VAR(%SST(&OPTIONS 5 1)) VALUE('0')                      
 CHGVAR     VAR(%SST(&OPTIONS 6 1)) VALUE('1')                      
 CHGVAR     VAR(%SST(&OPTIONS 7 1)) VALUE('0')                      
  CHGVAR     VAR(%SST(&OPTIONS 12 4)) VALUE(X'00000000')            
  CHGVAR     VAR(%SST(&OPTIONS 16 5)) VALUE(X'0000000000')          
      CHGVAR     VAR(&CMD) VALUE('?RSTOBJ OBJTYPE(*FILE) +          
                    OPTION(*NEW) MBROPT(*NEW) ALWOBJDIF(*ALL) +    
                     ?*RSTLIB(RESTORELIB) OUTPUT(*PRINT)')            
          CALL       PGM(QCMDCHK) PARM(&CMD 2000)                    
         MONMSG     MSGID(CPF6801) EXEC(RETURN)                      
      CALL       PGM(QCAPCMD) PARM(&CMD &CMDLEN &OPTIONS +            
                   &OPTIONSLEN 'CPOP0100' &NEWCMD +                  
                   &NEWCMDLENA &NEWCMDLENC X'00000000')              
         MONMSG     MSGID(CPF6801) EXEC(RETURN)                      

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will be converting StringData saved within a text file into a hash table. This can be further used in a PowerShell script for replacing settings that are dynamic in nature from environment to environment.
This article provides a convenient collection of links to Microsoft provided Security Patches for operating systems that have reached their End of Life support cycle. Included operating systems covered by this article are Windows XP,  Windows Server…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…

696 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question