 /********************************************************
 *                                                       *
 *            PROCESS FMH-5                              *
 *                                                       *
 * This procedure handles the processing of the          *
 * the FMH-5 record (Attach).                            *
 *                                                       *
 * INPUT : the FMHCOM record                             *
 *                                                       *
 * OUTPUT: if error : build the fmh-7 and send it, or    *
 *                    close the session.                 *
 *         if no error: call appl. program (pointer to   *
 *                      wich was set in the ATTACH_LU    *
 *                      record.                          *
 *                                                       *
 *                                                       *
 * CopyRight 1995. Nicholas Poljakov all rights reserved.*
 *                                                       *
 ********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <signal.h>
#include <fcntl.h>
#include <fmh5.h>
#include <fmh7.h>
#include <fmhcom.h>
#include <prefix.h>
#include <rcb.h>
#include <tcb.h>
#include <lucb.h>
#include <drcb.h>
#include <rcbd.h>
#include <crtp.h>
#include <state1.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

int tpst_pid;
int tpst_fd[2];
int got_sig;
int semid;
struct lucb lu6;
unsigned long upmex(void *, void *);
unsigned long calltpn(void *, void *);
unsigned long rmfmh5(void *, void *);
int bldfmh7(struct rcb *, unsigned long);
int psrm(int, void *, void *);
int proterr(struct rcb *, unsigned long);
int dcp(struct tcb *);
int buffmng(unsigned char, void *, void *, void *, unsigned, unsigned char, unsigned);
int sendhsf(void *);

pfmh5(s_ptr)
char *s_ptr;
{
    unsigned int code;
    unsigned long sense;
    struct cma { /* RM fills this structure */
                 struct tcb *p_tcb;
                 struct rcb *p_rcb;
               } ar;
    struct rcb *p_rcb;
    struct tcb *p_tcb;
    struct drcb a_drcb;
    struct rcbd a_rcbd;

#if OS_TYPE == 1
/*********  Trace facility **********/
unsigned int rtype;   /* type of record */
unsigned int pnum;    /* point number */
char pname[8];        /* name of module */
char *drec;       /* record for dump */
int  lenr;            /* record length */

rtype = INPROC;
strcpy(pname, "pfmh5");
pnum = 1;
drec = s_ptr;
lenr = 200;
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif

    sense = rmfmh5(s_ptr, &ar); /* Call RM for check header*/
    switch (sense) {
        case 0x00000000 :
                          { /* Load and call TP */
                            sense = upmex(s_ptr, &ar);
                            if (sense == 0) {
				return 0;
                            }
                            p_rcb = ar.p_rcb;
                            bldfmh7(p_rcb, sense);
                          /* Deallocate RCB */
                            p_tcb = ar.p_tcb;
                            a_drcb.p_tcb = p_tcb;
                            a_drcb.p_rcb = p_rcb;
                            code = DEALLOCATE_RCB;
                            psrm(code, &a_drcb, &a_rcbd);
                            break;
                          }
        case 0x1008200e :
        case 0x10086000 :
        case 0x10086005 :
        case 0x10086009 :
        case 0x10086011 :
        case 0x10086040 :
                          { /* deactivate session */
                            p_rcb = ar.p_rcb;
                            if (p_rcb == NULL) {
                                break;
                            }
                            proterr(p_rcb, sense);
			    dcp(p_tcb);
                            break;
                          }
        default:
                          {
                            p_rcb = ar.p_rcb;
                            if (p_rcb != NULL) {
                                bldfmh7(p_rcb, sense);
                              /* Deallocate RCB */
                                p_tcb = ar.p_tcb;
                                a_drcb.p_tcb = p_tcb;
                                a_drcb.p_rcb = p_rcb;
                                code = DEALLOCATE_RCB;
                                psrm(code, &a_drcb, &a_rcbd);
                            }
                            break;
                          }

     }
}
unsigned long upmex(s_ptr, ar)
char *s_ptr;
struct cma { /* RM fills this structure */
             struct tcb *p_tcb;
             struct rcb *p_rcb;
           } *ar;
