问题
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.
回答1:
@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.
回答2:
There's still no example for the Retrieve Identity of Last Spooled File Created (QSPRILSP) API, so I'll add one. Compile something like this:
pgm ( +
&pSplFName +
&pJobName +
&pUserName +
&pJobNbr +
&pSplFNbr +
)
dcl &pSplFName *char 10
dcl &pJobName *char 10
dcl &pUserName *char 10
dcl &pJobNbr *char 6
dcl &pSplFNbr *int
dcl &szRcvVar *int value( 70 )
dcl &errCod *char 128
dcl &errRtn *int stg( *defined ) defvar( &errCod 1 )
dcl &errAvl *int stg( *defined ) defvar( &errCod 5 )
dcl &errMsgID *char 7 stg( *defined ) defvar( &errCod 9 )
dcl &errMsgDta *char 80 stg( *defined ) defvar( &errCod 17 )
dcl &fSPRL0100 *char 70
dcl &bytRtn *int stg( *defined ) defvar( &fSPRL0100 1 )
dcl &bytAvl *int stg( *defined ) defvar( &fSPRL0100 5 )
dcl &splFName *char 10 stg( *defined ) defvar( &fSPRL0100 9 )
dcl &jobName *char 10 stg( *defined ) defvar( &fSPRL0100 19 )
dcl &userName *char 10 stg( *defined ) defvar( &fSPRL0100 29 )
dcl &jobNbr *char 6 stg( *defined ) defvar( &fSPRL0100 39 )
dcl &splFNbr *int stg( *defined ) defvar( &fSPRL0100 45 )
dcl &jobSysName *char 8 stg( *defined ) defvar( &fSPRL0100 49 )
dcl &splFCrtDat *char 7 stg( *defined ) defvar( &fSPRL0100 57 )
dcl &rsv01 *char 1 stg( *defined ) defvar( &fSPRL0100 64 )
dcl &splFCrtTim *char 6 stg( *defined ) defvar( &fSPRL0100 65 )
call QSPRILSP ( +
&fSPRL0100 +
&szRcvVar +
'SPRL0100' +
&errCod +
)
chgvar &pSplFName &splFName
chgvar &pJobName &jobName
chgvar &pUserName &userName
chgvar &pJobNbr &jobNbr
chgvar &pSplFNbr &splFNbr
return
endpgm
And in your CL, call it something like this:
pgm ( +
)
dcl &splFName *char 10
dcl &jobName *char 10
dcl &userName *char 10
dcl &jobNbr *char 6
dcl &splFNbr *int
dspmsgd CPF9898 output( *PRINT )
call @@TSTSPL ( +
&splFName +
&jobName +
&userName +
&jobNbr +
&splFNbr +
)
sndpgmmsg msgid( CPF9897 ) msgf( QSYS/QCPFMSG ) +
msgdta( &splFName *bcat &jobName *bcat &jobNbr ) +
topgmq( *EXT ) +
msgtype( *INFO )
return
endpgm
Instead of @@TSTSPL, give the new program a meaningful name. That second set of example code can be compiled and you can call it in a FTP session to test if it calls the API example and returns the correct identifying info. (The SNDPGMMSG command simply puts a message into the FTP server joblog; you won't need it in your CL.)
If you run WRKOBJLCK against your user profile before you QUIT the FTP session, you can check the joblog to see if the message shows up. You can use the message to learn the job number of the your QPRTJOB job to verify that the spooled file from the example DSPMSGD command shows up there. It should be the most recent spooled file in that job. It should also be the most recent spooled file in a WRKSPLF list; and if you display its attributes, you should see the QPRTJOB name.
回答3:
This code snipit copies the last spoolfile created to qtemp and then to a stream file. &file is the name of the spoolfile 'QPRINT' for example. &TOSMF is the name of the stream file. I use this code all the time to send reports as email attachments.
/* delete the ifs file this is a good check for authority */
/* if the object can't be deleted you probably can't replace it */
RMVLNK OBJLNK(&TOSTMF)
MONMSG MSGID(CPFA0A9) /*object not found */
/* make sure the spool file exists by holding it */
/* cpf returns to caller if the spool file doesn't exist */
HLDSPLF FILE(&FILE) SPLNBR(*LAST)
MONMSG MSGID(CPF3337) /*already held */
DLTF FILE(QTEMP/QSPOOL)
MONMSG MSGID(CPF2105) /*object not found */
CRTPF FILE(QTEMP/QSPOOL) RCDLEN(132)
CPYSPLF FILE(&FILE) TOFILE(QTEMP/QSPOOL) SPLNBR(*LAST)
CPYTOSTMF +
FROMMBR('/qsys.lib/qtemp.lib/qspool.file/qsp+
ool.mbr') TOSTMF(&TOSTMF) +
STMFOPT(*REPLACE) STMFCCSID(*PCASCII)
来源:https://stackoverflow.com/questions/40757520/how-to-identify-and-use-spooled-files-of-other-user-using-qtcp-usercommand-prom