In order for RPG to be able to call an application on a remote computer, you need to be able to do three things:
- Identify the IP address of a computer from within an RPG program
- Allow commands to be executed on the remote computer
- Call the remote application from within an RPG program
In this article, I'll tell you how to achieve the first requirement.
Identifying the Network Location of the RPG User
For an RPG program to execute an application on a remote computer, it must first know the location of the target computer on the network.
To retrieve the IP address of the user associated with the current job, you can use the Retrieve Device Description (QDCRDEVD) API, whose parameters are shown in the table below.
The QDCRDEVD API Parameters
| ||
Parameters | Input/Output | Type |
Receiver Variable | Output | Char(*) |
Length of Receiver Variable | Input | Binary(4) |
Format Name | Input | Char(8) |
Device Name | Input | Char(10) |
Error Code | Input/Output | Char(*) |
- The Receiver Variable is where the information will be returned for the device.
- The Length of Receiver Variable indicates the length of the first parameter, Receiver Variable.
- The Format Name determines the type of information to be returned. The Format Name will identify the contents of the Receiver Variable output.
- The Device Name is the name of the device of interest.
- The Error Code is standard error code.
The QDCRDEVD API is used to retrieve information about a device description. In our case, we will be retrieving the currently active IP address of the device description in use. But you could also pass in the workstation name of another job to retrieve the IP address of that job.
D**********************************************************************
D* RETRIEVE THE IP ADDRESS OF THE JOB (Free Format)
D**********************************************************************
D SDS
D thisJob 244 253
D PROTO_IP C CONST(X'02')
D PROTO_IPX C CONST(X'06')
D PROTO_SNA C CONST(X'40')
D**********************************************************************
D* QUSEC IS THE COMMON ERROR CODE PARAMETER PROVIDED BY IBM
D/COPY QSYSINC/QRPGLESRC,QUSEC
D stdError DS qualified
D QUSEC likeDs(QUSEC)
D outError 1024
D**********************************************************************
D* QDCD060000 defines the fixed portion of the DEVD0600 format.
D/COPY QSYSINC/QRPGLESRC,QDCRDEVD
D*
D displayString S 52A
D*
D GetDeviceDescription...
D PR ExtPgm('QDCRDEVD')
D outReceiver 972A Const
D inLength 10I 0 Const
D inFormat 8A Const
D inDeviceName 10A Const
D ioErrorCode 1040A Const
D*
/free
//
// Set the length of the expected error code
// This will prevent a potentially large return value
stdError.QUSEC.QUSBPRV = 1040;
//
// Use 'DEVD0600' format for *DSP Description
GetDeviceDescription(QDCD060000:972:'DEVD0600':thisJob:stdError);
if stdError.QUSEC.QUSBAVL > 0;
if stdError.QUSEC.QUSEI = 'CPF2702';
displayString = 'Unknown Device: ' + thisJob;
else;
displayString = 'QDCRDEVD Error: ' + stdError.QUSEC.QUSEI;
endif;
else;
select;
when QDCNP = PROTO_IP;
displayString = 'IP Device:' + thisJob
+ ' IP:' + QDCIPADF;
when QDCNP = PROTO_IPX;
displayString = 'IPX Device:' + thisJob
+ ' IP:' + QDCIPADF;
other;
// Identified X'40', but use SNA as catch all
displayString = 'SNA Device:' + thisJob
+ ' CTL:' + %trim(QDCANSCN02)
+ ' Switch:' + %trim(%editc(QDCSS:'3'))
+ ' Port:' + %trim(%editc(QDCDP:'3'));
endsl;
endif;
DSPLY displayString;
*inlr = *ON;
/end-free
As you can see, I am testing the waters by switching my coding style over to free-format with a few other extras thrown in. I always try to provide the code in a manner that will be usable by the widest audience, so if this code is not comprehensive for you, please post a comment and I will provide the code in the classic fixed-format style.
I don't wish to stray too far from the primary objective of this article, but I do not feel as though I could drastically change my coding style without attempting to fill in the gaps on some of the coding changes. So allow me to briefly explain a few points that I believe may be of interest: qualified data structures, nested data structures, and the procedure name with the ellipses (...).
Qualified and Nested Data Structures
When you use the "qualified" keyword on the data structure (DS) declaration, you are indicating that the variable names referenced in the data structure need to be qualified when referenced within the program, meaning that you need to specify the data structure name prior to the variable name contained within the data structure. So, to access the outError variable within the data structure, I need to refer to it as stdError.outError.
You may be asking yourself, "Why do that?" My reason in this particular instance is because I wanted to use the standard error data structure QUSEC that is provided by IBM, but I also wanted to add the outError field to receive the error code results.
I could have copied and pasted the QUSEC source code into this source code and added the new outError field after the QUSEC fields. But if IBM changes the data structure by adding a new field, I'll need to change all of my programs that are using it. So I opted to use the likeDS keyword to create a data structure within the data structure. This way, my new outError field will be grouped with the QUSEC data structure to produce the desired results.
When you use the likeDS keyword to define a nested data structure, it is required to qualify the data structure that it is contained within. As my brother Mark, the plumber, always says, "Work smarter, not harder."
Procedure Name with the Ellipses
This is an easy one. The prototype is being defined in the fixed-formatted section of the code on the D specifications, which has a limited number of characters in the name field. To overcome this obstacle, I put the name on the line prior to the PR declaration type and end the name with the ellipses (...). When you're using free-formatted code, why not make your variables and procedure names as comprehensive as possible?
What were we talking about again? Oh yeah, retrieving the IP address of the device....
Using the QDCRDEVD API to Retrieve the IP Address
GetDeviceDescription(QDCD060000:972:'DEVD0600':thisJob:stdError);
The QDCRDEVD API will be accessed through the GetDeviceDescription prototype. The third parameter is the format name, which will determine the format and content of the data that is returned by the API. IBM has provided the convenient /COPY file QSYSINC/QRPGLESRC,QDCRDEVD, which defines all of the data structures for the possible formats that you can use. The first parameter will return the data structure that matches the DEVD0600 format and will be contained in the QDCD060000 variable with the length of 972, which is specified in the second parameter.
The fourth parameter identifies the device name that you wish to retrieve the IP address for. In this case, I'm using the device name of the current job, which is retrieved from the system data structure. But you can specify any device name of interest.
And finally, the fifth parameter is used to identify any errors that may occur. It is recommended that you specify the length of the expected error code results; otherwise, it could return a large amount of und
LATEST COMMENTS
MC Press Online