home *** CD-ROM | disk | FTP | other *** search
- /* Utils.c: Miscellaneous support routines for xprzmodem.library;
- Version 2.0, 28 October 1989, by Rick Huebner.
- Released to the Public Domain; do as you like with this code. */
-
-
- #include <proto/all.h>
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "xproto.h"
- #include "zmodem.h"
- #include "xprzmodem.h"
-
- /* Transfer options to use if XProtocolSetup not called */
- struct SetupVars Default_Config = {
- NULL, NULL, 0,
- { "C" }, { "N" }, { "16" }, { "0" }, { "N" },
- { "N" }, { "Y" }, { "N" }, { "Y" }, { "" }
- };
-
- #ifdef DEBUGLOG
- UBYTE DebugName[] = "Log:ZDebug.log";
- void *DebugLog = NULL;
- #endif
-
-
- /* Called by comm program to set transfer options */
- long __saveds XProtocolSetup(struct XPR_IO *io) {
- struct SetupVars *sv, tempsv;
- struct xpr_option *option_ptrs[11], *optr, xo_hdr, xo_t, xo_o, xo_b, xo_f, xo_s, xo_r, xo_a, xo_d, xo_k, xo_p;
- UBYTE buf[256], *p;
- long i, len;
-
- /* Allocate memory for transfer options string */
- if (!(sv = io->xpr_data)) {
- io->xpr_data = AllocMem((long)sizeof(struct SetupVars),MEMF_CLEAR);
- if (!(sv = io->xpr_data)) {
- ioerr(io,"Not enough memory");
- return XPRS_FAILURE;
- }
- /* Start out with default options; merge user changes into defaults */
- *sv = Default_Config;
- }
-
- /* If options string passed by comm prog, use it; else prompt user */
- if (io->xpr_filename) strcpy(buf,io->xpr_filename);
- else {
- /* If xpr_options() implemented by comm program, use it */
- if (io->xpr_extension >= 1 && io->xpr_options) {
- /* Let user edit temp copy of options so we can ignore invalid entries */
- /* Have to init all this crud the hard way 'cause it's got to be on the
- stack in order to maintain reentrancy */
- tempsv = *sv;
- xo_hdr.xpro_description = "ZModem options:";
- xo_hdr.xpro_type = XPRO_HEADER;
- xo_hdr.xpro_value = NULL;
- xo_hdr.xpro_length = 0;
- option_ptrs[0] = &xo_hdr;
- xo_t.xpro_description = "Text mode (Y,N,?,C):";
- xo_t.xpro_type = XPRO_STRING;
- xo_t.xpro_value = tempsv.option_t;
- xo_t.xpro_length = sizeof(tempsv.option_t);
- option_ptrs[1] = &xo_t;
- xo_o.xpro_description = "Overwrite mode (Y,N,R,S):";
- xo_o.xpro_type = XPRO_STRING;
- xo_o.xpro_value = tempsv.option_o;
- xo_o.xpro_length = sizeof(tempsv.option_o);
- option_ptrs[2] = &xo_o;
- xo_b.xpro_description = "I/O buffer size (KB):";
- xo_b.xpro_type = XPRO_LONG;
- xo_b.xpro_value = tempsv.option_b;
- xo_b.xpro_length = sizeof(tempsv.option_b);
- option_ptrs[3] = &xo_b;
- xo_f.xpro_description = "Frame size (bytes):";
- xo_f.xpro_type = XPRO_LONG;
- xo_f.xpro_value = tempsv.option_f;
- xo_f.xpro_length = sizeof(tempsv.option_f);
- option_ptrs[4] = &xo_f;
- xo_a.xpro_description = "Auto-activate receiver:";
- xo_a.xpro_type = XPRO_BOOLEAN;
- xo_a.xpro_value = tempsv.option_a;
- xo_a.xpro_length = sizeof(tempsv.option_a);
- option_ptrs[5] = &xo_a;
- xo_d.xpro_description = "Delete after sending:";
- xo_d.xpro_type = XPRO_BOOLEAN;
- xo_d.xpro_value = tempsv.option_d;
- xo_d.xpro_length = sizeof(tempsv.option_d);
- option_ptrs[6] = &xo_d;
- xo_k.xpro_description = "Keep partial files:";
- xo_k.xpro_type = XPRO_BOOLEAN;
- xo_k.xpro_value = tempsv.option_k;
- xo_k.xpro_length = sizeof(tempsv.option_k);
- option_ptrs[7] = &xo_k;
- xo_s.xpro_description = "Send full path:";
- xo_s.xpro_type = XPRO_BOOLEAN;
- xo_s.xpro_value = tempsv.option_s;
- xo_s.xpro_length = sizeof(tempsv.option_s);
- option_ptrs[8] = &xo_s;
- xo_r.xpro_description = "Use received path:";
- xo_r.xpro_type = XPRO_BOOLEAN;
- xo_r.xpro_value = tempsv.option_r;
- xo_r.xpro_length = sizeof(tempsv.option_r);
- option_ptrs[9] = &xo_r;
- xo_p.xpro_description = "Default receive path:";
- xo_p.xpro_type = XPRO_STRING;
- xo_p.xpro_value = tempsv.option_p;
- xo_p.xpro_length = sizeof(tempsv.option_p);
- option_ptrs[10] = &xo_p;
- /* Convert Y/N used elsewhere into "yes"/"no" required by spec */
- for (i=5; i<=9; ++i) {
- optr = option_ptrs[i];
- strcpy(optr->xpro_value,(*optr->xpro_value == 'Y') ? "yes" : "no");
- }
- (*io->xpr_options)(11L,option_ptrs);
- /* Convert "yes"/"no" or "on"/"off" into Y/N */
- for (i=5; i<=9; ++i) {
- optr = option_ptrs[i];
- strcpy(optr->xpro_value,(!stricmp(optr->xpro_value,"yes") || !stricmp(optr->xpro_value,"on")) ? "Y" : "N");
- }
- /* Convert xpr_options() results into parseable options string */
- sprintf(buf,"T%s,O%s,B%s,F%s,A%s,D%s,K%s,S%s,R%s,P%s",tempsv.option_t,tempsv.option_o,tempsv.option_b,tempsv.option_f,
- tempsv.option_a,tempsv.option_d,tempsv.option_k,tempsv.option_s,tempsv.option_r,tempsv.option_p);
- /* If xpr_options() not provided, try xpr_gets() instead */
- } else {
- /* Start buffer with current settings so user can see/edit them in place */
- sprintf(buf,"T%s,O%s,B%s,F%s,A%s,D%s,K%s,S%s,R%s,P%s",sv->option_t,sv->option_o,sv->option_b,sv->option_f,
- sv->option_a,sv->option_d,sv->option_k,sv->option_s,sv->option_r,sv->option_p);
- if (io->xpr_gets) (*io->xpr_gets)("ZModem options:",buf);
- }
- }
- /* Upshift options string for easier parsing */
- strupr(buf);
-
- /* Merge new T(ext) option into current settings if given */
- /* "TY" = Force Text mode on,
- "TN" = Force Text mode off,
- "T?" = Use other end's text mode suggestion (default to binary)
- "TC" = Ask Comm program for file type */
- if (p = find_option(buf,'T')) {
- if (*p == 'Y' || *p == 'N' || *p == '?' || *p == 'C') *sv->option_t = *p;
- else ioerr(io,"Invalid T flag ignored; should be Y, N, ?, or C");
- }
-
- /* Merge new O(verwrite) option into current settings if given */
- /* "OY" = Yes, delete old file and replace with new one,
- "ON" = No, prevent overwrite by appending ".dup" to avoid name collision,
- "OR" = Resume transfer at end of existing file,
- "OS" = Skip file if it already exists; go on to next */
- if (p = find_option(buf,'O')) {
- if (*p == 'R' && !io->xpr_finfo) ioerr(io,"Can't Resume; xpr_finfo() not supported");
- else if (*p == 'Y' || *p == 'N' || *p == 'R' || *p == 'S') *sv->option_o = *p;
- else ioerr(io,"Invalid O flag ignored; should be Y, N, R, or S");
- }
-
- /* Merge new B(uffer) setting into current settings if given */
- /* Size of file I/O buffer in kilobytes */
- if (p = find_option(buf,'B')) {
- len = atol(p);
- if (len < 1) len = 1;
- sprintf(sv->option_b,"%ld",len);
- }
-
- /* Merge new F(ramelength) setting into other settings if given */
- /* Number of bytes we're willing to send or receive between ACKs.
- 0 = unlimited; nonstop streaming data */
- if (p = find_option(buf,'F')) {
- len = atol(p);
- if (len < 0) len = 0;
- if (len > 0 && len < MINBLOCK) len = MINBLOCK;
- sprintf(sv->option_f,"%ld",len);
- }
-
- /* Merge new A(uto-activate) setting into other settings if given */
- /* "AY" = Automatically call XProtocolReceive() if ZRQINIT string received
- "AN" = Don't look for ZRQINIT; user will explicitly activate receive */
- if (p = find_option(buf,'A')) {
- if (*p == 'Y' || *p == 'N') *sv->option_a = *p;
- else ioerr(io,"Invalid A flag ignored; should be Y or N");
- }
-
- /* Merge new D(elete after sending) setting into other options */
- /* "DY" = Delete files after successfully sending them
- "DN" = Don't delete files after sending */
- if (p = find_option(buf,'D')) {
- if (*p == 'Y' && (io->xpr_extension < 2 || !io->xpr_unlink))
- ioerr(io,"Can't use DY; xpr_unlink() not supported");
- else if (*p == 'Y' || *p == 'N') *sv->option_d = *p;
- else ioerr(io,"Invalid D flag ignored; should be Y or N");
- }
-
- /* Merge new K(eep partial files) setting into other options */
- /* "KY" = Keep partially-received file fragments to allow later resumption
- "KN" = Delete partially-received file fragments */
- if (p = find_option(buf,'K')) {
- if (*p == 'N' && (io->xpr_extension < 2 || !io->xpr_unlink))
- ioerr(io,"Can't use KN; xpr_unlink() not supported");
- else if (*p == 'Y' || *p == 'N') *sv->option_k = *p;
- else ioerr(io,"Invalid K flag ignored; should be Y or N");
- }
-
- /* Merge new S(end full path) setting into other options */
- /* "SY" = Send full filename including directory path to receiver
- "SN" = Send only simple filename portion, not including directory path */
- if (p = find_option(buf,'S')) {
- if (*p == 'Y' || *p == 'N') *sv->option_s = *p;
- else ioerr(io,"Invalid S flag ignored; should be Y or N");
- }
-
- /* Merge new R(eceive path) setting into other options */
- /* "RY" = Use full filename exactly as received; don't use P option path
- "RN" = Ignore received directory path if any; use path from P option */
- if (p = find_option(buf,'R')) {
- if (*p == 'Y' || *p == 'N') *sv->option_r = *p;
- else ioerr(io,"Invalid R flag ignored; should be Y or N");
- }
-
- /* Merge new P(ath) setting into other options */
- /* "Pdir" = Receive files into directory "dir" if RN selected
- "dir" can by any valid existing directory, with or without trailing "/" */
- if (p = find_option(buf,'P')) {
- strcpy(sv->option_p,p);
- p = sv->option_p + strcspn(sv->option_p," ,\t\r\n");
- *p = '\0';
- }
-
- return (*sv->option_a == 'Y') ? XPRS_SUCCESS|XPRS_NORECREQ|XPRS_HOSTMON : XPRS_SUCCESS|XPRS_NORECREQ;
- }
-
-
- /* Called by comm program to give us a chance to clean up before program ends */
- long __saveds XProtocolCleanup(struct XPR_IO *io) {
- /* Release option memory, if any */
- if (io->xpr_data) {
- FreeMem(io->xpr_data,(long)sizeof(struct SetupVars));
- io->xpr_data = NULL;
- }
-
- return XPRS_SUCCESS;
- }
-
-
-
- /* Called by comm program upon our request (XPRS_HOSTMON) to let us monitor
- the incoming data stream for our receiver auto-activation string (ZRQINIT packet).
- We only ask for this to be called if option AY is set. */
- long __saveds XProtocolHostMon(struct XPR_IO *io,UBYTE *serbuff,long actual,long maxsize) {
- static UBYTE startrcv[] = { ZPAD, ZDLE, ZHEX, "00" };
- struct SetupVars *sv;
-
- if (!(sv = io->xpr_data)) return actual; /* XProtocolSetup() never called?! */
- if (!sv->matchptr) sv->matchptr = startrcv;
-
- /* Scan through serbuff to see if we can match all bytes in the start string in sequence */
- for (sv->bufpos=serbuff; sv->bufpos < serbuff+actual; ++sv->bufpos) {
- if (*sv->bufpos == *sv->matchptr) { /* if data matches current position in match string */
- ++sv->matchptr; /* increment match position */
- if (!*sv->matchptr) { /* if at end of match string, it all matched */
- sv->matchptr = startrcv;
- sv->buflen = actual - (sv->bufpos - serbuff);
- XProtocolReceive(io);
- actual = 0; /* serbuff contents probably trashed by Receive() */
- break;
- }
- } else if (sv->matchptr > startrcv) { /* if mismatch, reset to start of match string */
- sv->matchptr = startrcv;
- if (*sv->bufpos == *sv->matchptr) ++sv->matchptr;
- }
- }
-
- sv->bufpos = NULL;
- return actual;
- }
-
-
- /* Called by comm program to let us monitor user's inputs; we never ask for
- this to be called, but it's better to recover gracefully than guru the machine */
- long __saveds XProtocolUserMon(struct XPR_IO *io,UBYTE *serbuff,long actual,long maxsize) {
- return actual;
- }
-
-
-
- /* Perform setup and initializations common to both Send and Receive routines */
- struct Vars *setup(struct XPR_IO *io) {
- static long bauds[] = { 110,300,1200,2400,4800,9600,19200,31250,38400,57600,76800,115200 };
- struct SetupVars *sv;
- struct Vars *v;
- long origbuf, newstatus;
- #ifdef DEBUGLOG
- long i, *lng;
- #endif
-
- /* Make sure comm program supports the required call-back functions */
- if (!io->xpr_update) return NULL;
- if (!io->xpr_fopen || !io->xpr_fclose || !io->xpr_fread || !io->xpr_fwrite ||
- !io->xpr_fseek || !io->xpr_sread || !io->xpr_swrite) {
- ioerr(io,"Comm prog missing required function(s); see docs");
- return NULL;
- }
-
- /* Hook in default transfer options if XProtocolSetup wasn't called */
- if (!(sv = io->xpr_data)) {
- io->xpr_data = AllocMem((long)sizeof(struct SetupVars),MEMF_CLEAR);
- if (!(sv = io->xpr_data)) {
- ioerr(io,"Not enough memory");
- return NULL;
- }
- *sv = Default_Config;
- }
-
- /* Allocate memory for our unshared variables, to provide reentrancy */
- if (!(v = AllocMem((long)sizeof(struct Vars),MEMF_CLEAR))) {
- nomem:
- ioerr(io,"Not enough memory");
- return NULL;
- }
-
- /* Allocate memory for our file I/O buffer; if we can't get as much as
- requested, keep asking for less until we hit minimum before giving up */
- v->Filebufmax = origbuf = atol(sv->option_b) * 1024;
- while (!(v->Filebuf = AllocMem(v->Filebufmax,0L))) {
- if (v->Filebufmax > 1024) v->Filebufmax -= 1024;
- else {
- FreeMem(v,(long)sizeof(struct Vars));
- goto nomem;
- }
- }
-
- /* If framelength was intended to match buffer size, stay in sync */
- v->Tframlen = atol(sv->option_f);
- if (v->Tframlen && v->Tframlen == origbuf) v->Tframlen = v->Filebufmax;
-
- /* Copy caller's io struct into our Vars for easier passing */
- v->io = *io;
-
- #ifdef DEBUGLOG
- if (!DebugLog) DebugLog = (*v->io.xpr_fopen)(DebugName,"w");
- dlog(v,"XPR_IO struct:\n");
- for (i=0,lng=(long *)io; i < sizeof(struct XPR_IO)/4; ++i) {
- sprintf(v->Msgbuf," %08lx\n",*lng++);
- dlog(v,v->Msgbuf);
- }
- #endif
-
- /* Get baud rate; set serial port mode if necessary (and possible) */
- if (v->io.xpr_setserial) {
- v->Oldstatus = (*v->io.xpr_setserial)(-1L);
- /* ZModem requires 8 data bits, no parity (full transparency),
- leave other settings alone */
- newstatus = v->Oldstatus & 0xFFFFE0BC;
- /* newstatus |= on_flags; Here's where we'd turn bits on if we needed to */
- if (newstatus != v->Oldstatus) (*v->io.xpr_setserial)(newstatus);
- v->Baud = bauds[(newstatus>>16) & 0xFF];
- #ifdef DEBUGLOG
- sprintf(v->Msgbuf,"Old serial status = %lx, new = %lx, baud = %ld\n",v->Oldstatus,newstatus,v->Baud);
- dlog(v,v->Msgbuf);
- #endif
- /* If no xpr_setserial(), muddle along with most likely guess */
- } else v->Baud = 2400;
-
- return v;
- }
-
-
-
- /* Set text/binary mode flags in accordance with T option setting */
- void set_textmode(struct Vars *v) {
- struct SetupVars *sv;
- long i;
-
- sv = v->io.xpr_data;
- switch(*sv->option_t) {
- case 'Y': /* Force text mode on receive; suggest text mode on send */
- TY: v->Rxascii = TRUE;
- v->Rxbinary = FALSE;
- v->Lzconv = ZCNL;
- break;
- case 'N': /* Force binary mode on receive; suggest binary mode on send */
- TN: v->Rxascii = FALSE;
- v->Rxbinary = TRUE;
- v->Lzconv = ZCBIN;
- break;
- case 'C': /* Ask comm program for proper mode for this file */
- if (v->io.xpr_finfo) {
- i = (*v->io.xpr_finfo)(v->Filename,2L);
- if (i == 1) goto TN; /* Comm program says use binary mode */
- if (i == 2) goto TY; /* Comm program says use text mode */
- }
- /* xpr_finfo() not provided (or failed); default to T? */
- case '?':
- v->Rxascii = v->Rxbinary = FALSE;
- v->Lzconv = 0;
- break;
- }
- }
-
-
-
- /* Search for specified option setting in string */
- UBYTE *find_option(UBYTE *buf,UBYTE option) {
- while (*buf) {
- buf += strspn(buf," ,\t\r\n");
- if (*buf == option) return ++buf;
- buf += strcspn(buf," ,\t\r\n");
- }
-
- return NULL;
- }
-
-
-
- /* send cancel string to get the other end to shut up */
- void canit(struct Vars *v) {
- static char canistr[] = { 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 };
-
- zmputs(v,canistr);
- }
-
-
-
- /* Send a string to the modem, with processing for \336 (sleep 1 sec)
- and \335 (break signal, ignored since XPR spec doesn't support it) */
- void zmputs(struct Vars *v,UBYTE *s) {
- UBYTE c;
-
- while (*s) {
- switch (c = *s++) {
- case '\336':
- TimeOut(50L);
- case '\335':
- break;
- default:
- sendline(v,c);
- }
- }
- }
-
-
-
- /* Write one character to the modem */
- void xsendline(struct Vars *v,UBYTE c) {
- (*v->io.xpr_swrite)(&c,1L);
- }
-
-
- /* Get a byte from the modem;
- return TIMEOUT if no read within timeout tenths of a second,
- return RCDO if carrier lost or other fatal error (sread returns -1).
- Added in some buffering so we wouldn't hammer the system with single-byte
- serial port reads. Also, the buffering makes char_avail() a lot easier to implement. */
- short readock(struct Vars *v,short tenths) {
- /* If there's data waiting in our buffer, return next byte */
- if (v->Modemcount) {
- gotdata:
- --v->Modemcount;
- return (short)(*v->Modemchar++);
- }
-
- /* Our buffer is empty; see if there's anything waiting in system buffer */
- v->Modemcount = (*v->io.xpr_sread)(v->Modembuf,(long)sizeof(v->Modembuf),0L);
- if (v->Modemcount < 0) { /* Carrier dropped or other fatal error; abort */
- v->Modemcount = 0;
- return RCDO;
- } else if (!v->Modemcount) { /* Nothing in system buffer; try waiting */
- v->Modemcount = (*v->io.xpr_sread)(v->Modembuf,1L,tenths*100000L);
- if (v->Modemcount < 0) {
- v->Modemcount = 0;
- return RCDO;
- } else if (!v->Modemcount) return TIMEOUT; /* Nothing received in time */
- }
- v->Modemchar = v->Modembuf; /* Reset buffer pointer to start of data */
- goto gotdata;
- }
-
-
-
- /* Check if there's anything available to read from the modem */
- char char_avail(struct Vars *v) {
- if (v->Modemcount) return TRUE;
-
- /* No data in our buffer; check system's input buffer */
- v->Modemcount = (*v->io.xpr_sread)(v->Modembuf,(long)sizeof(v->Modembuf),0L);
- if (v->Modemcount < 1) { /* Nothing in system buffer either */
- v->Modemcount = 0;
- return FALSE;
- } else { /* System buffer had something waiting for us */
- v->Modemchar = v->Modembuf;
- return TRUE;
- }
- }
-
-
-
- /* Update the elapsed time, expected total time, and effective data
- transfer rate values for status display */
- void update_rate(struct Vars *v) {
- long sent, elapsed, expect;
- short hr, min;
-
- /* Compute effective data rate so far in characters per second */
- sent = v->xpru.xpru_bytes - v->Strtpos; /* Actual number of chars transferred */
- elapsed = GetSysTime(NULL) - v->Starttime; /* Time it took to send them */
- if (elapsed < 1) elapsed = 1;
- /* If we haven't transferred anything yet (just starting), make reasonable
- guess (95% throughput); otherwise, compute actual effective transfer rate */
- v->xpru.xpru_datarate = (sent) ? sent / elapsed : v->Baud * 95L / 1000;
-
- /* Compute expected total transfer time based on data rate so far */
- if (v->xpru.xpru_filesize < 0) expect = 0; /* Don't know filesize; display time=0 */
- else expect = (v->xpru.xpru_filesize - v->Strtpos) / v->xpru.xpru_datarate;
- hr = expect / (60*60); /* How many whole hours */
- expect -= hr * (60*60); /* Remainder not counting hours */
- min = expect / 60; /* How many whole minutes */
- expect -= min * 60; /* Remaining seconds */
- sprintf(v->Msgbuf,"%02ld:%02ld:%02ld",(long)hr,(long)min,expect);
- v->xpru.xpru_expecttime = (char *)v->Msgbuf;
-
- /* Compute elapsed time for this transfer so far */
- hr = elapsed / (60*60);
- elapsed -= hr * (60*60);
- min = elapsed / 60;
- elapsed -= min * 60;
- sprintf(v->Msgbuf+20,"%02ld:%02ld:%02ld",(long)hr,(long)min,elapsed);
- v->xpru.xpru_elapsedtime = (char *)v->Msgbuf+20;
- }
-
-
-
- /* Buffered file I/O fopen() interface routine */
- void *bfopen(struct Vars *v,UBYTE *mode) {
- /* Initialize file-handling variables */
- v->Filebufpos = v->Filebuflen = v->Filebufcnt = 0;
- v->Fileflush = FALSE;
- v->Filebufptr = v->Filebuf;
- /* Open the file */
- #ifdef DEBUGLOG
- sprintf(v->Msgbuf,"bfopen: %s %s\n",v->Filename,mode);
- dlog(v,v->Msgbuf);
- #endif
- return (*v->io.xpr_fopen)(v->Filename,mode);
- }
-
-
-
- /* Buffered file I/O fclose() interface routine */
- void bfclose(struct Vars *v) {
- /* If bfwrite() left data lingering in buffer, flush it out before closing */
- if (v->Fileflush) (*v->io.xpr_fwrite)(v->Filebuf,1L,v->Filebufcnt,v->File);
- /* Close the file */
- (*v->io.xpr_fclose)(v->File);
- v->File = NULL;
- }
-
-
-
- /* Buffered file I/O fseek() interface routine */
- void bfseek(struct Vars *v,long pos) {
- long offset;
-
- /* If new file position is within currently buffered section, reset pointers */
- if (pos >= v->Filebufpos && pos < v->Filebufpos + v->Filebuflen) {
- offset = pos - v->Filebufpos;
- v->Filebufptr = v->Filebuf + offset;
- v->Filebufcnt = v->Filebuflen - offset;
- /* Otherwise, fseek() file and discard buffer contents to force new read */
- } else {
- (*v->io.xpr_fseek)(v->File,pos,0L);
- v->Filebuflen = v->Filebufcnt = 0;
- v->Filebufpos = pos;
- }
- }
-
-
-
- /* Buffered file I/O fread() interface routine */
- long bfread(struct Vars *v,UBYTE *buf,long length) {
- long count, total = 0;
-
- /* Keep going until entire request completed */
- while (length > 0) {
- /* Copy as much of the request as possible from the buffer */
- count = (length <= v->Filebufcnt) ? length : v->Filebufcnt;
- CopyMem(v->Filebufptr,buf,count);
- #ifdef DEBUGLOG
- sprintf(v->Msgbuf,"bfread got %ld bytes from buffer\n",count);
- dlog(v,v->Msgbuf);
- #endif
- buf += count;
- total += count;
- length -= count;
- v->Filebufptr += count;
- v->Filebufcnt -= count;
-
- /* If we've emptied the buffer, read next buffer's worth */
- if (!v->Filebufcnt) {
- v->Filebufpos += v->Filebuflen;
- v->Filebufptr = v->Filebuf;
- v->Filebufcnt = v->Filebuflen = (*v->io.xpr_fread)(v->Filebuf,1L,v->Filebufmax,v->File);
- #ifdef DEBUGLOG
- sprintf(v->Msgbuf,"bfread read %ld bytes\n",v->Filebufcnt);
- dlog(v,v->Msgbuf);
- #endif
- /* If we hit the EOF, return with however much we read so far */
- if (!v->Filebufcnt) break;
- }
- }
-
- return total;
- }
-
-
-
- /* Buffered file I/O fwrite() interface routine */
- long bfwrite(struct Vars *v,UBYTE *buf,long length) {
- long count, total = 0;
-
- /* Keep going until entire request completed */
- while (length > 0) {
- /* Copy as much as will fit into the buffer */
- count = v->Filebufmax - v->Filebufcnt;
- if (length < count) count = length;
- CopyMem(buf,v->Filebufptr,count);
- #ifdef DEBUGLOG
- sprintf(v->Msgbuf,"bfwrite buffered %ld bytes\n",count);
- dlog(v,v->Msgbuf);
- #endif
- buf += count;
- total += count;
- length -= count;
- v->Filebufptr += count;
- v->Filebufcnt += count;
- v->Fileflush = TRUE;
-
- /* If we've filled the buffer, write it out */
- if (v->Filebufcnt == v->Filebufmax) {
- count = (*v->io.xpr_fwrite)(v->Filebuf,1L,v->Filebufcnt,v->File);
- #ifdef DEBUGLOG
- sprintf(v->Msgbuf,"bfwrite wrote %ld bytes\n",count);
- dlog(v,v->Msgbuf);
- #endif
- if (count < v->Filebufcnt) return -1;
- v->Filebufptr = v->Filebuf;
- v->Filebufcnt = 0;
- v->Fileflush = FALSE;
- }
- }
-
- return total;
- }
-
-
-
- /* Have the comm program display an error message for us, using a
- temporary XPR_UPDATE structure; used to display errors before Vars
- gets allocated */
- void ioerr(struct XPR_IO *io,char *msg) {
- struct XPR_UPDATE xpru;
-
- if (io->xpr_update) {
- xpru.xpru_updatemask = XPRU_ERRORMSG;
- xpru.xpru_errormsg = msg;
- (*io->xpr_update)(&xpru);
- }
- }
-
-
-
- /* Have the comm program display an error message for us, using the
- normal XPR_IO structure allocated in Vars */
- void upderr(struct Vars *v,char *msg) {
- v->xpru.xpru_updatemask = XPRU_ERRORMSG;
- v->xpru.xpru_errormsg = msg;
- (*v->io.xpr_update)(&v->xpru);
- #ifdef DEBUGLOG
- dlog(v,msg);
- dlog(v,"\n");
- #endif
- }
-
-
-
- /* Have the comm program display a normal message for us */
- void updmsg(struct Vars *v,char *msg) {
- v->xpru.xpru_updatemask = XPRU_MSG;
- v->xpru.xpru_msg = msg;
- (*v->io.xpr_update)(&v->xpru);
- #ifdef DEBUGLOG
- dlog(v,msg);
- dlog(v,"\n");
- #endif
- }
-
-
-
- /* Figure out how many bytes are free on the drive we're uploading to.
- Stubbed out for now; not supported by XPR spec. */
- long getfree(void) {
- return 0x7FFFFFFF;
- }
-
-
-
- /* Check whether file already exists; used to detect potential overwrites */
- char exist(struct Vars *v) {
- void *file;
-
- file = (*v->io.xpr_fopen)(v->Filename,"r");
- if (file) {
- (*v->io.xpr_fclose)(file);
- return TRUE;
- } else return FALSE;
- }
-
-
-
- #ifdef DEBUGLOG
- /* Write a message to the debug log */
- void dlog(struct Vars *v,UBYTE *s) {
- /* Open the debug log if it isn't already open */
- if (!DebugLog) DebugLog = (*v->io.xpr_fopen)(DebugName,"a");
- (*v->io.xpr_fwrite)(s,1L,(long)strlen(s),DebugLog);
- /* Close file to flush output buffer; comment these two lines out if
- you aren't crashing your system and don't mind waiting until the
- transfer finishes to look at your log file.
- (*v->io.xpr_fclose)(DebugLog);
- DebugLog = NULL; */
- }
- #endif
-