/*--------------------------------------------------------------------+ | | | Copyright 1996 (c), SAS Institute Inc. | | Unpublished - All Rights Reserved | | | | S A S / C S A M P L E | | | | Name: APPCSEND | | | | Language: C | | | | EntryPoint: MAIN | | | | EntryType : OS Entry Linkage | | | | Files Note: 'prefix' is the installation defined high level | | qualifier for the SAS/C product. | | | | Purpose: Demonstrate SAS/C APPC/VM support. | | | | MVS - Not Supported for MVS | | | | Source: prefix.SAMPLE.C(APPSEND) | | | | CMS - | | Source: SAMPLC MACLIB (APPCSEND) | | | | Compile: global maclib lc370 | | lc370 appcsend | | | | Link: global txtlib lc370bas lc370std | | load (appcsend | | genmod appcsend(from @main | | | | Execute: See the SAS/C Language Reference Vol 2, | | chapter 'APPC/VM Functions' for details. | | | | Notes: | | - This sample for CMS only. | | - See sample APPCSERV for setup information. | | | +--------------------------------------------------------------------*/ #eject #include #include #include #include void appctrap(void); /* Declare SIGIUCV handler. */ /* Set up stdin amparms. */ char *_stdiamp = "prompt=What message do I send?\n,eof="; static int rep_len = 0; static short pathid = 0; static short ident_pathid = 0; void main() { struct appc_conn_plist conn; /* APPC plist for CONNECT, SEVER */ struct appc_send_plist send; /* APPC plist for SENDDATA, */ /* SENDCNFD */ int maxconns, /* Maximum number of IUCV connec- */ /* tions for this virtual machine*/ rc; /* Return code from APPC functions*/ struct senddata { unsigned short length; /* length of data to send */ char message(|120+2|); /* Message buffer. */ } logrec, reply; /* Log record and reply buffers */ /*----------------------------------------------------------------+ | Initialize IUCV signal processing and establish a handler. | | Block IUCV signals until we're ready to handle them. | +----------------------------------------------------------------*/ signal(SIGIUCV,&appctrap); sigblock(1 << (SIGIUCV-1)); /*----------------------------------------------------------------+ | Identify this program as APPCSEND. | +----------------------------------------------------------------*/ if ((rc = iucvset("APPCSEND",&maxconns)) != 0) { printf("Return code from iucvset was %d\n",rc); exit(4); } printf("Maximum IUCV connections: %d\n",maxconns); /*----------------------------------------------------------------+ | Fill in the APPC "conn" parameter list with the target resource | | id, "APPCSERV". | | | | Note that the resource name in IPRESID must be eight bytes | | long, padded on the right with blanks if necessary. | +----------------------------------------------------------------*/ memset(&conn, 0, sizeof(conn)); conn.ip2.flags2 = IPLVLCF + IPMAPPED; memcpy(conn.resid, "APPCSERV",8); /*----------------------------------------------------------------+ | Request an APPC CONNECT to the resource named in the | | parameter list. Check for an IUCV error (return code != 0) and | | print the APPC error code. | +----------------------------------------------------------------*/ rc = appcconn("APPCSEND",&conn, 0); if (rc != 0) { printf("Return code from appcconn was %d\n",rc); if (rc == 1) printf("IPRCODE = x'%X'\n",conn.ip1.rcode); exit(8); } /*----------------------------------------------------------------+ | Now we're ready. The first interrupt we will receive is the | | CONNECTION COMPLETE interrupt that occurs when APPCSERV | | issues an APPC ACCEPT. | +----------------------------------------------------------------*/ sigpause(0); /*----------------------------------------------------------------+ | Initialize the SEND parameter list with the pathid and buffer | | addresses, and the length of the reply buffer. | +----------------------------------------------------------------*/ memset(&send, 0,sizeof(send)); send.pathid = pathid; send.sendop = IPSNDRCV; send.bf1.adr = (char *) &logrec; send.bf2.adr = (char *) &reply; send.bf2.ln = sizeof(reply); /*----------------------------------------------------------------+ | Prompt for input messages and send until EOF. | +----------------------------------------------------------------*/ fgets(logrec.message, sizeof(logrec.message), stdin); while (!feof(stdin)) { /*-------------------------------------------------------------+ | Put message length in the SEND parameter list. | +-------------------------------------------------------------*/ logrec.length = strlen(logrec.message) + 1; send.bf1.ln = logrec.length; /*-------------------------------------------------------------+ | 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. | +-------------------------------------------------------------*/ appcsdta(&send); sigpause(0); rep_len = reply.length - sizeof(reply.length); printf("APPCSERV replies \"%.*s\"\n",rep_len,reply.message); fgets(logrec.message, sizeof(logrec.message), stdin); } /*----------------------------------------------------------------+ | We're ready to quit. Ask the server if it's OK to sever. If | | so, then sever. | +----------------------------------------------------------------*/ memset(&send, 0, sizeof(send)); send.pathid = pathid; send.ip2.flags2 = IPWAIT; /* Specify WAIT=YES */ send.sendop = IPCNFSEV; if ((rc = appcsdta(&send)) != 2) { printf("Return code from appcsdta = %d\n",rc); if (rc == 1) printf("IPRCODE = x'%X'\n",send.ip1.rcode); exit(12); } memset(&conn, 0, sizeof(conn)); conn.pathid = pathid; conn.ip2.flags2 = IPWAIT; /* Specify WAIT=YES */ conn.sendop = IPSNORM; if ((rc = appcsevr("APPCSEND",&conn,"ONE")) != 2) { printf("Return code from appcsever = %d\n",rc); if (rc == 1) printf("IPRCODE = x'%X'\n",conn.ip1.rcode); exit(16); } /*----------------------------------------------------------------+ | Terminate APPC communications for APPCSEND. | +----------------------------------------------------------------*/ iucvclr("APPCSEND"); exit(0); } #pragma eject /*-------------------------------------------------------------------+ | The SIGIUCV signal handler. Signals are blocked until return. | +-------------------------------------------------------------------*/ void appctrap() { appc_conn_data *XID; /* Pointer to external interrupt */ /* data returned by siginfo. */ int rc; /*----------------------------------------------------------------+ | Get a pointer to the external interrupt data. Use the interrupt| | type to determine what to do. | +----------------------------------------------------------------*/ XID = (appc_conn_data *) siginfo(); switch (XID->ip1.type) { case APPC_CONNECTION_COMPLETE: pathid = XID->pathid; /* Save the pathid */ break; case APPC_FUNCTION_COMPLETE: /* See if it's for CONFIRM */ if (XID->pathid == pathid && XID->ip2.whatrc == IPSNDCNF) { struct appc_send_plist *send = (struct appc_send_plist *)XID; send->sendop = IPCNFRMD; rc = appcscfd(send); if (rc != 2) { printf("Error %d confirming request to recv\n", rc); printf("IPRCODE = x'%X'\n", XID->ip1.rcode); exit(20); } } break; case APPC_SEVER_INTERRUPT: /* Handle unexpected termination */ /* of APPCSERV. */ puts("Unexpected SEVER!"); exit(24); default: /* Handle unexpected signal type */ printf("Unexpected interrupt type x'%X'\n",XID->ip1.type); fflush(stdout); abort(); } /*----------------------------------------------------------------+ | Re-establish this function as the SIGIUCV signal handler. | +----------------------------------------------------------------*/ signal(SIGIUCV,&appctrap); return; }