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 resumed
The 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
severed
In 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.