/* Copyright (C) Magna Carta Software, Inc., 1990. All Rights Reserved. C COMMUNICATIONS TOOLKIT RXXFER.C -- ROUTINES TO HANDLE FILE RECEPTION. */ #define CCT_DEVELOPMENT #include #if (defined(MSC) || defined(__WATCOMC__) || defined(_INTELC32_)) #include #elif defined(__TURBOC__) || defined(__POWERC) #include #endif #include #include #include #include /* MSC v6.0A bugs force sub-optimization of this file To see the problem, try $(C_OPT) instead of $(C_OPTR) in small model */ #if defined(_MSC_VER) #pragma optimize("e", off) #endif char *ftempname = "temp0001.$$$"; char fname[PATHLEN]; /* received file name from remote */ unsigned long fsize; /* received file size from remote */ unsigned long fdate; /* received file dtae from remote */ /* C_FPUTC_ -- Add a byte to the receive buffer. If it is full, write it to disk. The disk write resets the buffer pointer. Return value: 0 -- Normal return; DISK_FULL -- insufficient disk space for file; */ short c_fputc_(COMM_PORT *p, short ch) { short ret = 0; XFER *x = p->x; #if XDEBUG if (ch == '\0') fputc(ch, stdout); #endif *x->pb = (BYTE) ch; x->pb++; if (x->pb > x->high) ret = c_fwrite_(p, x); return ((short) ret); } /* C_FWRITE_ -- Write the received data in x->buf to disk. If high level flow control is enabled, it is used. Return value: 0 -- no error; DISK_FULL -- insufficient disk space to write file; */ short c_fwrite_(COMM_PORT *p, XFER *x) { short save_rts, save_dtr, f_xoff = FALSE; short ret = 0; #if XDEBUG printf("\nEntering c_fwrite"); #endif /* IF FLOW CONTROL IS ASSERTED, TURN FLOW OFF */ if (p->flowctl & TX) { if (p->flowctl & TXONXOFF) { if (p->inhold & TXONXOFF) { p->inhold &= ~TXONXOFF; f_xoff = TRUE; } else c_putc(p, p->xoffchar); } if (p->flowctl & TRTS_CTS) { save_rts = get_rts(p); set_rts(p, LOW); } if (p->flowctl & TDTR_DSR) { save_dtr = get_dtr(p); set_dtr(p, LOW); } ms_pause(150); /* wait for flow control to take effect */ } ret = x->pb - x->buf; x->pb = x->buf; ret = cct_file_write_(x->fh, x->buf, ret); if (ret == EOF) { if (x->error != NULL) x->error[-DISK_FULL - XERROR_OFFSET]++; if (x->p_user != NULL) (*x->p_user)(p, DISK_FULL, 0L); ret = DISK_FULL; } if (ret > 0) ret = 0; /* IF FLOW CONTROL IS ASSERTED, TURN FLOW ON */ if (p->flowctl & TX) { if (p->flowctl & TXONXOFF) { if (f_xoff) p->inhold |= TXONXOFF; else c_putc(p, p->xonchar); } if (p->flowctl & TRTS_CTS) set_rts(p, save_rts); if (p->flowctl & TDTR_DSR) set_dtr(p, save_dtr); } return ((short) ret); } /* C_CALLOC_ -- Allocate memory for file receive buffer. Return value: 0 -- normal return (success); -1 -- Insufficient memory for receive buffer; */ short c_calloc_(XFER *x, unsigned bufsize) { short ret = 0; DWORD ramavail = memavail(); ramavail = (memavail() > (DWORD) UINT_MAX) ? (DWORD) UINT_MAX : ramavail; if (ramavail < MIN_BUFFER_SIZE + HEADROOM) ret = EOF; else { /* ADJUST BUFSIZE TO > MIN. */ bufsize = (bufsize > MIN_BUFFER_SIZE) ? bufsize : MIN_BUFFER_SIZE; /* ADJUST BUFSIZE FOR AVAILABLE RAM */ if (ramavail < bufsize + HEADROOM) bufsize = (unsigned) ramavail - HEADROOM; x->pb = x->buf = (char *) memcalloc(bufsize, sizeof(char)); x->len = bufsize; /* file receive buffer length */ x->high = x->buf + bufsize - MIN_BUFFER_SIZE/2; /* file receive buffer highwater mark */ #if XDEBUG printf("\nx->buf is %Fp, x->high is %Fp\n", x->buf, x->high); printf("\nThe buffer length (difference) is %ld, x->len is %Fp\n", x->high - x->buf, x->len); #endif } return (ret); } /* FRECEIVE - Receive files from a communications port. Return value: 0 -- normal return (success); -1 -- Insufficient memory for receive buffer; -2 -- unable to open file; */ short freceive(COMM_PORT *p, XFER *x, short protocol, unsigned bufsize, short (CDECL_ *progress)(struct comm_port *, short, DWORD)) { short ret = 0, f_flow = FALSE; WORD save_kbd_clear; p->x = x; x->num_files = 0; if ((ret = c_calloc_(x, bufsize)) != 0) return (ret); if (!ret) { save_kbd_clear = kbd_clear; kbd_clear = TRUE; if (x->ibdelay == 0) x->ibdelay = XFER_IBDELAY; /* initialize interbyte delay */ if (x->retries == 0) x->retries = XFER_RETRIES; /* init. retries */ if (progress != NULL) x->p_user = progress; /* enable progress reports */ x->error = a_xfer_errors; /* enable error recording */ /* CHOOSE THE FILE TRANSFER PROTOCOL */ switch(protocol) { case ASCII: ret = rx_ascii_(p); break; case KERMIT: if (x->k == NULL) k_init(p, x, NULL); ret = k_rcv_(x->k); break; case XMODEM: x->chk = checksum; x->poll = NAK; x->protocol = XMODEM; ret = rx_xmodem_(p, x); break; case XMODEM_CRC: x->chk = crc_ccitt; x->poll = 'C'; x->protocol = XMODEM_CRC; ret = rx_xmodem_(p, x); break; case YMODEM: case XMODEM_1K: x->chk = crc_ccitt; x->poll = 'C'; x->protocol = XMODEM_1K; ret = rx_xmodem_(p, x); break; case YMODEM_G: x->chk = crc_ccitt; x->poll = 'G'; x->protocol = YMODEM_G; /* IF NO FORM OF FLOW CONTROL IS BEING ASSERTED, USE XONXOFF */ if (!(p->flowctl & TX)) { set_tx_xlat(p, FLOWCTL, XONXOFF); f_flow = TRUE; } ret = rx_xmodem_(p, x); if (f_flow) p->flowctl &= ~XONXOFF; break; case ZMODEM: if (p->ppb == NULL) z_init(p, CANFDX | CANOVIO | CANBRK | CANFC32, 0, 0); ret = z_receive_(p); break; case FAST: break; default: break; } } ffreebuf_(x); kbd_clear = save_kbd_clear; return (ret); }