/*
 *                    ALLOCATE
 *
 * Function: This function is intended to allocation
 *           resources for transaction program.
 *           The Resource Control Block will be created
 *           in case if all supplied parameters are correct.
 *
 *           For detailed description of the ALLOCATE request
 *           see the "SNA Transaction Programmer's Reference Manual".
 *
 * Input: ALLOCATE structure.
 * Output: a return code in the ALLOCATE structure.
 *
 * CopyRight 1995. Nicholas Poljakov all rights reserved.
 *
 */
#include <alloc.h>
#include <tcb.h>
#include <mode.h>
#include <lucb.h>
#include <arcb.h>
#include <state1.h>
#include <rcballoc.h>
#include <partner.h>
#include <repass.h>
#include <rcb.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#if OS_TYPE == 1
#include <memory.h>
#endif

struct psp {
       struct lucb *lucb_list_ptr; /* pointer to lucb list */
       struct tcb  *tcb_list_ptr ; /* pointer to tcb  list */
       struct rcb  *rcb_list_ptr ; /* pointer to rcb  list */
       char    *param;
     } psp_ini;

int sk_r_wt(void *);
int SendBlock(void *, void *);
int setrc(void *, void *);
int sendhsf(void *);
int sendhs(void *);
int sendbm(void *, void *);
int sendat(void *);
int rtsend(void *);
unsigned long rmfmh5(void *, void *);
int recwait(void *);
int rcvru(void *, void *);
int rcvhs(void *, void *, void *, void *);
int ralloc(void *, void *);
int psrm(int, void *, void *);
int ps_conv(int, void *);
int proterr(void *, unsigned long);
int preptrcv(void *, void *);
int post_rcb(void *);
struct repass *postopen(void *);
int phsrec(void *);
int pfmh5(void *);
int opndst(void *);
int obtsess(void *, unsigned char);
int Lrf_handler(void *);
int get_sess(void *, void *);
int get_attr(void *);
int fsm_error(unsigned char, void *);
int fsm_conv(unsigned char, unsigned char, void *);
int flush (void *);
int dcp(void *);
int dealloc(void *);
int crtp(void *);
int conv(void *);
int chkparm(void *, void *);
int check_end(unsigned int, void *);
struct rqb *call_appl(void *);
int buffmng(unsigned char, void *, void *, void *, unsigned, unsigned char, unsigned);
unsigned long attltck(void *);
unsigned long attacheck(void *);
char *cgetmem(int, int);
int sendhsf(void *);
int opndst(void *);
int alloc_rcb(void *, void *);
int clsdst(void *);

