 /*
 *
 *                        RCVHS
 *                Receive records from HS
 *   This function receives records from the HS and places it
 *   into the input queue to the RCB.
 *
 *   Records received from the HS make the list "RCB -> first_in".
 *   The text and other info from that list  will be moved to buff.
 *
 *   INPUT :  - count for received characters; pointer to RCB,
 *              pointer to type field, data buffer.
 *
 *   OUTPUT:  - return code as follow:
 *            0 - OK;
 *            2 - system error in HS or in here.
 *
 *  CopyRight 1995. Nicholas Poljakov all rights reserved.
 *
 */
#include <stdio.h>
#include <state1.h>
#include <rcb.h>
#include <prefix.h>
#include <malloc.h>
#include <string.h>
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 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 allocate(void *);
int clsdst(void *);

int rcvhs(p_cnt, p_rcb, p_type, buff)
int *p_cnt;  /* on input : max. length;
              * on output: data length */
struct rcb *p_rcb;
unsigned int *p_type; /* type of record (DFC code) */
char *buff;  /* data buffer */
{
    struct prefix *p_prf;
    struct prefix *t_prf;
    int i;
    int j;
    int lim;
    char *p;
    char *p1;

#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, "rcvhs");
pnum = 1;
drec = p_rcb;
lenr = sizeof(struct rcb);
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif


    if (p_rcb -> hsps == No) {
        goto rcv_exit_1;
    }
    if ((p_prf = p_rcb -> first_in) == NULL) {
        goto rcv_exit_1;
    }
    if (*p_cnt <= 0) {
        lim = MAX_RU;
    }
    else
        lim = *p_cnt;
    i = p_prf -> lt_text;
#if OS_TYPE == 1 /* Unix System V */
printf("LUPS...rcvhs...len = %d, lim = %d\n", i, lim);
#endif
    if (i > lim) {
       /* buff is full; insert new element in the
        * RCB -> first_in chain.
        */
        i = lim;
        j = p_prf -> lt_text - i;
        if ((t_prf = malloc(sizeof(struct prefix) + j)) == NULL) {
            goto rcv_exit_2;
        }
        p = (char *)t_prf + sizeof(struct prefix);
        t_prf -> next = p_prf -> next;
        t_prf -> prev = p_prf;
        t_prf -> text = p;
        t_prf -> lt_text = j;
        t_prf -> type = p_prf -> type;
        p_prf -> type = Send_data;
        t_prf -> dsc = p_prf -> dsc;
        p_prf -> next = t_prf;
        p_prf -> lt_text = i;
        p1 = p_prf -> text;
        p1 += i;
        memcpy(p, p1, j);
    }
    /*
     * Delete the first element from the input chain.
     */

    *p_type = p_prf -> type;
    *p_cnt = i;
    memcpy(buff, p_prf -> text, i);

    free(p_prf -> text);
    t_prf = p_prf;
    p_prf = p_prf -> next;
    free(t_prf);
    if (p_prf != NULL) {
        p_rcb -> first_in = p_prf;
        p_prf -> prev = NULL;
    }
    else
            p_rcb -> first_in = NULL;

    if (p_rcb -> first_in == NULL) {
        p_rcb -> hsps = No;
    }
		   fsm_error(RESET, p_rcb);
                   return(0);
     rcv_exit_1 :
		   fsm_error(CONV_FAIL_SON, p_rcb);
                   return (1);
     rcv_exit_2 :
		   fsm_error(Receive_error, p_rcb);
                   return (2);
}
