IBM Support

Calling unix-type APIs in ILE CL Program

Question & Answer


Question

Calling unix-type APIs in ILE CL Program.

This document will use API QIBM_QTG_DEVINIT exit point as an example to illustrate the concept.
 

Cause

This document uses API QIBM_QTG_DEVINIT exit point as an example to illustrate the concept.
Additional search kwds: Sample Example CL CLP CLLE

Answer

When you call an API, the protocol for passing parameters is to typically pass a space pointer that points to the information being passed. (This is also referred to as pass-by-reference.) This is the convention used by default for the control language (CL), RPG, and COBOL compilers. Care must be used in those languages that support pass-by-value (such as ILE C) to ensure that these conventions are followed. Refer to the appropriate language documentation for instructions. The parameter passing convention of pass-by-reference can be used in all programming languages. Some of the UNIX-type APIs require pass-by-value parameter passing. VisualAge® C++ for IBM® i also supports pass-by-value parameter passing.

If you’ve used any of the ILE compilers, you probably know that IBM ships thousands of procedure-level APIs. Many of those procedures are defined to expect parameters to be passed “by value” and CL could only pass parameters “by reference”. 
In V5R3, the CALLPRC command allows you to choose whether the parameter is passed by reference or by value.


•CALLPRC (Call Procedure) command supports calls from ILE CL procedures to other ILE procedures
•In prior releases, CALLPRC only supported passing parameters "by reference"
•Can specify *BYREF or *BYVAL special value for each parameter being passed
•Enables ILE CL to call many MI and C functions and other  procedure APIs    
•Maximum numbers of parameters still 300
•Added TYPE(*PTR) on DCL statement
•New %ADDRESS built-in to set pointer
•New %OFFSET built-in to set or retrieve the offset portion of pointer variable
•Added STG(*BASED) attribute on DCL statement
•Enables calling (or being called by) programs that have pointer parameters
•Makes many procedure APIs available to ILE CL
–Full record-level file I/O
–String functions

Some people would not expect CL and pointers to be used in the same sentence!  This enhancement is part of the effort to make CL more API-friendly.  The fact is that many APIs either expect parameters that are pointers or return arrays of information, which are most naturally navigated using pointers and based variables. 
We added pointer support in V5R4, with the related support for based variables and built-in functions, %ADDRESS and %OFFSET, to manipulate pointer variables.  While both the classic and ILE CL compilers will benefit from the addition of pointer support, the ILE CL compiler may have the advantage because this support will make many API procedures available that the classic CL compiler cannot take advantage of.



Declaring a Pointer CL Variable
DCL  &CHARVAR  *CHAR  LEN(10)
DCL  &PTRVAR  *PTR  ADDRESS(&CHARVAR)
Declaring a *BASED CL Variable
DCL  &ENTRYPTR  *PTR
DCL  &CHARENTRY  *CHAR 10  STG(*BASED) BASPTR(&ENTRYPTR)
Declaring a *DEFINED Pointer CL Variable
DCL  &CHARSTRUCT  *CHAR  LEN(48)

DCL  &PTRVAR2  *PTR  STG(*DEFINED) DEFVAR(&CHARSTRUCT 17)

Below is a sample CLLE program that illustrates how to capture the IP address of clients using Telnet to connect to IBM i server. This CLLE program is using QIBM_QTG_DEVINIT exit point.
Details about Device initialization exit program are provided in IBM Knowledge Center
The ip address is contained in Connection description information. It is 4-byte unsigned.

Required parameter group
1 User description information I/O Char(*)
2 Device description information I/O Char(*)
3 Connection description information Input Char(*)
4 Environment options Input Char(*)
5 Length of environment options Input Binary(4)
6 Allow connection Output Char(1)
7 Allow autosign-on Output Char(1)


IPv4 Client internet address
The IP address (or type structure) of the requesting client. An IP address is always provided to the exit point program. The IP address is specified in this field if the address is an IPv4 address. If the address is a pure IPv6 address, it is specified in the IPv6 Client internet address field, in which case this structure is set to all binary zeros. The layout of the field is as follows:

Name
Size
Description
Table 2. Client IP address layout
sin_len CHAR(1) Size of the sockaddr_in structure
sin_family CHAR(1) Protocol family IP (Version 4) is hex 02
sin_port CHAR(2) 16-bit unsigned port number
sin_addr CHAR(16) 4-byte unsigned


The inet_ntoa() function is used to translate an Internet address from a 32-bit IP address to dotted decimal format.

 

/* The information contained in this document has not been submitted          */
/* to any formal tests and is distributed on an 'As is' basis                 */
/* without any warranty either expressed or implied. The use of this          */
/* information or the implementation of any of these techniques is a          */
/* customer responsibility and depends on the customer's ability to           */
/* evaluate and integrate them into the customer's operation                  */
/* environment. While each item may have been reviewed by IBM                 */
/* for accuracy in a specific situation, there is no guarantee that the       */
/* same or similar results will be obtained elsewhere. Customers              */
/* attempting to adapt these techniques to their environments do so           */
/* at their own risk.                                                         */
             
