/*--------------------------------------------------------------------+
| |
| 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 <lcsignal.h>
#include <lcstring.h>
#include <cmsappc.h>
#include <lcio.h>
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;
}
|