/*---------------------------------------------------------------------+ | Copyright (c) 1995, SAS Institute Inc. | | Unpublished - All Rights Reserved | | S A S / C S A M P L E | | | | NAME: SENDER | | LANGUAGE: C | | PURPOSE: This application demonstrates IUCV communications in | | CMS environments. SENDER works in conjunction with | | the SAS/C RECEIVER sample. Refer to the SAS/C Library | | Reference, Volume 2, Third Edition, Version 6.00 for | | additional information. | | MVS - N/A - SAS/C IUCV functions are only supported in CMS. | | CMS - | | COMPILE: LC370 SENDER | | LINK: CLINK SENDER (genmod | | EXECUTE: SENDER | | NOTES: The target virtual machine, in this case the machine | | running the RECEIVER module, must be identified. | | Modify the: #define TARGET statement below. The default| | value is: "SASCUSER". The value *is* case sensitive, | | if less then eight characters, padded with blanks. | | | +---------------------------------------------------------------------*/ #include #include #include #include /*----------------------------------------------------------------+ | TARGET must customized to identify the virtual machine | | running the RECEIVER module. The value should be the virtual | | machine name. If the name is not correct or the RECEIVER is NOT | | running, expect IUCV connect errors with non-zero IPRCODE's. | +----------------------------------------------------------------*/ #define TARGET "SASCUSER" void iucvtrap(void); /* Declare SIGIUCV handler. */ /* Set up stdin amparms. */ char *_stdiamp = "prompt=What message do I send?\n,eof="; int rep_len = 0; short pathid = 0; void main() { struct iucv_path_plist path; /* IUCV plist for CONNECT, SEVER. */ struct iucv_msg_plist msg; /* IUCV plist for SEND. */ int maxconns, /* Maximum number of IUCV connec- */ /* tions for this virtual machine*/ 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,(_HANDLER) &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 superflous in this program. | | | | Note that the userid copied to path.vmid must be eight bytes | | long, padded on the right with blanks if necessary. | +----------------------------------------------------------------*/ memset((char *) &path,0,sizeof(path)); memcpy(path.vmid,TARGET,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're ready. The first interrupt we will 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((char *) &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're 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); } #eject /*-------------------------------------------------------------------+ | The SIGIUCV signal handler. Signals are blocked until return. | +-------------------------------------------------------------------*/ void iucvtrap() { iucv_path_data *XID; /* Pointer to external interrupt */ /* data returned by siginfo. The */ /* type is arbitrary since it */ /* can point to any of the */ /* IUCV structures. */ /*----------------------------------------------------------------+ | 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; case INCOMING_REPLY: /* Extract the number of unused */ /* characters in the buffer. */ rep_len = ((iucv_msg_data *)XID)->bf2.ln; break; case PATH_SEVERED: /* Handle unexpected termination */ /* of RECEIVER. */ puts("Unexpected SEVER!"); exit(20); default: /* Handle unexpected type of */ /* IUCV signal. */ printf("Unexpected interrupt type %d\n",XID->ip.type); fflush(stdout); abort(); } /*----------------------------------------------------------------+ | Re-establish this function as the SIGIUCV signal handler. | +----------------------------------------------------------------*/ signal(SIGIUCV,(_HANDLER) &iucvtrap); return; }