/*--------------------------------------------------------------------+
| |
| Copyright 1996 (c), SAS Institute Inc. |
| Unpublished - All Rights Reserved |
| |
| S A S / C S A M P L E |
| |
| Name: APPCSERV |
| |
| 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(APPSERV) |
| |
| CMS - |
| Source: SAMPLC MACLIB (APPCSERV) |
| |
| Compile: global maclib lc370 |
| lc370 appcserv |
| |
| Link: global txtlib lc370bas lc370std |
| load (appcserv |
| genmod appcserv(from @main |
| |
| Execute: See the SAS/C Language Reference Vol 2, |
| chapter 'APPC/VM Functions' for details. |
| |
| Notes: |
| - This sample for CMS only. |
| - The userid executing APPCSERV will need directory |
| statement authorizing IUCV with the *IDENT system |
| service option. The following were used to |
| test this sample: |
| |
| IUCV ALLOW |
| IUCV *IDENT appcserv local |
| |
| |
+--------------------------------------------------------------------*/
#pragma eject
#include <lcsignal.h>
#include <lcstring.h>
#include <lcio.h>
#include <cmsappc.h>
#include <stdlib.h>
void appctrap(void); /* Declare SIGIUCV signal handler.*/
/* Establish stdin prompt string. */
char *_stdiamp = "prompt=What do I reply to SENDER?\n,eof=";
int connects = 0; /* Number of connections made. */
static short ident_pathid = 0; /* used for *IDENT */
/*-------------------------------------------------------------------+
| Declare internal functions. |
+-------------------------------------------------------------------*/
static void rcvrply(struct appc_send_plist *);
void main()
{
int maxconns, /* Number of IUCV connections */
/* allowed. */
rc; /* Return code from functions */
struct iucv_path_plist conn; /* IUCV CONNECT parameter list */
ident_parms ident; /* *IDENT parameters */
/*----------------------------------------------------------------+
| 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 APPCSERV. |
+----------------------------------------------------------------*/
if ((rc = iucvset("APPCSERV",&maxconns)) != 0) {
printf("Return code from iucvset APPCSERV was %d\n",rc);
exit(4);
}
printf("Maximum IUCV connections: %d\n",maxconns);
/*----------------------------------------------------------------+
| Declare another name for connecting to *IDENT. |
+----------------------------------------------------------------*/
if ((rc = iucvset("IDENTHAN",&maxconns)) != 0) {
printf("Return code from iucvset IDENTHAN was %d\n",rc);
exit(8);
}
/*----------------------------------------------------------------+
| Create an *IDENT parameter list. |
+----------------------------------------------------------------*/
memset(&ident, 0 ,sizeof(ident));
memcpy(ident.name, "APPCSERV", 8);
ident.fcode = MANAGE_RESOURCE;
ident.flag = ALLOW_SECURITY_NONE;
ident.ntype = RESOURCE_ID;
/*----------------------------------------------------------------+
| Stow "*IDENT" in IPVMID and copy *IDENT parms to CONNECT plist. |
| Execute an IUCV CONNECT to *IDENT. |
+----------------------------------------------------------------*/
memset(&conn, 0, sizeof(conn));
memcpy(conn.vmid, "*IDENT ", 8);
memcpy(conn.pgm, &ident, sizeof(ident));
rc = iucvconn("IDENTHAN", &conn);
if (rc != 0) {
printf("Return code from iucvconn IDENTHAN was %d\n",rc);
if (rc == 1)
printf("IPRCODE = x'%X'\n",conn.ip.rcode);
exit(12);
}
ident_pathid = conn.pathid; /* Save IDENTHAN pathid */
sigpause(0); /* Wait for CONNECTION COMPLETE */
/* from *IDENT */
/*----------------------------------------------------------------+
| Wait for initial CONNECTION PENDING from APPCSEND. |
+----------------------------------------------------------------*/
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("APPCSERV");
iucvclr("IDENTHAN");
exit(0);
}
#pragma eject
/*-------------------------------------------------------------------+
| SIGIUCV signal handler. Signals are blocked until return. |
+-------------------------------------------------------------------*/
void appctrap(void)
{
struct appc_send_plist recv; /* used to receive allocate */
struct appc_send_plist *send; /* APPC SEVER plist pointer */
appc_conn_data *XID; /* Pointer to external interrupt */
/* data returned by siginfo. */
int rc; /* Return code from iucvacc. */
ident_parms ident; /* so we can test RCODE */
char *allocate_data; /* ptr to allocate data */
/*----------------------------------------------------------------+
| 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_PENDING:
/* Retrieve allocation data */
allocate_data = malloc(XID->bf2.ln);
memset(&recv, 0, sizeof(recv));
recv.pathid = XID->pathid;
recv.ip2.flags2 = IPWAIT;
recv.bf1.adr = allocate_data;
recv.bf1.ln = XID->bf2.ln;
rc = appcrecv(&recv);
if (rc != 2) {
printf("Error %d receiving allocation data\n", rc);
printf("IPRCODE = x'%X'\n", recv.ip1.rcode);
printf("IPAUDIT = %x\n", recv.audit);
exit(16);
}
XID->ip1.type = 0; /* Accept the connection */
XID->ip2.flags2 = 0;
if ((rc = iucvacc("APPCSERV",
(struct iucv_path_plist *) XID)) != 2) {
printf("Return code from iucvacc = %d\n",rc);
if (rc == 1)
printf("IPRCODE = x'%X'\n",XID->ip1.rcode);
exit(20);
}
connects++; /* Keep track of the number of */
break; /* connections made. */
case APPC_INCOMING_MSG:
/* Call message handler */
rcvrply((struct appc_send_plist *)XID);
break;
case PATH_SEVERED:
/* *IDENT decided to stop. */
if (XID->pathid == ident_pathid) {
memcpy(&ident, XID->resid, sizeof(ident));
if (ident.rcode != 0x00) {
printf("*IDENT path severed. rcode = %x\n", ident.rcode);
exit(24);
}
}
else { /* An IUCV sever? Really? */
printf("Unexpected sever. IPPATHID = %d\n", XID->pathid);
exit(28);
}
break;
case CONNECTION_COMPLETE:
/* *IDENT connection complete */
if (XID->pathid == ident_pathid) {
puts("Connection to *IDENT complete\n");
}
else { /* Some other connection? */
printf("Unexpected connection complete. Path = %d\n",
XID->pathid);
exit(32);
}
break;
case APPC_SEVER_INTERRUPT:
/* APPCSEND decided to stop. */
send = (struct appc_send_plist *) XID;
send->ip2.flags2 = IPWAIT;
send->sendop = IPSNORM;
send->bf1.adr = NULL;
send->bf1.ln = 0;
if ((rc = appcsevr("APPCSERV", send, "ONE")) != 2) {
printf("Return code from appcsevr = %d\n",rc);
printf("IPRCODE is x'%X'\n", send->ip1.rcode);
exit(36);
}
connects--; /* Update number of connections. */
break;
default: /* Handle other interrupt types. */
printf("Unexpected interrupt type %d\n",XID->ip1.type);
fflush(stdout);
abort();
}
/*----------------------------------------------------------------+
| Re-establish this function as the SIGIUCV signal handler. |
+----------------------------------------------------------------*/
signal(SIGIUCV, appctrap);
return;
}
#pragma eject
/*-------------------------------------------------------------------+
| Function to issue APPC RECEIVE and print the message. |
+-------------------------------------------------------------------*/
static void rcvrply(struct appc_send_plist *int_data)
{
int msg_len; /* Incoming message length. */
struct senddata {
unsigned short length; /* length of data to send */
char message(|120+2|); /* Message buffer. */
} logrec;
int rc = 0; /* return code */
/*----------------------------------------------------------------+
| Create APPC RECEIVE parameter list using the external |
| interrupt data area. Issue the APPC RECEIVE. |
+----------------------------------------------------------------*/
int_data->ip2.flags2 = IPWAIT;
int_data->bf1.adr = (char *) &logrec;
int_data->bf1.ln = sizeof(logrec);
rc = appcrecv(int_data);
if (rc != 2) {
printf("Return code from receive = %d\n", rc);
printf("IPRCODE is x'%X'\n", int_data->ip1.rcode);
exit(40);
}
/*----------------------------------------------------------------+
| Perhaps the sender wants to sever. If so, confirm sever. |
+----------------------------------------------------------------*/
if (int_data->ip2.whatrc == IPCNFSEV) {
int_data->sendop = IPCNFRMD;
if ((rc = appcscfd(int_data)) != 2) {
printf("Error %d attempting to confirm sever\n", rc);
printf("IPRCODE is x'%X'\n", int_data->ip1.rcode);
exit(44);
}
return;
}
/*----------------------------------------------------------------+
| If the return code is anything else, bad news. |
+----------------------------------------------------------------*/
if (int_data->ip2.whatrc != IPSEND) {
puts("Protocol error. Sender not in receive state\n");
exit(48);
}
/*----------------------------------------------------------------+
| Upon return, int_data->bf2.ln contains the number of unused |
| bytes in the message buffer. Print the message. |
+----------------------------------------------------------------*/
msg_len = sizeof(logrec) - int_data->bf2.ln - 2;
printf("SENDER says \"%.*s\"\n", msg_len, logrec.message);
/*----------------------------------------------------------------+
| Prompt for a reply message. If EOF, quit. |
+----------------------------------------------------------------*/
fgets(logrec.message, sizeof(logrec.message), stdin);
if (feof(stdin)) {
puts("Terminating due to end-of-file.\n");
exit(52);
}
/*----------------------------------------------------------------+
| Fill in APPC SENDDATA parameter list with buffer address/length.|
| Send reply. |
+----------------------------------------------------------------*/
int_data->ip2.flags2 = IPWAIT;
int_data->sendop = IPDATA;
int_data->bf1.adr = (char *) &logrec;
logrec.length = strlen(logrec.message) + 1;
int_data->bf1.ln = logrec.length;
rc = appcsdta(int_data);
if (rc != 2) {
printf("Error %d on reply SENDDATA\n", rc);
printf("IPRCODE is x'%X'\n", int_data->ip1.rcode);
exit(56);
}
/*----------------------------------------------------------------+
| We are still in SEND state. Ask to turn conversation around. |
+----------------------------------------------------------------*/
int_data->ip2.flags2 = IPWAIT;
int_data->sendop = IPPREPRC;
if ((rc = appcscnf(int_data)) != 2) {
printf("Error requesting confirmation to receive. rc = %d\n",
rc);
printf("IPRCODE = x'%X'\n", int_data->ip1.rcode);
exit(60);
}
}
|