This chapter covers the SAS/C IUCV functions. Topics include a brief introduction to IUCV communications in a virtual machine, CMS support of IUCV, IUCV parameter lists and external interrupt data formats, and IUCV library functions.
Although an overview of the IUCV and CMS IUCV functions is provided, this discussion of IUCV communications is written primarily for programmers experienced with IUCV. A knowledge of CP and CMS is assumed. More detailed coverage of all aspects of IUCV can be found in the appropriate IBM publications for your release of VM. For a complete description of how the SAS/C Library supports asynchronous signals and the use of signal-related SAS/C functions, refer to Chapter 5, "Signal-Handling Functions," in SAS/C Library Reference, Volume 1 .
IUCV transfers data in blocks known as messages. Messages travel from a source communicator to a target communicator along a route called the message path. Each communicator can have many paths and can be a source communicator on some paths and a target communicator on others simultaneously.
When you write a program that permits IUCV communication, you invoke IUCV functions to perform the following basic IUCV tasks:
Programs written in assembler invoke IUCV functions via an instruction known as the IUCV macro instruction. The IUCV macro instruction specifies the IUCV function requested and a parameter list that contains the information needed to perform it. CMS IUCV services are provided by two assembler macros called HNDIUCV and CMSIUCV. HNDIUCV provides support for IUCV initialization and termination. CMSIUCV handles the connection to the communicating program. The CMSIUCV and HNDIUCV macros require that the program provide a name for CMS to use to keep track of IUCV paths. If a CMS IUCV macro in turn invokes an IUCV macro instruction, an IUCV parameter list also is required.
All SAS/C IUCV functions invoke either the IUCV macro instruction or one of the CMS IUCV macros. When a SAS/C function uses CMS IUCV support, the program must provide a name parameter and possibly an IUCV parameter list. When a SAS/C function invokes the IUCV macro instruction directly, the IUCV parameter list must be provided.
The SAS/C functions are described in detail in the following pages,
including specification of their parameters and the CMS IUCV service or
IUCV macro invoked. The <cmsiucv.h>
header file, providing
structure definitions for the IUCV parameter lists and external
interrupt data, also is described.
To summarize the IUCV functions and tasks involved, the following table shows IUCV functions as implemented by the library. Listing the macro and parameter involved in the function call illustrates how the library interfaces with IUCV and CMS.
SAS/C Function Purpose IUCV or CMS Macro
iucvset Initialize IUCV Invoke HNDIUCV communications macro with SET parameter iucvacc Accept a pending Invoke CMSIUCV connection macro with ACCEPT parameter iucvconn Request that a Invoke CMSIUCV path be macro with CONNECT established parameter iucvsevr Terminate an Invoke CMSIUCV existing path macro with SEVER parameter iucvclr Terminate IUCV Invoke HNDIUCV communications macro with CLR parameter iucvrply Respond to a Invoke the IUCV message macro instruction for REPLY iucvrecv Accept a message Invoke the IUCV macro instruction for function RECEIVE iucvrej Refuse a message Invoke the IUCV macro instruction for function REJECT iucvsend Send a message Invoke the IUCV macro instruction for function SEND iucvqs Temporarily suspend Invoke the IUCV communication macro instruction for function QUIESCE iucvresm Restore Invoke the IUCV communication after macro instruction a QUIESCE for function RESUME iucvtcmp Determine if a Invoke the IUCV message has been macro instruction completed for function TEST COMPLETION iucvpurg Terminate a message Invoke the IUCV macro instruction for function PURGE
signal
or sigaction
to establish a handler for SIGIUCV signals. Calling
signal
identifies a function (called a handler) that should be
invoked when an IUCV interrupt occurs. The handler should call the
signal function siginfo
, which returns a pointer to a structure
containing the external interrupt data.
Signal processing handles the IUCV interrupts associated with the basic IUCV tasks. IUCV external interrupts can be divided into those concerning connections and paths and those prompted by message transfer. The IUCV external interrupt types are summarized in the following table.
Connection and PathInterrupts Message Transfer Interrupts Interrupts
Connection pending Incoming priority message Connection complete Incoming message nonpriority Path severed Incoming priority reply Path quiesced Priority reply Path resumedThe library, at the time of the first call to
signal
with the
SIGIUCV signal identifier, initializes all library handling of IUCV
external interrupts for the program and associates a SIGIUCV handler
with the external interrupt. Although iucvset
can be called any
number of times within a program to establish multiple message paths,
only one SIGIUCV handler can be associated with IUCV signals at any one
time. Of course, programs can redefine handlers in subsequent calls to
signal
, or a single handler can use the external interrupt type
to route the signal to subsidiary functions. Because each message is
uniquely identified, the SIGIUCV handler can use this data to route
signals of similar types to other functions.
A simple example of the complete IUCV communication process is given in
the following table. In this example, calls to the signal functions sigblock
, sigpause
, and siginfo
are combined with SAS/C
IUCV function calls to process a message sent from a source virtual
machine to a receiving or target virtual machine. Note that before any
message transfer can occur, a call must be made to signal
to
identify the handler for subsequent SIGIUCV interrupts. Note also that
the call to signal
must be paired with a call to iucvset
to
initialize communication (step 1). These calls must be made by both
sender and receiver before any inter-user communication can take
place. Subsequent calls are traced back and forth across the table.
In step 2, for example, the receiving program issues a call to sigpause
to wait for the sending program's interrupt. In step 3, the
sender issues an iucvconn
to attempt a connection with the
receiver, and so on.
Sending Program Purpose of Call Receiving Program Function Called Function Called
1. signal Initialize signal sigblock sigblock iucvset communications iucvset Wait for 2. sigpause interrupt 3. iucvconn Sender attempts 4. siginfo to connect; receiver recognizes a connection pending 5. sigpause Sender waits 6. iucvacc until receiver accepts connection 7. siginfo Sender recognizes iucvsend sigpause connection is complete, sends a message, and waits for the reply Receiver 8. siginfo recognizes an iucvrecv iucvrply incoming message, sigpause receives it, replies, and waits 9. siginfo Sender recognizes an incoming reply and processes it 10. iucvsevr Message transfer 11. siginfo iucvclr complete; sender severs path and clears; receiver recognizes path severedIn this table, many of the IUCV function calls occur based on the information returned from the call to
siginfo
. This signal
function returns a pointer to one of three external interrupt
structures. The structure pointed to depends on the interrupt
subtype. These structures and their parameters are easily accessible
to the program. The next section discusses the structures involved in
IUCV communication and the information available to the program.
<cmsiucv.h>
. Three
structures cover all IUCV parameter lists and external interrupt data
formats. Each structure used in IUCV communication is discussed on the
following pages. As indicated by the comments, <cmsiucv.h>
parameter list fields correspond to fields in the parameter lists for
each individual IUCV function. These fields are explained in detail in
the IBM documentation mentioned in Introduction .
The structure iucv_path_plist
defines the ACCEPT, CONNECT,
QUIESCE, RESUME, and SEVER parameter list. External interrupt data are
defined for PENDING CONNECTION, CONNECTION COMPLETE, SEVER, QUIESCE,
and RESUME external interrupts.
struct iucv_path_plist { short pathid; /* IPPATHID */ char flags1; /* IPFLAGS1 */ union { char rcode; /* IPRCODE */ char type; /* IPTYPE */ } ip; short msglim; /* IPMSGLIM */ char fcncd; /* IMFCNCD */ char _; char vmid[8]; /* IPVMID */ char pgm[8]; /* IPUSER */ char user[8]; double _d; /* (used only for alignment) */ }; typedef struct iucv_path_plist iucv_path_data;The structure
iucv_msg_plist
defines the parameter list for the
RECEIVE, REJECT, REPLY, and SEND functions. External interrupt data
are defined for the pending message external interrupt.
struct iucv_msg_plist { short pathid; /* IPPATHID */ char flags1; /* IPFLAGS1 */ union { char rcode; /* IPRCODE */ char type; /* IPTYPE */ } ip; int msgid; /* IPMSGID */ int tgrcls; /* IPTRGCLS */ union { char data[8]; /* IPRMMSG1/IPRMMSG2 */ struct _adlen bf1; /* IPBFADR1/IPBFLN1F */ } msg; int srccls; /* IPSRCCLS */ int msgtag; /* IPMSGTAG */ struct _adlen bf2; /* IPBFADR2/IPBFLN2F */ double _d; /* (used only for alignment) */ }; typedef struct iucv_msg_plist iucv_msg_data;The last of the three IUCV structures is
iucv_comp_plist
. This
structure defines the parameter list for the PURGE and TEST COMPLETION
functions. External interrupt data are defined for the complete
message external interrupt.
struct iucv_comp_plist { short pathid; /* IPPATHID */ char flags1; /* IPFLAGS1 */ union { char type; /* IPTYPE */ char rcode; /* IPRCODE */ } ip; int msgid; /* IPMSGID */ unsigned audit; /* IPAUDIT (byte 4 not applicable)*/ char msgdata[8]; /* IPRMMSG1/IPRMMSG2 */ int srccls; /* IPSRCCLS */ int msgtag; /* IPMSGTAG */ int _; int bfln2f; /* IPBFLN2F */ double _d; /* (used only for alignment) */ }; typedef struct iucv_comp_plist iucv_comp_data;
The values for the interrupt subtypes, as defined for the structure
variable ip.type
, are shown in the following table:
Variable Value
CONNECTION_PENDING 1 CONNECTION_COMPLETE 2 PATH_SEVERED 3 PATH_QUIESCED 4 PATH_RESUMED 5 INCOMING_PRI_REPLY 6 INCOMING_REPLY 7 INCOMING_PRI_MSG 8 INCOMING_MSG 9The type definitions (such as
iucv_path_data
) and interrupt types
(ip.type
) enable you to control the way your program handles IUCV
interrupts. The following code illustrates how this can be done:
iucv_path_data *XID; XID = (iucv_path_data *) siginfo(); switch (XID->ip.type) { case CONNECTION_COMPLETE: break; case INCOMING_REPLY: /* Get reply length. */ rep_len = ((iucv_msg_data *)XID)->bf2.ln; break; }In this section of code, a cast expression converts the value returned by
siginfo
to a pointer of type iucv_path_data
so it can be
assigned to XID. A case statement is then used to handle the possible
interrupt subtypes returned in ip.type
.
#include <cmsiucv.h> int iucvacc(const char *name, struct iucv_path_plist *acc_parmlst);
iucvacc
requests CMS to issue an IUCV ACCEPT. name
points to
a string that must match the name
argument to a previously invoked
iucvset
function. acc_parmlst
is a pointer to an IUCV ACCEPT
parameter list.
iucvacc
returns 0
if the function call was successful. If
signal(SIGIUCV,fp)
has never been called, iucvacc
returns
-1. If the CMSIUCV macro returns a nonzero return code, iucvacc
returns that value. If an IUCV error occurs, iucvacc
returns 1
,
and the value of IPRCODE is available in acc_parmlst->ip.rcode
.
iucvset
before calling iucvacc
.
iucvacc
invokes the CMS CMSIUCV macro with the ACCEPT parameter.
#include <cmsiucv.h> /* Issue an IUCV ACCEPT in response to a */ /* pending connection. */ int rc; /* external interrupt data for a pending connection */ iucv_path_data *p_connect; /* other IUCV CONNECT parameter list initializations */ . . . p_connect->ip.type = 0; rc = iucvacc("RECEIVER",p_connect);
#include <cmsiucv.h> int iucvclr(const char *name);
iucvclr
terminates IUCV communications for a program.
name
points to a string that must match the name
argument to a
previously invoked iucvset
function.
iucvclr
returns 0
if the function call was successful.
If signal(SIGIUCV,fp)
has not been called, iucvclr
returns -1. If the HNDIUCV macro returns a nonzero return code, iucvclr
returns that value. If an IUCV error occurs, iucvclr
returns
1000
+ the value of IPRCODE (as does HNDIUCV).
iucvset
before calling iucvclr
.
iucvclr
invokes the CMS HNDIUCV macro with the CLR parameter and
frees the external interrupt data queue associated with name
.
#include <cmsiucv.h> . . . rc = iucvclr("SENDER");
#include <cmsiucv.h> int iucvconn(const char *name, struct iucv_path_plist *conn_parmlst);
iucvconn
requests CMS to issue an IUCV CONNECT. name
points
to a string that must match the name
argument to a previously
invoked iucvset
function. conn_parmlst
is a pointer to an
IUCV CONNECT parameter list.
iucvconn
returns 0
if the function call was successful. If
signal(SIGIUCV,fp)
has not been called, iucvconn
returns
-1 . If the CMSIUCV macro returns a nonzero return code, iucvconn
returns that value. If an IUCV error occurs, iucvconn
returns 1
,
and the value of IPRCODE is available in conn_parmlst->ip.rcode
.
iucvset
before calling iucvconn
.
iucvconn
invokes the CMS CMSIUCV macro with the CONNECT
parameter.
#include <cmsiucv.h> #include <lcstring.h> int rc; struct iucv_path_plist path; . . . /* Name the receiving userid and program. */ memset((char *) &path,0,sizeof(path)); memcpyp(path.vmid,"USERID",sizeof(path.vmid),6,' '); memcpy(path.pgm,"RECEIVER",8); rc = iucvconn("SENDER",&path);
#include <cmsiucv.h> int iucvpurg(struct iucv_comp_plist *comp_p); int iucvqs(struct iucv_path_plist *path_p); int iucvrecv(struct iucv_msg_plist *msg_p); int iucvrej(struct iucv_msg_plist *msg_p); int iucvresm(struct iucv_path_plist *path_p); int iucvrply(struct iucv_msg_plist *msg_p); int iucvsend(struct iucv_msg_plist *msg_p); int iucvtcmp(struct iucv_comp_plist *comp_p);
msg_p
,
path_p
, and comp_p
point to the IUCV parameter list associated
with that function. The function names and IUCV functions are
associated as follows:
SAS/C function IUCV function
iucvpurg PURGE iucvqs QUIESCE iucvrecv RECEIVE iucvrej REJECT iucvresm RESUME iucvrply REPLY iucvsend SEND iucvtcmp TEST COMPLETION
signal
or sigaction
and
initialized IUCV communications with iucvset
before invoking any
of these functions.
iucvset
.
sigaction
, signal
#include <cmsiucv.h> int iucvset(const char *name, int *maxconns);
iucvset
identifies an IUCV program to CMS. name
is a 1- to
8-character string identifying the communicating program's name.
For example, a SAS/C program called sender.c
may specify
the name
"SENDER"
. If name
is less than eight
characters long, it is padded with blanks on the right. If name
is greater than eight characters, it is truncated. The maximum number
of connections for the virtual machine is returned in the integer
pointed to by maxconns
.
You can call iucvset
any number of times as long as each call uses
a different name
string.
iucvset
returns 0
if the function call was successful.
iucvset
returns a negative code as follows:
signal
or sigaction
has never been called
to handle the SIGIUCV signal.
iucvset
had the same name
parameter.
iucvset
returns that value.
signal
or sigaction
to establish an IUCV interrupt handler before
calling iucvset
. An IUCV program must be ready to handle
incoming IUCV interrupts even before iucvset
has returned.
iucvset
invokes the CMS HNDIUCV macro with the SET parameter. In
addition, it allocates an initial 4K external interrupt data buffer.
#include <cmsiucv.h> #include <stdio.h> int maxconns, rc; . . . rc = iucvset("SENDER",&maxconns); if (rc != 0) puts("iucvset failed.");
#include <cmsiucv.h> int iucvsevr(const char *name, struct iucv_path_plist *svr_parmlst, const char *code);
iucvsevr
requests CMS to issue an IUCV SEVER. name
points to
a string that must match the name
argument to a previously invoked
iucvset
function. svr_parmlst
is a pointer to an IUCV SEVER
parameter list.
code
can be either "ALL"
or "ONE"
. If it is
"ONE"
, only the one path specified by svr_parmlist.pathid
is severed
(using SEVER). If code
is "ALL"
, all paths owned by the
program are severed. The "ALL"
and "ONE"
parameters must be
coded exactly as shown, uppercase and enclosed in quotation marks, with no
substitutions or variations in syntax.
iucvsevr
returns 0
if the function call was successful. If
neither
signal
nor sigaction
has not been called to handle the SIGIUCV signal,
iucvsevr
returns
-1. If the CMSIUCV macro returns a nonzero return code, iucvsevr
returns that value. If an IUCV error occurs, iucvsevr
returns 1
,
and the value of IPRCODE is available in svr_parmlst->ip.rcode
.
iucvset
before calling iucvsevr
.
iucvsevr
invokes the CMS CMSIUCV macro with the SEVER parameter.
The value of the CODE parameter depends on the value of code
.
#include <cmsiucv.h> short pathid; /* PATHID to be severed */ path.pathid = pathid; rc = iucvsevr("SENDER",&path,"ONE");
main
function
initializes signal processing and IUCV. It uses fgets
to read
message strings and printf
to display reply strings. The
sigpause
function makes the program wait until a reply is sent. The
sigblock
function blocks SIGIUCV signals until the program is
ready to handle them.
The iucvtrap
function is the SIGIUCV signal handler. Only two
IUCV interrupt types are expected: a CONNECTION COMPLETE interrupt in
response to the IUCV CONNECT and an INCOMING REPLY in response to each
IUCV SEND.
The source code for these examples is provided with the compiler and library. Ask your SAS Software Representative for SAS/C software products for information about obtaining copies of these programs.
/* SENDER */ #include <lcsignal.h> #include <lcstring.h> #include <cmsiucv.h> #include <lcio.h> void iucvtrap(void); /* Declare SIGIUCV handler.*/ /* Set up stdin amparms.*/ char *_stdiamp = "prompt=What message do I send?,eof="; int rep_len = 0; short pathid = 0; main() { struct iucv_path_plist path; /* IUCV plist for CONNECT, SEVER */ struct iucv_msg_plist msg; /* IUCV plist for SEND */ /* maximum number of IUCV connections for this virtual machine */ int maxconns; int rc; /* return code from IUCV functions*/ char message[120], /* message buffer */ reply[120]; /* reply buffer */ /* Initialize IUCV signal processing and establish a handler. */ /* Block IUCV signals until we're ready to handle them. */ signal(SIGIUCV,&iucvtrap); sigblock(1 << (SIGIUCV-1)); /* Identify this program as SENDER. */ if ((rc = iucvset("SENDER",&maxconns)) != 0) { printf("Return code from iucvset was %d\n",rc); exit(4); } printf("Maximum IUCV connections: %d\n",maxconns); /* Fill in the IUCV "path" parameter list with the target */ /* userid and the name of the target program. All of the other */ /* parameters are superfluous in this program. */ memset((void *) &path,0,sizeof(path)); memcpy(path.vmid,"SASCUSER",8); memcpy(path.pgm,"RECEIVER",8); /* Request an IUCV CONNECT to the userid/program pair named */ /* in the parameter list. Check for an IUCV error (return */ /* code of 1)and print the IUCV error code. */ rc = iucvconn("SENDER",&path); if (rc != 0) { printf("Return code from iucvconn was %d\n",rc); if (rc == 1) printf("IPRCODE = %d\n",path.ip.rcode); exit(8); } /* Now we are ready. The first interrupt we receive is the */ /* CONNECTION COMPLETE interrupt that occurs when RECEIVER */ /* issues an IUCV ACCEPT. */ sigpause(0); /* Initialize the SEND parameter list with the pathid and */ /* buffer addresses and the length of the reply buffer. */ memset((void *) &msg,'\0',sizeof(msg)); path.pathid = msg.pathid = pathid; msg.msg.bf1.adr = message; msg.bf2.adr = reply; msg.bf2.ln = sizeof(reply); /* Prompt for input messages and send until EOF. */ fgets(message,sizeof(message),stdin); while (!feof(stdin)) { /* Put message length in the SEND parameter list. */ msg.msg.bf1.ln = strlen(message) - 1; /* Send message. Wait (via sigpause) for reply. Upon */ /* receipt of reply, 'rep_len' contains the number of */ /* unused bytes in the reply buffer. Print the reply */ /* and prompt for a new message. */ iucvsend(&msg); sigpause(0); rep_len = sizeof(reply) - rep_len; printf("RECEIVER replies \"%.*s\"\n", rep_len,reply); fgets(message,sizeof(message),stdin); } /* We are ready to quit. SEVER the IUCV path. Check for IUCV */ /* errors as before. */ if ((rc = iucvsevr("SENDER",&path,"ONE")) != 0) { printf("Return code from iucvsever = %d\n",rc); if (rc == 1) printf("IPRCODE = %d\n",path.ip.rcode); exit(10); } /* Terminate IUCV communications for SENDER. */ iucvclr("SENDER"); exit(0); } /* The SIGIUCV signal handler. Signals are blocked until return. */ void iucvtrap(void) { /* Pointer to external interrupt data returned by siginfo. The */ /* type is arbitrary since it can point to any of the IUCV */ /* structures. */ iucv_path_data *XID; /* Get a pointer to the external interrupt data. Use the */ /* interrupt type to determine what to do. */ XID = (iucv_path_data *) siginfo(); switch (XID->ip.type) { case CONNECTION_COMPLETE: /* Save the pathid for SEND. */ pathid = XID->pathid; break; /* Extract the number of unused characters in the buffer. */ case INCOMING_REPLY: rep_len = ((iucv_msg_data *)XID)->bf2.ln; break; /* Handle unexpected termination of RECEIVER. */ case PATH_SEVERED: puts("Unexpected SEVER!"); exit(20); /* Handle unexpected type of IUCV signal. */ default: printf("Unexpected interrupt type %d\n",XID->ip.type); fflush(stdout); abort(); } /* Reestablish this function as the SIGIUCV signal handler. */ signal(SIGIUCV,&iucvtrap); return; }
main
function, again,
initializes signal processing and IUCV. main
calls sigpause
to wait for the initial CONNECTION PENDING interrupt once and then
repeatedly (until all connections are severed) for incoming messages.
The iucvtrap
function is again the SIGIUCV signal handler. Three
types of IUCV interrupts are expected: a CONNECTION PENDING for each
sending program, a PATH SEVERED as each sending program finishes, and
an INCOMING MSG interrupt for each message sent by a sending program.
Finally, the rcvrply
function issues an IUCV RECEIVE for each
incoming message and prompts for a reply string. It then sends the
reply string via an IUCV REPLY.
/* RECEIVER */ #include <lcsignal.h> #include <lcstring.h> #include <cmsiucv.h> #include <lcio.h> void iucvtrap(void); /* SIGIUCV signal handler */ /* stdin prompt string */ char *_stdiamp = "prompt=What do I reply to SENDER?"; int connects = 0; /* number of connections made */ static void rcvrply(iucv_msg_data *); /* Declare internal functions. */ void main() { int maxconns; /* number of IUCV connections allowed */ int rc; /* return code from IUCV functions */ /* Initialize IUCV signal processing and establish a handler. */ /* Block IUCV signals until we are ready to handle them. */ signal(SIGIUCV,&iucvtrap); sigblock(1 << (SIGIUCV-1)); /* Identify this program as RECEIVER. */ if ((rc = iucvset("RECEIVER",&maxconns)) != 0) { printf("Return code from iucvset was %d\n",rc); exit(4); } printf("Maximum IUCV connections: %d\n",maxconns); /* This call waits for the initial */ /* CONNECTION PENDING interrupt. */ sigpause(0); /* As long as some SENDER is connected, */ /* wait for incoming messages. */ while (connects > 0) sigpause(0); /* All paths have been terminated. Terminate IUCV processing. */ iucvclr("RECEIVER"); exit(0); } /* SIGIUCV signal handler. Signals are blocked until return. */ void iucvtrap(void) { /* Pointer to external interrupt data returned by siginfo. The */ /* type is arbitrary because it can point to any of the IUCV */ /* structures. */ iucv_path_data *XID; int rc; /* Return code from iucvacc.*/ /* Get a pointer to the external interrupt data. Use the */ /* interrupt type to determine what to do. */ XID = (iucv_path_data *) siginfo(); switch (XID->ip.type) { case CONNECTION_PENDING: /* Issue ACCEPT. */ XID->ip.type = 0; if ((rc = iucvacc("RECEIVER",XID)) != 0) { printf("Return code from iucvacc = %d\n",rc); if (rc == 1) printf("IPRCODE = %d\n",XID->ip.rcode); exit(8); } /* Keep track of the number of connections made. */ connects++; break; /* Call function to get message and send reply. */ case INCOMING_MSG: rcvrply((iucv_msg_data *)XID); break; case PATH_SEVERED: /* SENDER decided to stop. */ if ((rc = iucvsevr("RECEIVER",XID,"ONE")) != 0) { printf("Return code from iucvsevr = %d\n",rc); exit(8); } connects--; /* Update number of connections.*/ break; default: /* Handle other interrupt types.*/ printf("Unexpected interrupt type %d\n",XID->ip.type); fflush(stdout); abort(); } /* Re-establish this function as the SIGIUCV signal handler. */ signal(SIGIUCV,&iucvtrap); return; } /* Function to issue IUCV RECEIVE and print the message. */ static void rcvrply(m_data) iucv_msg_data *m_data; { int msg_len; /* incoming message length */ char msg_buffer[120]; /* message buffer */ /* Create IUCV RECEIVE parameter list using the external */ /* interrupt data area. Issue the IUCV RECEIVE. */ m_data->msg.bf1.adr = msg_buffer; m_data->msg.bf1.ln = sizeof(msg_buffer); iucvrecv(m_data); /* Upon return, m_data->msg.bf1.ln contains the number of */ /* unused bytes in the message buffer. Print the message. */ msg_len = sizeof(msg_buffer) - m_data->msg.bf1.ln; printf("SENDER says \"%.*s\"\n", msg_len,msg_buffer); /* Prompt for a reply message. If EOF, quit. */ fgets(msg_buffer,sizeof(msg_buffer),stdin); if (feof(stdin)) { puts("Terminating due to end-of-file."); exit(12); } /* Fill in IUCV REPLY parameter list with buffer */ /* address/length and send REPLY. */ m_data->bf2.adr = msg_buffer; m_data->bf2.ln = strlen(msg_buffer) - 1; iucvrply(m_data); }
In using SAS/C IUCV functions, be aware of the following points:
signal
or sigaction
function
with the SIGIUCV signal as
the first argument. This is necessary to establish signal handling
before an IUCV signal occurs. You must do this before any IUCV
function is called.
iucvset
creating an IUCV path must be matched with an
eventual call to iucvclr
destroying the path. If, at program
termination (either by return
or exit
), there are still IUCV
paths that have not been destroyed via iucvclr
, the library
issues iucvclr
calls for these paths. Invoking iucvclr
also
frees the space allocated by iucvset
for queuing interrupts.
code
argument in the iucvsevr
function is
not "ALL"
, "ONE"
is assumed.
iucvset
is
called. If there are times when you do not want to be interrupted, use
sigblock
and sigpause
.
sigpause
to wait for
an IUCV signal. The use of sigblock
to block the SIGIUCV signal
at other times is critical to these examples. If you do not use
sigblock
(or sigsetmask
) to block IUCV signals, an expected
signal may be discovered before the call to sigpause
. In this
event, sigpause
causes the program to wait for a second signal.
Depending on the logic of the program, this can cause it to wait for an
indefinitely long period.
iucvset
.
iucvclr
or by program termination. The library uses approximately 44 bytes
per enqueued IUCV message. Queue storage is allocated in 4K blocks.
If the library cannot allocate a 4K block to extend the queue, then a
user ABEND 1228 is issued.
errno
variable. If, during program termination, paths are cleared implicitly
by the library and an error occurs, an informatory NOTE is issued.
However, the program cannot be informed that an error has occurred.
Copyright (c) 1998 SAS Institute Inc. Cary, NC, USA. All rights reserved.