/* The information contained in this document has not been submitted          */
/* to any formal tests and is distributed on an 'As is' basis                 */
/* without any warranty either expressed or implied. The use of this          */
/* information or the implementation of any of these techniques is a          */
/* customer responsibility and depends on the customer's ability to           */
/* evaluate and integrate them into the customer's operation                  */
/* environment. While each item may have been reviewed by IBM                 */
/* for accuracy in a specific situation, there is no guarantee that the       */
/* same or similar results will be obtained elsewhere. Customers              */
/* attempting to adapt these techniques to their environments do so           */
/* at their own risk.                                                         */

             PGM        PARM(&USRDESC &DEVDESC &CONDESC &ENVDAT &ENVLTH &ALLOW &AUTOSGN)
             DCL        VAR(&USRDESC) TYPE(*CHAR) LEN(44)
             DCL        VAR(&DEVDESC) TYPE(*CHAR) LEN(40)
             DCL        VAR(&CONDESC) TYPE(*CHAR) LEN(74)
             DCL        VAR(&ENVDAT) TYPE(*CHAR) LEN(1024)
             DCL        VAR(&ENVLTH ) TYPE(*CHAR) LEN(04)
             DCL        VAR(&ALLOW ) TYPE(*CHAR) LEN(01)
             DCL        VAR(&AUTOSGN) TYPE(*CHAR) LEN(01)

/* define pointer variables */
             DCL        VAR(&IADDR) TYPE(*UINT) LEN(4)
             DCL        VAR(&PADDR) TYPE(*PTR)
             DCL        VAR(&BADDR) TYPE(*CHAR) STG(*BASED) BASPTR(&PADDR) LEN(15)
/* define variables to perform scanning and trimming */
             DCL        VAR(&SPOS) TYPE(*UINT) LEN(2)
             DCL        VAR(&ZERO) TYPE(*CHAR) LEN(1) VALUE(X'00')
             DCL        VAR(&TIME) TYPE(*CHAR) LEN(9)

/* ip address is 4-byte unsigned starting offset 9 of the connection description */
             CHGVAR     VAR(&IADDR) VALUE(%BIN(&CONDESC 9 4))

/* inet_ntoa is UNIX-type API and requires pass-by-value parameter passing */
             CALLPRC    PRC('inet_ntoa') PARM((&IADDR *BYVAL)) RTNVAL(&PADDR)

/* Locate first blank char that might be present at the tail end of ipaddr */
/* There is a good chance the ip address may not be using all 15 positions */
/* i.e 9.5.10.20 <== the last 6 positions will contain nulls, which will display as */
/* block cursor(s) when &BADDR is passed into SNDPGMMSG. This is not desirable. */
/* The trailing blanks need to be trimmed off */
             CHGVAR     VAR(&SPOS) VALUE(%SCAN(&ZERO &BADDR))
             CHGVAR     VAR(&SPOS) VALUE(&SPOS - 1)
             CHGVAR     VAR(&BADDR) VALUE(%SST(&BADDR 1 &SPOS))
/* the Exit Point is invoked by QTVDEVICE job */
/* SNDPGMMSG will post the dotted ipaddr in the QTVDEVICE message queue */
             RTVSYSVAL  SYSVAL(QTIME) RTNVAR(&TIME)
             CHGVAR     VAR(&TIME) VALUE(%SST(&TIME 1 2) *TCAT ':' *TCAT %SST(&TIME 3 2) *TCAT +
                          ':' *TCAT %SST(&TIME 5 2))
             SNDPGMMSG  MSG(&BADDR *TCAT ' Connected at ' *CAT &TIME)
/* At this point you may want to block or allow the connection. I am allowing it. */
             CHGVAR     VAR(&ALLOW) VALUE('1')
             ENDPGM 

CRTBNDCL PGM(<yourlib>/<your pgm>) SRCFILE(<your lib>/< your QCLLESRC>)
The program now needs to be added to Exit Point:-

ADDEXITPGM EXITPNT(QIBM_QTG_DEVINIT) FORMAT(INIT0100)
PGMNBR(1) PGM(<yourlib>/<yourpgm>) REPLACE(*YES)
CRTEXITPNT(*NO) PGMDTA(*JOB *CALC 10)

Exit point performance

The Telnet server response time for your initial session request includes any time that it takes for the server to call, process, and return the QIBM_QTG_DEVINIT exit program. If your exit program is doing significant processing, the performance impact might result in a longer wait before your session is established. If you want to modify the default 60 second timeout value for user exit programs, you can use the ADDEXITPGM command to add user data that is read as the timeout value. In the above example, the PGMDTA parameter overrides the default 60 second timeout to 10 seconds.


Any new Telnet connection that is requested will result in the exit point program to get control.

image-20240324102801-1

[{"Product":{"code":"SWG60","label":"IBM i"},"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Component":"Programming (Languages- compilers- tools)","Platform":[{"code":"PF012","label":"IBM i"}],"Version":"Version Independent","Edition":"All Editions","Line of Business":{"code":"LOB57","label":"Power"}}]

Document Information

More support for:
IBM i

Software version:
Version Independent

Operating system(s):
IBM i

Document number:
687873

Modified date:
24 March 2024

UID

nas8N1022435

Manage My Notification Subscriptions