Chapter Contents |
Previous |
Next |
iucvsevr |
The SENDER Program |
This program has only two functions. The
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.
/* 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; }
The RECEIVER Program |
This program defines three functions. The
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); }
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.