/*
 * Call the user defined subroutine as a trans. prog.
 */
{
    struct FMH5 *p_fmh5;
    struct crtp *p_crtp;
    struct lucb *p_lucb;
    struct tcb *p_tcb;
    struct rcb *p_rcb;
    struct fmhcom *p_fmh;
    struct LUOW1 *p_luow;
    char *p;
    int i;
    unsigned char cnt;
    unsigned long sense;

    p_fmh = (struct fmhcom *)s_ptr;
    p_fmh5 = (struct FMH5 *)(p_fmh -> ru);
    p_luow = (struct LUOW1 *)&((*p_fmh5).tpname);
    cnt = p_fmh5 -> lntpn;
    p_luow = (char *)p_luow + cnt;

    p_tcb = ar -> p_tcb;
    p_rcb = ar -> p_rcb;
    p_lucb = p_tcb -> p_lucb;

    if ((p_crtp = calloc(1, sizeof(struct crtp))) == NULL) {
        sense = 0x084b6031; /* trans_pgm_not_avail_retry */
        return(sense);
    }
    /*
     * Initialisation the CREATE_TP record
     */
    p_crtp -> code = 0x2300;
    p_crtp -> sense = 0;
#if OS_TYPE == 1
    p_crtp -> rsrv4.semid = semid;
#endif
    memcpy(p_crtp -> tp_id, p_tcb -> tcb_id, 8);
    memcpy(p_crtp -> lu_id, p_lucb -> lu_id, 8);
    p_crtp -> conv_id = p_rcb -> rcb_id;
    p_crtp -> type = 0; /* Basic */
    p_crtp -> sync_level = 0; /* None */
    memcpy(p_crtp -> mode_name, p_rcb -> mode_name, 8);
    memcpy(p_crtp -> partner, p_rcb -> lu_name, 8);
    if (p_luow -> lnluw != 0) {
        p = &((*p_luow).fqnam);
        cnt = p_luow -> lnfqn;
        memcpy(p_crtp -> flun, p, cnt);
        p_crtp -> flun_lt = cnt;
    }

    cnt = p_fmh5 -> lntpn;
    memset(p_crtp -> tp_name, 0, 64);
    p = &((*p_fmh5).tpname);
    memcpy(p_crtp -> tp_name, p, cnt);
    strcpy(p_crtp -> rsrv1, lu6.lu_name);
    for (i = 7; i > 0; i--) {
        if ((p_crtp -> rsrv1[i] == 0)||(p_crtp -> rsrv1[i] == 32)) {
            p_crtp -> rsrv1[i] = 0x0;
        }
    }
    sense = calltpn(p_crtp, p_tcb);
    return(sense);
}
/*
 * Build the function management header type 7.
 * 1) Purge an output queue;
 * 2) Built the FMH-7 and insert it into the output queue;
 * 3) Call Sendhs to flush output queue and send the FMH-5.
 */
int bldfmh7(p_rcb, sense)
struct rcb *p_rcb;
unsigned long sense;
{
    struct FMH7 *p_fmh7;
    struct prefix *p_prf;
    char *p;
    char p1;
    unsigned int type;
    unsigned char lt;

    lt = sizeof(struct FMH7);
    p_fmh7 = malloc(lt);
    p_fmh7 -> length = lt;
    p_fmh7 -> type = 7;
    memcpy(p_fmh7 -> sense, &sense, 4);
#if OS_TYPE == 0 /* MS-DOS */
    p1 = p_fmh7 -> sense[0];
    p_fmh7 -> sense[0] = p_fmh7 -> sense[3];
    p_fmh7 -> sense[3] = p1;
    p1 = p_fmh7 -> sense[1];
    p_fmh7 -> sense[1] = p_fmh7 -> sense[2];
    p_fmh7 -> sense[2] = p1;
#endif
    p_fmh7 -> nfld = 0;
/*
 * Purge the output and input queues.
 */
    p = (char *)(p_rcb -> first_out);
    p1 = 'D';
    p_prf = p_rcb -> first_out;
    while (p_prf != NULL) {
        buffmng(p1, p_prf, p, p_rcb,0,0,0); /* Delete buff. */
        p_prf = p_prf -> next;
    }
    p = (char *)(p_rcb -> first_in);
    p1 = 'D';
    p_prf = p_rcb -> first_in;
    while (p_prf != NULL) {
        buffmng(p1, p_prf, p, p_rcb,0,0,0); /* Delete buff. */
        p_prf = p_prf -> next;
    }
/*
 * Place the FMH-7 in output queue.
 */
    p = (char *)(p_rcb -> first_out);
    p1 = 'A';
    type = Fmh;
    buffmng(p1, p_fmh7, p, p_rcb, lt, 0, type);

    sendhsf(p_rcb); /* Flush output queue */
}
#if OS_TYPE == 1
unsigned long calltpn(p, p_tcb)
struct crtp *p;
struct tcb *p_tcb;
{
    struct rsp {
                  int long unsigned sense;
                  int tp_pid;
               } rs;
    char p1[40];
    char p2[6];
    char buff[7];
    int i;
    int cnt;
    int *j;
    int lu_pid;
    int short resp;
    int flags;
/*********  Trace facility **********/
unsigned int rtype;   /* type of record */
unsigned int pnum;    /* point number */
char pname[8];        /* name of module */
char *drec;       /* record for dump */
int  lenr;            /* record length */

rtype = INPROC;
strcpy(pname, "calltpn");
pnum = 1;
drec = p;
lenr = sizeof(struct crtp);
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/

