Search code examples
ftpcommand-promptibm-midrangerpglerpg

How to identify and use spooled files of other user using QTCP user(COMMAND PROMPT)?


Here i am connecting to an AS400 machine from command prompt using (FTP Servername) command.
Every action that i do using command prompt is being submitted with QTCP user in the background.

Here is the main concern:

  • I have a command that generates spool file with the name i used to login from command prompt.
  • I want to use that spool file content and copy to one of my library , and all these can be done with CPYSPLF command but how to do the same thing using QTCP user.
  • My main requirement here is to perform CL command operations using command prompt rather than AS400 terminal.

Solution

  • @user2338816 makes a good point about using the QSPRILSP API. But if that doesn't provide what you need, here is how you can use the List Spooled Files (QUSLSPL) API to find it.

    Before beginning, please review my answer from this post: Programming IBM iSeries API QUSLSPL in C# That has a good primer on using the QUSLSPL API and user spaces, although it talks in C#. So here is how you use that API in RPG IV:

    To start with, you need to prototype out the calls to the APIs.

    List Spooled Files

    DQUSLSPL          PR                  EXTPGM('QUSLSPL')    
    D UserSpaceName                       Like(UserSpace) CONST
    D FormatName                     8    CONST                
    D UserName                      10    CONST                
    D QualOutQName                  20    CONST                
    D FormType                      10    CONST                
    D UsrDta                        10    CONST                
    D ErrorCode                           Like(APIError)       
    D QualJobName                   26    CONST                
    D KeyFields                      1    CONST                
    D KeyFieldsNum                  10i 0 CONST                
    D ASP                           10i 0 CONST                
    D JobSystemName                  8    CONST                
    D StartCRDate                    7    CONST                
    D StartCRTime                    6    CONST                
    D EndCRDate                      7    CONST                
    D EndCRTime                      6    CONST                
    

    Create User Space

    DCreateUserSpace  PR                  ExtPgm('QUSCRTUS')   
    D Name                                Like(UserSpace) CONST
    D ExtendedAttrib                10    CONST                
    D InitialSize                   10i 0 CONST                
    D InitialValue                   1    CONST                
    D PublicAuth                    10    CONST                
    D Text                          50    CONST                
    D Replace                       10    CONST                
    D ErrorCode                           Like(APIError)       
    

    Retrieve data from the user space

    DRtvUserSpace     PR                  ExtPgm('QUSRTVUS')   
    D UserSpaceName                       Like(UserSpace) CONST
    D StartingPos                   10i 0 CONST                
    D LengthToReturn                10i 0 CONST                
    D ReceiverVar                         Like(SPLF0300)       
    D ErrorCode                           Like(APIError)       
    

    Delete User Space

    DDeleteUserSpace  PR                  ExtPgm('QUSDLTUS')   
    D Name                                Like(UserSpace) CONST
    D ErrorCode                           Like(APIError)       
    

    I like to make a field to store the user space name so I don't have to keep typing it in:

    DUserSpace        S             20    INZ('SPLFSPACE QTEMP     ')
    

    When calling APIs, you'll need the following API error data structure:

    DAPIError         DS                  Qualified
    D AEBytesProv                   10i 0 Inz(117) 
    D AEBytesAvail                  10i 0 Inz(0)   
    D AEExceptionID                  7             
    D AEReserved                     1             
    D AEExceptData                  80             
    

    Finally, here is a data structure with the information for each spooled file returned:

    DSPLF0300         DS                  Qualified
    D JobName                       10             
    D UserName                      10             
    D JobNumber                      6             
    D SplfName                      10             
    D SplfNumber                    10i 0          
    D SplfStatus                    10i 0          
    D DateCreated                    7             
    D TimeCreated                    6             
    D SplfSchedule                   1             
    D SplfSystemName                10             
    D UserData                      10             
    D FormType                      10             
    D OutQName                      10             
    D OutQLib                       10             
    D ASP                           10i 0          
    D SplfSize                      10i 0          
    D SplfSizeMult                  10i 0          
    D TotalPages                    10i 0          
    D CopiesLeft                    10i 0          
    D Priority                       1             
    D Reserved                       3             
    D Internalppji                  10i 0          
    

    The List Spooled Files API has more parameters than what was needed in that other answer and I used them in the prototype above. Because you can't specify the spooled file name as a parameter to search on, we can specify a creation date and time range to help limit the returned results.

    So the actual coding is simple. You list all spooled files owned by QTCP for, say, the last 5 minutes. Look through the list and see which ones are named QPJOBLOG. Grab the most recent one.

    DCounter          S             10i 0                                     
    DStartPoint       S             10i 0                                     
    DFiveMinutesAgo   S               Z                                       
    DDateStart        S              7                                        
    DTimeStart        S              6                                        
    
    DLastSPLF         DS                  Qualified                           
    D Job                           26                                        
    D SplfName                      10                                        
    D SplfNumber                    10i 0                                     
    D Date                           7                                        
    D Time                           6                                        
    
     /free                                                                    
      FiveMinutesAgo = %TimeStamp()-%Minutes(5);                              
      DateStart=%Char(%Date(FiveMinutesAgo):*CYMD0);                          
      TimeStart=%Char(%Time(FiveMinutesAgo):*HMS0);                           
      CreateUserSpace(UserSpace:*Blank:1:x'00':'*ALL':*Blank:'*YES':APIError);
      QUSLSPL(UserSpace:'SPLF0300':'QTCP':'*ALL':'*ALL':'*ALL':APIError:  
              *Blanks:*Blank:0:0:'*CURRENT':DateStart:TimeStart:'*LAST':      
              *Blanks);                                                       
      RtvUserSpace(UserSpace:1:%Len(ListInfo):ListInfo:APIError);             
      Counter = 0;                                                          
      StartPoint = ListInfo.ListDataOfs+1;                                  
    
      DoW Counter<ListInfo.ListEntryCount;                                  
        RtvUserSpace(UserSpace:StartPoint:%Len(SPLF0300):SPLF0300:APIError);
        If SPLF0300.SplfName='QPJOBLOG' And                                 
           SPLF0300.DateCreated>=LastSplf.Date And                          
           SPLF0300.TimeCreated>=LastSplf.Time;                             
          LastSplf.Job = SPLF0300.JobName +                                 
                         SPLF0300.UserName +                                
                         SPLF0300.JobNumber;                                
          LastSplf.SplfName = SPLF0300.SplfName;                            
          LastSplf.SplfNumber = SPLF0300.SplfNumber;                        
          LastSplf.Date = SPLF0300.DateCreated;                             
          LastSplf.Time = SPLF0300.TimeCreated;                             
        EndIf;                                                              
        StartPoint=StartPoint+ListInfo.EntrySize;                           
        Counter=Counter+1;                                                  
      EndDo;                                                                
    
      DeleteUserSpace(UserSpace:APIError);                                  
    

    My example uses 5 minutes, but that's probably too large of a timespan. Experiment to see what works for you.

    All of this will have to go into a new program that will then return the information needed for the a CPYSPLF command. In fact, you can have this program build and execute a CPYSPLF command for you so your FTP script is simpler.