allocate(pptr)
struct allocate *pptr;
 {
struct arcb *alloc_rcb;
struct rcballoc *rcb_alloc;
struct mode *temp2;
struct lucb *p_lucb;
struct lucb *temp1;
struct pnlu *temp;
struct pnlu *save;
struct tcb *p_tcb;
struct rcb *p_rcb;
struct repass *p_rep;
int code_rec;
char mode[9];
char lu[9];
char tp[9];
int  i;
int  k;

#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, "allocat");
pnum = 1;
drec = pptr;
lenr = sizeof(struct allocate);
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif

    if ((alloc_rcb = calloc(1, sizeof(struct arcb))) == NULL) {
         pptr -> prim_rc = PORT_ABENDED;
         return (0);
    }
    if ((rcb_alloc = calloc(1, sizeof(struct rcballoc))) == NULL) {
         pptr -> prim_rc = PORT_ABENDED;
         free(alloc_rcb);
         return (0);
    }
    p_rep = (struct repass *)pptr;

    /* Проверка наличия lu с именем заданным в
     * примитиве allocate.
     */
    for (i = 0; i < 8; i++) {
        lu[i] = pptr -> p_lu_name[i];
        mode[i] = pptr -> mode_name[i];
        tp[i] = pptr -> tp_id[i];
    }
    mode[8] = 0;
    lu[8] = 0;
    tp[8] = 0;

    temp1 = psp_ini.lucb_list_ptr;
    p_tcb = temp1 -> tcb_list_ptr;

/*
 * Seek for tr. prog. idetifier
 */
    while (p_tcb != NULL) {
       if ((k = memcmp(p_tcb -> tcb_id, tp, 8)) != 0)
             p_tcb = p_tcb -> next;
           else
              break;
    }
    if (p_tcb == NULL) {
       pptr->prim_rc = PARAMETR_CHECK;
       pptr->sec_rc = BAD_TP_ID;
       goto alloc_exit;
    }
    alloc_rcb -> p_tcb = p_tcb; /* Set tcb pointer in alloc_rcb record*/
    p_rep -> tp_fd = p_tcb -> tp_fd;

    temp = temp1 -> pluptr;  /* pointer to partner lu */
/*
 * Seek for partner_lu
 */
    while (temp != NULL) {
        if (memcmp(temp -> lu_name, lu, 8) != 0)
           temp = temp -> next;
        else
           break;
    }
    if (temp == NULL) {
       pptr->prim_rc = PARAMETR_CHECK; /* lu which has that name was not found */
       pptr->sec_rc = INVALID_LU_NAME;
       goto alloc_exit;
    }

    save = temp; /* Save pointer to partner_lu_block */

    temp2 = temp->m_ptr; /* pointer to MODE block */
    if ((k = memcmp(mode, temp2 -> name, 8)) != 0) {
       pptr->prim_rc = PARAMETER_ERROR; /* block mode
                                       * with that name not found */
       pptr->sec_rc = INVALID_MODE_NAME;
       goto alloc_exit;
    }
    if (pptr -> tp_lt == 0)
       goto dcp_ex;
    if (pptr -> conv_type == MAPPED)
       goto dcp_ex; /* mapped conversation not supported*/
    if (pptr -> return_control == DELAYED_ALLOCATION_PERMITED)
       goto dcp_ex; /* this option not supported*/

    memcpy(alloc_rcb -> lu_name, pptr -> p_lu_name, 8);
    memcpy(alloc_rcb -> mode_name, pptr->mode_name, 8);

   /* Synchronous RM call */
    code_rec = ALLOCATE_RCB;
    psrm(code_rec, alloc_rcb, rcb_alloc);
    p_rcb = rcb_alloc -> rcb_ptr;
    p_rcb -> p_partner = save; /* Pointer to Partner_LU */
    p_rcb -> verb_ptr = pptr;
    p_rcb -> verb_code = Allocate;

    if (save -> lu_type == 0) {
      /* Allocate for LU type 0 */
        if (rcb_alloc -> rc == OK) {
             obtsess(p_rcb, ATTACH);
             if (p_rcb -> error_state != NO_RQS) {
                pptr -> prim_rc = UNSUCCESSFUL;
                goto alloc_exit;
             }
             pptr -> prim_rc = OK;
	     pptr -> conv_id = p_rcb -> rcb_id;
        }
        else
                pptr -> prim_rc = UNSUCCESSFUL;
        goto alloc_exit;
    }

 /* Make the rcb_allocated request for building an FMH-5 and return code
  * setting.
  */
    ralloc(rcb_alloc, pptr);
    goto alloc_exit;

 dcp_ex :
    p_lucb = psp_ini.lucb_list_ptr;
    if (p_lucb == NULL) {
        pptr -> prim_rc = PORT_ABENDED;
        goto alloc_exit;
    }
    p_tcb = p_lucb -> tcb_list_ptr;
    if (p_tcb == NULL) {
        pptr -> prim_rc = PORT_ABENDED;
        goto alloc_exit;
    }
    while (p_tcb != NULL) {
        if (memcmp(pptr -> tp_id, p_tcb -> tcb_id, 8) == 0) {
                goto Call_dcp;
        }
        p_tcb = p_tcb -> next;
    }
    pptr -> prim_rc = PORT_ABENDED;
    goto alloc_exit;

 /* Call the deallocation_cleanup procedure because of abend condition */
    Call_dcp :

    dcp(p_tcb);
    alloc_exit:
                free(alloc_rcb);
                free(rcb_alloc);
                return (0);
}