    if ((cnt = write(tpst_fd[1], p, sizeof(struct crtp))) < 0) {
        return (0x084c0000); /* tp not available no retry */
    }
printf("LUPS...calltpn WRITE O.K!...cnt = %d\n",cnt);
    kill(tpst_pid, SIGUSR1);
    while (got_sig == 0);  /* Wait for signal from TPST */
    got_sig--;
    if ((cnt = read(tpst_fd[0], &rs, sizeof(struct rsp))) < 0) {
        return (0x084c0000); /* tp not available no retry */
    }
printf("LUPS...calltpn READ O.K!...cnt = %d\n",cnt);

/***********************************/
rtype = GREC;
strcpy(pname, "calltpn");
pnum = 2;
drec = &rs;
lenr = sizeof(struct rsp);
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/

    if (rs.sense == OK) {
        strcpy(p1, PPATH);
        strcat(p1, "tp");
        sprintf(p2, "%d", rs.tp_pid);
        strcat(p1, p2);
        mknod(p1, IFIFO|0666, 0);
        if ((p_tcb -> tp_fd = open(p1, O_RDWR | O_NDELAY)) < 0) {
            rs.sense = 0x084c0000; /* tp not available no retry */
            kill(rs.tp_pid, SIGKILL);
            return(rs.sense);
        }
printf("LUPS...calltpn...fifo to TP now is open...\n");
        if ((flags=fcntl(p_tcb -> tp_fd,F_GETFL,0))== -1)  {
            rs.sense = 0x084c0000; /* tp not available no retry */
            kill(rs.tp_pid, SIGKILL);
            close(p_tcb -> tp_fd);
            return(rs.sense);
        }
        if (fcntl(p_tcb -> tp_fd,F_SETFL,flags & ( 0xffff - O_NDELAY) ) == -1) {
            rs.sense = 0x084c0000; /* tp not available no retry */
            kill(rs.tp_pid, SIGKILL);
            close(p_tcb -> tp_fd);
            return(rs.sense);
        }
        /* Read response from TP */
        if ((cnt = read(p_tcb -> tp_fd, &resp, sizeof(short))) < 0) {
            rs.sense = 0x084c0000; /* tp not available no retry */
            kill(rs.tp_pid, SIGKILL);
            close(p_tcb -> tp_fd);
            return(rs.sense);
        }
printf("LUPS...calltpn...response from TP was received...\n");
        flags = O_WRONLY & (0xffff - O_NDELAY);
        if (fcntl(p_tcb -> tp_fd,F_SETFL,flags) == -1) {
            rs.sense = 0x084c0000; /* tp not available no retry */
            kill(rs.tp_pid, SIGKILL);
            close(p_tcb -> tp_fd);
            return(rs.sense);
        }
        /* Write to TP create_TP record */
        if ((cnt = write(p_tcb -> tp_fd, p, sizeof(struct crtp))) < 0) {
            rs.sense = 0x084c0000; /* tp not available no retry */
            kill(rs.tp_pid, SIGKILL);
            close(p_tcb -> tp_fd);
            return(rs.sense);
        }
printf("LUPS...calltpn...write to TP O.K! cnt = %d\n", cnt);

        /* Set tp_id */
        p_tcb -> tp_pid = rs.tp_pid;
    }

    return(rs.sense);
}
handler()
        {
            got_sig++;
            return 0;
        }
#endif
#if DEBUG == 1
unsigned long calltpn(p, p_tcb)
struct crtp *p;
struct tcb *p_tcb;
{
    return (0);
}
#endif
