home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- * Utils.c: Miscellaneous support routines for xprzmodem.library;
- * Version 2.10, 12 February 1991, by Rick Huebner.
- * Released to the Public Domain; do as you like with this code.
- *
- * Version 2.50, 15 November 1991, by William M. Perkins. Added code
- * to update_rate() function in utils.c to avoid the Guru # 80000005
- * you would have gotten if you had decided to adjust the system clock
- * back during an upload or download.
- *
- * Mysprintf() function to replace sprintf() and proto code to use
- * libinit.o and linent.o library code was supplied by Jim Cooper of SAS.
- *
- * Version 2.54, 28 June 1993, by Olaf `Olsen' Barthel. Got rid of the
- * timer.c code, added OS 2.0 dependencies, rewrote update_rate() to
- * display only the information which was really available, added
- * control-code escaping & run-length encoding, changed the abort
- * routine to pay attention to the different abort levels, removed
- * SAS/C library dependencies (octal conversion, etc.), added
- * support for proper file creation date and access permission bits.
- **********************************************************************/
-
- /* Transfer options to use if XProtocolSetup not called */
- struct SetupVars Default_Config =
- {
- NULL, NULL, 0,
- {"C"},
- {"N"},
- {"16"},
- {"0"},
- {"10"},
- {"N"},
- {"N"},
- {"N"},
- {"Y"},
- {"N"},
- {"Y"},
- {""},
- {"1024"},
- {"S"}
- };
-
- /* Global data. */
- struct DosLibrary *DOSBase;
- struct ExecBase *SysBase;
- struct Library *UtilityBase, *LocaleBase, *TimerBase;
- struct Catalog *Catalog;
- struct timerequest TimeRequest;
-
- /* Offset to convert local time into GMT. */
- LONG GMT_Offset = UTC_OFFSET;
-
- /* So we know who we are. */
- STATIC LONG LibVersion, LibRevision;
-
- /* This gets called by the SAS/C library init code. */
- int __saveds __asm __UserLibInit(register __a6 struct MyLibrary *libbase)
- {
- /* Save these for later. */
- LibVersion = ((struct Library *) libbase)->lib_Version;
- LibRevision = ((struct Library *) libbase)->lib_Revision;
-
- /* All the code depends on this. */
- SysBase = *(struct ExecBase **) 4;
-
- /* Already set up? */
- if (DOSBase)
- return (NULL);
- else
- {
- /* Now open all the libraries we need. */
- if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
- {
- if (UtilityBase = OpenLibrary("utility.library", 37))
- {
- if (!OpenDevice(TIMERNAME, UNIT_VBLANK, &TimeRequest, NULL))
- {
- TimerBase = (struct Library *) TimeRequest.tr_node.io_Device;
-
- /* Try to open locale.library. */
- if (LocaleBase = OpenLibrary("locale.library", 38))
- {
- struct Locale *Locale;
-
- /* Try to open the catalog. */
- if (Catalog = OpenCatalogA(NULL, "xprzmodem.catalog", NULL))
- {
- /* Exclude all other catalogs, this is to avoid
- * conflicts with xprzmodem 3.1 catalog files.
- */
- if (Catalog->cat_Version < 17)
- {
- CloseCatalog(Catalog);
-
- Catalog = NULL;
- }
- }
-
- /* Open the current default locale. */
- Locale = OpenLocale(NULL);
-
- /* Calculate time offset for GMT. */
- GMT_Offset = 60 * Locale->loc_GMTOffset + UTC_OFFSET;
-
- CloseLocale(Locale);
- }
-
- /* Return success. */
- return (NULL);
- }
-
- CloseLibrary(UtilityBase);
-
- UtilityBase = NULL;
- }
-
- CloseLibrary(DOSBase);
-
- DOSBase = NULL;
- }
- }
-
- return (~0);
- }
-
- /* This gets called by the SAS/C library cleanup code. */
- void __saveds __asm __UserLibCleanup(register __a6 struct MyLibrary *libbase)
- {
- if (TimerBase)
- {
- CloseDevice(&TimeRequest);
-
- TimerBase = NULL;
- }
-
- if (DOSBase)
- {
- CloseLibrary(DOSBase);
-
- DOSBase = NULL;
- }
-
- if (UtilityBase)
- {
- CloseLibrary(UtilityBase);
-
- UtilityBase = NULL;
- }
-
- if (Catalog)
- {
- CloseCatalog(Catalog);
-
- Catalog = NULL;
- }
-
- if (LocaleBase)
- {
- CloseLibrary(LocaleBase);
-
- LocaleBase = NULL;
- }
- }
-
- /* Convert a string to all upper case characters. */
- STATIC VOID __regargs
- string_upper(register STRPTR buf)
- {
- register UBYTE c;
-
- while (c = *buf)
- *buf++ = ToUpper(c);
- }
-
- /* Skip blanks in a string. */
- STATIC STRPTR __regargs
- skip_blank(register STRPTR buf)
- {
- register UBYTE c;
-
- while (c = *buf)
- {
- if (c == ' ' || c == ',' || c == '\t' || c == '\r' || c == '\n')
- buf++;
- else
- break;
- }
-
- return (buf);
- }
-
- /* Skip non-blank chars in a string. */
- STATIC STRPTR __regargs
- skip_chars(register STRPTR buf)
- {
- register UBYTE c;
-
- while (c = *buf)
- {
- if (c == ' ' || c == ',' || c == '\t' || c == '\r' || c == '\n')
- return (buf);
- else
- buf++;
- }
-
- return (buf);
- }
-
- /* Look up a string in the locale database. */
- STRPTR GetLocaleString(LONG ID)
- {
- extern struct
- {
- LONG as_ID;
- STRPTR as_Str;
- } *AppStrings;
-
- extern LONG NumAppStrings;
-
- STRPTR Builtin;
-
- if (ID < NumAppStrings && AppStrings[ID].as_ID == ID)
- Builtin = AppStrings[ID].as_Str;
- else
- {
- WORD i;
-
- Builtin = "";
-
- for (i = 0; i < NumAppStrings; i++)
- {
- if (AppStrings[i].as_ID == ID)
- {
- Builtin = AppStrings[i].as_Str;
-
- break;
- }
- }
- }
-
- if (LocaleBase && Catalog)
- {
- STRPTR String = GetCatalogStr(Catalog, ID, Builtin);
-
- if (String[0])
- return (String);
- else
- return (Builtin);
- }
- else
- return (Builtin);
- }
-
- /* Get the local time, convert it to GMT. */
- ULONG getsystime(struct timeval * tv)
- {
- struct timeval Now;
-
- GetSysTime(&Now);
-
- Now.tv_secs += GMT_Offset;
-
- if (tv)
- {
- tv->tv_secs = Now.tv_secs;
- tv->tv_micro = 0;
- }
-
- return (Now.tv_secs);
- }
-
- /* Our reentrant sprintf() clone. */
- VOID __stdargs mysprintf(STRPTR Buffer, STRPTR Format,...)
- {
- va_list VarArgs;
-
- va_start(VarArgs, Format);
- RawDoFmt(Format, VarArgs, (VOID(*)())(VOID(*))"\x16\xC0\x4E\x75", Buffer);
- va_end(VarArgs);
- }
-
- /* Convert a string into numeric data. */
- LONG Atol(STRPTR Buffer)
- {
- LONG Value;
-
- StrToLong(Buffer, &Value);
-
- return (Value);
- }
-
- /**********************************************************
- * long XProtocolSetup(struct XPR_IO *xio)
- *
- * Called by comm program to set transfer options
- **********************************************************/
- long __saveds __asm XProtocolSetup(register __a0 struct XPR_IO *xio)
- {
- struct SetupVars *sv, tempsv;
- struct xpr_option *option_ptrs[15];
- struct xpr_option *optr, xo_hdr, xo_t, xo_o, xo_b, xo_f, xo_e, xo_s,
- xo_c, xo_r, xo_a, xo_d, xo_k, xo_p, xo_m, xo_i;
- UBYTE buf[512], *p;
- long i, len;
-
- /* Allocate memory for transfer options string */
- if (!(sv = (void *) xio->xpr_data))
- {
- xio->xpr_data = AllocMem((long) sizeof(struct SetupVars), MEMF_PUBLIC | MEMF_CLEAR); /* OLSEN */
-
- if (!(sv = (void *) xio->xpr_data))
- {
- ioerr(xio, GetLocaleString(MSG_NOT_ENOUGH_MEMORY_TXT));
- 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 (xio->xpr_filename)
- strcpy(buf, xio->xpr_filename);
- else
- {
- /* If xpr_options() implemented by comm program, use it */
- if (xio->xpr_extension >= 1 && xio->xpr_options)
- {
- /* Set up protocol string. */
- mysprintf(buf, GetLocaleString(MSG_ZMODEM_OPTIONS_TXT), LibVersion, LibRevision);
-
- /* 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 = buf;
- 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 = GetLocaleString(MSG_ZMODEM_TEXT_MODE_TXT);
- 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 = GetLocaleString(MSG_ZMODEM_OVERWRITE_MODE_TXT);
- 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 = GetLocaleString(MSG_ZMODEM_IO_BUFFER_SIZE_TXT);
- 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 = GetLocaleString(MSG_ZMODEM_FRAME_SIZE_TXT);
- 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_m.xpro_description = GetLocaleString(MSG_ZMODEM_MAXIMUM_PACKET_SIZE_TXT);
- xo_m.xpro_type = XPRO_LONG;
- xo_m.xpro_value = tempsv.option_m;
- xo_m.xpro_length = sizeof(tempsv.option_m);
- option_ptrs[5] = &xo_m;
- */
- xo_e.xpro_description = GetLocaleString(MSG_ZMODEM_ERROR_LIMIT_TXT);
- xo_e.xpro_type = XPRO_LONG;
- xo_e.xpro_value = tempsv.option_e;
- xo_e.xpro_length = sizeof(tempsv.option_e);
- option_ptrs[5] = &xo_e;
-
- xo_i.xpro_description = GetLocaleString(MSG_FILE_ATTRIBUTES_TXT);
- xo_i.xpro_type = XPRO_STRING;
- xo_i.xpro_value = tempsv.option_i;
- xo_i.xpro_length = sizeof(tempsv.option_i);
- option_ptrs[6] = &xo_i;
-
- xo_c.xpro_description = GetLocaleString(MSG_ZMODEM_ESCAPE_CONTROL_CHARACTERS_TXT); /* OLSEN */
- xo_c.xpro_type = XPRO_BOOLEAN;
- xo_c.xpro_value = tempsv.option_c;
- xo_c.xpro_length = sizeof(tempsv.option_c);
- option_ptrs[7] = &xo_c;
-
- xo_a.xpro_description = GetLocaleString(MSG_ZMODEM_AUTO_ACTIVATE_RECEIVER_TXT);
- xo_a.xpro_type = XPRO_BOOLEAN;
- xo_a.xpro_value = tempsv.option_a;
- xo_a.xpro_length = sizeof(tempsv.option_a);
- option_ptrs[8] = &xo_a;
-
- xo_d.xpro_description = GetLocaleString(MSG_ZMODEM_DELETE_AFTER_SENDING_TXT);
- xo_d.xpro_type = XPRO_BOOLEAN;
- xo_d.xpro_value = tempsv.option_d;
- xo_d.xpro_length = sizeof(tempsv.option_d);
- option_ptrs[9] = &xo_d;
-
- xo_k.xpro_description = GetLocaleString(MSG_ZMODEM_KEEP_PARTIAL_FILES_TXT);
- xo_k.xpro_type = XPRO_BOOLEAN;
- xo_k.xpro_value = tempsv.option_k;
- xo_k.xpro_length = sizeof(tempsv.option_k);
- option_ptrs[10] = &xo_k;
-
- xo_s.xpro_description = GetLocaleString(MSG_ZMODEM_SEND_FULL_PATH_TXT);
- xo_s.xpro_type = XPRO_BOOLEAN;
- xo_s.xpro_value = tempsv.option_s;
- xo_s.xpro_length = sizeof(tempsv.option_s);
- option_ptrs[11] = &xo_s;
-
- xo_r.xpro_description = GetLocaleString(MSG_ZMODEM_USE_RECEIVED_PATH_TXT);
- xo_r.xpro_type = XPRO_BOOLEAN;
- xo_r.xpro_value = tempsv.option_r;
- xo_r.xpro_length = sizeof(tempsv.option_r);
- option_ptrs[12] = &xo_r;
-
- xo_p.xpro_description = GetLocaleString(MSG_ZMODEM_DEFAULT_RECEIVE_PATH_TXT);
- xo_p.xpro_type = XPRO_STRING;
- xo_p.xpro_value = tempsv.option_p;
- xo_p.xpro_length = sizeof(tempsv.option_p);
- option_ptrs[13] = &xo_p;
-
- /* Convert Y/N used elsewhere into "yes"/"no" required by spec */
- for (i = 7; i <= 12; ++i) /* OLSEN */
- {
- optr = option_ptrs[i];
- strcpy(optr->xpro_value, (*optr->xpro_value == 'Y') ? "yes" : "no");
- }
-
- (*xio->xpr_options) (14L, option_ptrs); /* OLSEN */
-
- /* Convert "yes"/"no" or "on"/"off" into Y/N */
- for (i = 7; i <= 12; ++i) /* OLSEN */
- {
- optr = option_ptrs[i];
-
- if (!Stricmp(optr->xpro_value, "yes") || !Stricmp(optr->xpro_value, "on"))
- strcpy(optr->xpro_value, "Y");
- else
- strcpy(optr->xpro_value, "N");
- }
-
- /* Convert xpr_options() results into parseable options string */
- mysprintf(buf, "T%s,O%s,B%s,F%s,E%s,C%s,A%s,D%s,K%s,S%s,R%s,I%s,P%s",
- tempsv.option_t, tempsv.option_o, tempsv.option_b, tempsv.option_f,
- tempsv.option_e, tempsv.option_c, tempsv.option_a, tempsv.option_d, tempsv.option_k,
- tempsv.option_s, tempsv.option_r, tempsv.option_i, tempsv.option_p);
- /* If xpr_options() not provided, try xpr_gets() instead */
- }
- else
- {
- /* Start buffer with current settings so user can see/edit them. */
- mysprintf(buf, "T%s,O%s,B%s,F%s,E%s,C%s,A%s,D%s,K%s,S%s,R%s,I%s,P%s",
- sv->option_t, sv->option_o, sv->option_b, sv->option_f,
- sv->option_e, sv->option_c, sv->option_a, sv->option_d, sv->option_k,
- sv->option_s, sv->option_r, sv->option_i, sv->option_p);
- if (xio->xpr_gets)
- (*xio->xpr_gets) (GetLocaleString(MSG_ZMODEM_OPTIONS2_TXT), buf);
- }
- }
- /* Upshift options string for easier parsing */
-
- string_upper(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(xio, GetLocaleString(MSG_INVALID_FLAG_T_IGNORED_TXT));
- }
-
- /* 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' && !xio->xpr_finfo)
- ioerr(xio, GetLocaleString(MSG_CANT_RESUME_TXT));
- else if (*p == 'Y' || *p == 'N' || *p == 'R' || *p == 'S')
- *sv->option_o = *p;
- else
- ioerr(xio, GetLocaleString(MSG_INVALID_FLAG_O_IGNORED_TXT));
- }
-
- /* 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;
- mysprintf(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;
- mysprintf(sv->option_f, "%ld", len);
- }
-
- /* Merge new E(rror limit) setting into other settings if given
- * Number of sequential errors which will cause an abort
- */
- if (p = find_option(buf, 'E'))
- {
- len = Atol(p);
- if (len < 1)
- len = 1;
- if (len > 32767)
- len = 32767;
- mysprintf(sv->option_e, "%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(xio, GetLocaleString(MSG_INVALID_FLAG_A_IGNORED_TXT));
- }
-
- /* Merge new Escape C(ontrol) character setting into other settings if given
- * "CY" = Escape control characters
- * "CN" = Don't do it
- */
- if (p = find_option(buf, 'C'))
- {
- if (*p == 'Y' || *p == 'N')
- *sv->option_c = *p;
- else
- ioerr(xio, GetLocaleString(MSG_INVALID_FLAG_C_IGNORED_TXT));
- }
-
- /* 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' && (xio->xpr_extension < 2 || !xio->xpr_unlink))
- ioerr(xio, GetLocaleString(MSG_CANT_UNLINK_TXT));
- else if (*p == 'Y' || *p == 'N')
- *sv->option_d = *p;
- else
- ioerr(xio, GetLocaleString(MSG_INVALID_FLAG_D_IGNORED_TXT));
- }
-
- /* 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' && (xio->xpr_extension < 2 || !xio->xpr_unlink))
- ioerr(xio, GetLocaleString(MSG_CANT_KEEP_TXT));
- else if (*p == 'Y' || *p == 'N')
- *sv->option_k = *p;
- else
- ioerr(xio, GetLocaleString(MSG_INVALID_FLAG_K_IGNORED_TXT));
- }
-
- /* 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(xio, GetLocaleString(MSG_INVALID_FLAG_S_IGNORED_TXT));
- }
-
- /* 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(xio, GetLocaleString(MSG_INVALID_FLAG_R_IGNORED_TXT));
- }
-
- /* Merge new file attribute setting into other options
- * "IS" = Transmit file attributes when sending
- * "IR" = Honor received file attributes
- * "IB" = Transmit file attributes when sending and honor then when
- * receiving
- */
- if (p = find_option(buf, 'I'))
- {
- if (*p == 'S' || *p == 'R' || *p == 'B')
- *sv->option_i = *p;
- else
- ioerr(xio, GetLocaleString(MSG_INVALID_FLAG_I_IGNORED_TXT));
- }
-
- /* 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 = skip_chars(sv->option_p);
- *p = '\0';
- }
-
- /*
- * Merge new M(aximum) packet setting into other settings.
- */
- if (p = find_option(buf, 'M'))
- {
- mysprintf(sv->option_m, "%ld", 1024);
- }
-
- return (*sv->option_a == 'Y') ? XPRS_SUCCESS | XPRS_NORECREQ | XPRS_HOSTMON
- : XPRS_SUCCESS | XPRS_NORECREQ;
- } /* End of long XProtocolSetup() */
-
- /**********************************************************
- * long XProtocolCleanup(struct XPR_IO *xio)
- *
- * Called by comm program to give us a chance to clean
- * up before program ends
- **********************************************************/
- long __saveds __asm XProtocolCleanup(register __a0 struct XPR_IO *xio)
- {
- /* Release option memory, if any */
- if (xio->xpr_data)
- {
- FreeMem(xio->xpr_data, (long) sizeof(struct SetupVars));
-
- xio->xpr_data = NULL;
- }
-
- return XPRS_SUCCESS;
- } /* End of long XProtocolCleanup() */
-
- /**********************************************************
- * long XProtocolHostMon(struct XPR_IO *xio,
- * char *serbuff, long actual, long maxsize)
- *
- * 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 __asm XProtocolHostMon(register __a0 struct XPR_IO *xio,register __a1 char *serbuff,register __d0 long actual,register __d1 long maxsize)
- {
- static UBYTE startrcv[] =
- {ZPAD, ZDLE, ZHEX, '0', '0', 0};
- struct SetupVars *sv;
-
- if (!(sv = (void *) xio->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; (ULONG) sv->bufpos < (ULONG) serbuff + actual; ++sv->bufpos)
- {
- if (*sv->bufpos == *sv->matchptr)
- { /* if data matches current position in match */
- ++sv->matchptr; /* string, increment match position */
- if (!*sv->matchptr)
- { /* if at end of match string, it all matched */
- sv->buflen = actual - (sv->bufpos - serbuff);
- XProtocolReceive(xio);
- sv->matchptr = startrcv;
- actual = 0;
- break;
- }
- }
- else if (sv->matchptr > startrcv)
- { /* mismatch? Reset to start of match string */
- sv->matchptr = startrcv;
- if (*sv->bufpos == *sv->matchptr)
- ++sv->matchptr;
- }
- }
-
- sv->bufpos = NULL;
- return actual;
- }
-
- /**********************************************************
- * long XProtocolUserMon(struct XPR_IO *xio,
- * char *serbuff, long actual, long maxsize)
- *
- * 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 __asm XProtocolUserMon(register __a0 struct XPR_IO *xio,register __a1 char *serbuff,register __d0 long actual,register __d1 long maxsize)
- {
- return actual;
- }
-
- /**********************************************************
- * struct Vars *setup(struct XPR_IO *io)
- *
- * 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;
-
- /* 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, GetLocaleString(MSG_COMM_PROGRAM_MISSING_FUNCTION_TXT));
- return NULL;
- }
-
- /* Hook in default transfer options if XProtocolSetup wasn't called */
- if (!(sv = (void *) io->xpr_data))
- {
- io->xpr_data = AllocMem((long) sizeof(struct SetupVars), MEMF_PUBLIC | MEMF_CLEAR); /* OLSEN */
-
- if (!(sv = (void *) io->xpr_data))
- {
- ioerr(io, GetLocaleString(MSG_NOT_ENOUGH_MEMORY_TXT));
- return NULL;
- }
- *sv = Default_Config;
- }
-
- /* Allocate memory for our unshared variables, to provide reentrancy */
- if (!(v = AllocMem((long) sizeof(struct Vars), MEMF_PUBLIC | MEMF_CLEAR))) /* OLSEN */
- {
- nomem:
- ioerr(io, GetLocaleString(MSG_NOT_ENOUGH_MEMORY_TXT));
- return NULL;
- }
- v->Modemchar = v->Modembuf;
-
- /*
- * 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;
-
- v->ErrorLimit = Atol(sv->option_e);
-
- /* If selected, enable control character escape mode. */
- if (sv->option_c[0] == 'Y')
- v->Zctlesc = 1;
- else
- v->Zctlesc = 0;
-
- /* Take care of the file attribute options. */
- if (sv->option_i[0] == 'S')
- v->FileAttributes = 1;
- else
- {
- if (sv->option_i[0] == 'R')
- v->FileAttributes = 2;
- else
- v->FileAttributes = 3;
- }
-
- /* Get the maximum allowed packet size. */
- if ((v->ksize = Atol(sv->option_m)) < MINBLOCK)
- v->ksize = MINBLOCK;
- else
- {
- if (v->ksize > KSIZE)
- v->ksize = KSIZE;
- }
-
- /* Copy caller's io struct into our Vars for easier passing */
- v->io = *io;
-
- /* Get baud rate; set serial port mode if necessary (and possible) */
- if (v->io.xpr_setserial)
- {
- v->Oldstatus = (*v->io.xpr_setserial) (-1L);
- if (v->Oldstatus != -1)
- {
- #if 0 /* OLSEN */
- ULONG newstatus;
-
- /* 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];
- #else
- v->Baud = bauds[(v->Oldstatus >> 16) & 0xFF];
- v->Oldstatus = -1;
- #endif
- }
- else
- v->Baud = 2400;
- /* If no xpr_setserial(), muddle along with most likely guess */
- }
- else
- v->Baud = 2400;
-
- return v;
- } /* End of struct Vars *setup() */
-
- /**********************************************************
- * void set_textmode(struct Vars *v)
- *
- * Set text/binary mode flags in accordance with T option
- * setting
- **********************************************************/
- void set_textmode(struct Vars *v)
- {
- struct SetupVars *sv;
- long i;
-
- sv = (void *) 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) /* Comm program says use binary mode */
- goto TN;
- if (i == 2) /* Comm program says use text mode */
- goto TY;
- }
- /* xpr_finfo() not provided (or failed); default to T? */
- case '?':
- v->Rxascii = v->Rxbinary = FALSE;
- v->Lzconv = 0;
- break;
- }
- } /* End of void set_textmode() */
-
- /**********************************************************
- * UBYTE *find_option(UBYTE *buf, UBYTE option)
- *
- * Search for specified option setting in string
- **********************************************************/
- UBYTE *find_option(UBYTE * buf, UBYTE option)
- {
- while (*buf)
- {
- buf = skip_blank(buf);
-
- if (*buf == option)
- return ++buf;
-
- buf = skip_chars(buf);
- }
-
- return NULL;
- } /* End of UBYTE *find_option() */
-
- /**********************************************************
- * void canit(struct Vars *v)
- *
- * 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);
- } /* End of void canit() */
-
- /**********************************************************
- * void zmputs(struct Vars *v, UBYTE *s)
- *
- * 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':
- Delay(TICKS_PER_SECOND);
- case '\335':
- break;
- default:
- sendline(v, c);
- }
- }
- sendbuf(v);
- } /* End of void zmputs() */
-
- /**********************************************************
- * void xsendline(struct Vars *v, UBYTE c)
- *
- * Write one character to the modem
- **********************************************************/
- void xsendline(struct Vars *v, UBYTE c)
- {
- v->Outbuf[v->Outbuflen++] = c;
- if (v->Outbuflen >= sizeof(v->Outbuf))
- sendbuf(v);
- } /* End of void xsendline() */
-
- /**********************************************************
- * void sendbuf(struct Vars *v)
- *
- * Send any data waiting in modem output buffer
- **********************************************************/
- void sendbuf(struct Vars *v)
- {
- if (v->Outbuflen)
- {
- /* Do the bookkeeping. */
- v->BytesSent += v->Outbuflen;
- (*v->io.xpr_swrite) (v->Outbuf, (long) v->Outbuflen);
- v->Outbuflen = 0;
- }
- } /* End of void sendbuf() */
-
- /**********************************************************
- * short readock(struct Vars *v, short tenths)
- *
- * 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)
- {
- long t;
-
- /* 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.
- * If the caller is in a hurry, don't wait around, but if it can spare
- * a half second, wait a bit and build up some input so we don't do as
- * many sread() calls.
- */
- t = (tenths < 5) ? 0 : 500000;
- v->Modemcount = (*v->io.xpr_sread) (v->Modembuf, (long) sizeof(v->Modembuf),
- t);
- 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 */
- {
- t = tenths * 100000L - t;
- v->Modemcount = (*v->io.xpr_sread) (v->Modembuf, 1L, t);
- if (v->Modemcount < 0)
- {
- v->Modemcount = 0;
- return RCDO;
- }
- else if (!v->Modemcount) /* Nothing received in time */
- return TIMEOUT;
- }
-
- /* Do the bookkeeping. */
- v->BytesReceived += v->Modemcount;
-
- /* Reset buffer pointer to start of data */
- v->Modemchar = v->Modembuf;
- goto gotdata;
- } /* End of short readock() */
-
- /**********************************************************
- * char char_avail(struct Vars *v)
- *
- * 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
- {
- /* Do the bookkeeping. */
- v->BytesReceived += v->Modemcount;
-
- /* System buffer had something waiting for us */
- v->Modemchar = v->Modembuf;
- return TRUE;
- }
- } /* End of char char_avail() */
-
- /**********************************************************
- * void update_rate(struct Vars *v)
- *
- * Update the elapsed time, expected total time, and
- * effective data transfer rate values for status display
- **********************************************************/
- void update_rate(struct Vars *v)
- {
- ULONG elapsed, expect, throughput, time, oldrate = v->xpru.xpru_datarate;
- struct timeval Now;
-
- /* What time is it? */
- GetSysTime(&Now);
-
- /* Now calculate the time elapsed since the protocol started
- * transferring the current file.
- */
- if (CmpTime(&Now, &v->Starttime) > 0)
- Now.tv_secs = Now.tv_micro = 0;
- else
- SubTime(&Now, &v->Starttime);
- elapsed = Now.tv_secs;
-
- /* Now take a look at the data that go through so far. */
- if (v->Receiving)
- throughput = v->BytesReceived;
- else
- throughput = v->BytesSent;
-
- /* Cut off the lowest 24 bits. */
- if (throughput > 0x00FFFFFF)
- throughput = 0xFFFFFF00;
- else
- throughput = throughput << 8;
-
- /* Now calculate the time. */
- if (elapsed > 0x00FFFFFF)
- time = 0xFFFFFF00 | (Now.tv_micro >> 12);
- else
- time = (elapsed << 8) | (Now.tv_micro >> 12);
-
- /* Finally, calculate the effective number of characters
- * transferred per second.
- */
- if (time)
- {
- if(v->xpru.xpru_datarate = throughput / time)
- v->xpru.xpru_updatemask |= XPRU_DATARATE;
- else
- v->xpru.xpru_updatemask &= ~XPRU_DATARATE;
- }
- else
- {
- v->xpru.xpru_datarate = 0;
- v->xpru.xpru_updatemask &= ~XPRU_DATARATE;
- }
-
- /* Any changes? */
- if (v->xpru.xpru_datarate == oldrate)
- v->xpru.xpru_updatemask &= ~(XPRU_DATARATE|XPRU_EXPECTTIME);
-
- /* Compute expected total transfer time based on data rate so far */
- if (v->xpru.xpru_filesize <= 0 || !v->xpru.xpru_datarate)
- v->xpru.xpru_updatemask &= ~XPRU_EXPECTTIME;
- else
- {
- if ((expect = (v->xpru.xpru_filesize - v->Strtpos) / v->xpru.xpru_datarate) < elapsed)
- expect = elapsed;
-
- v->xpru.xpru_updatemask |= XPRU_EXPECTTIME;
- }
-
- /* Any data to display? */
- if (v->xpru.xpru_updatemask & XPRU_EXPECTTIME)
- {
- v->xpru.xpru_expecttime = (char *)v->Msgbuf;
-
- mysprintf(v->xpru.xpru_expecttime, "%02ld:%02ld:%02ld", expect / (60 * 60), (expect / 60) % 60, expect % 60);
-
- v->xpru.xpru_elapsedtime = &v->xpru.xpru_expecttime[strlen(v->xpru.xpru_expecttime) + 1];
- }
- else
- v->xpru.xpru_elapsedtime = v->Msgbuf;
-
- mysprintf(v->xpru.xpru_elapsedtime, "%02ld:%02ld:%02ld", elapsed / (60 * 60), (elapsed / 60) % 60, elapsed % 60);
- } /* End of void update_rate() */
-
- /**********************************************************
- * long bfopen(struct Vars *v, UBYTE *mode)
- *
- * Buffered file I/O fopen() interface routine
- **********************************************************/
- long 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 */
- return (*v->io.xpr_fopen) (v->Filename, mode);
- } /* End of long bfopen() */
-
- /**********************************************************
- * void bfclose(struct Vars *v)
- *
- * Buffered file I/O fclose() interface routine
- **********************************************************/
- void bfclose(struct Vars *v)
- {
- if (v->File)
- {
- /* If bfwrite() left data 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);
-
- /* Let's see if we should muck with the file attributes. */
- if (v->SetAttributes && (v->FileAttributes & 2))
- {
- ULONG Bits = 0, Seconds;
-
- /* Convert UTC to local time. */
- if (v->Modtime > GMT_Offset)
- Seconds = v->Modtime - GMT_Offset;
- else
- Seconds = 0;
-
- /* Take care of the owner bits. */
- if (v->Bits & 0100)
- Bits |= FIBF_EXECUTE;
-
- if (v->Bits & 0200)
- Bits |= FIBF_WRITE | FIBF_DELETE;
-
- if (v->Bits & 0400)
- Bits |= FIBF_READ;
-
- /* Now for the group bits. */
- if (!(v->Bits & 0010))
- Bits |= FIBF_GRP_EXECUTE;
-
- if (!(v->Bits & 0020))
- Bits |= FIBF_GRP_WRITE | FIBF_GRP_DELETE;
-
- if (!(v->Bits & 0040))
- Bits |= FIBF_GRP_READ;
-
- /* Now for the other bits. */
- if (!(v->Bits & 0001))
- Bits |= FIBF_OTR_EXECUTE;
-
- if (!(v->Bits & 0002))
- Bits |= FIBF_OTR_WRITE | FIBF_OTR_DELETE;
-
- if (!(v->Bits & 0004))
- Bits |= FIBF_OTR_READ;
-
- /* Try to change the attributes. */
- SetProtection(v->Filename, Bits);
-
- /* Now for the modification date. */
- if (Seconds)
- {
- struct DateStamp __aligned Date;
-
- Date.ds_Days = Seconds / 86400;
- Date.ds_Minute = (Seconds % 86400) / 60;
- Date.ds_Tick = (Seconds % 60) * TICKS_PER_SECOND;
-
- SetFileDate(v->Filename, &Date);
- }
- }
-
- v->File = NULL;
- }
- } /* End of void bfclose() */
-
- /**********************************************************
- * void bfseek(struct Vars *v, long pos)
- *
- * 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 & discard buffer contents to force new read */
- }
- else
- {
- (*v->io.xpr_fseek) (v->File, pos, 0L);
- v->Filebuflen = v->Filebufcnt = 0;
- v->Filebufpos = pos;
- }
- } /* End of void bfseek() */
-
- /**********************************************************
- * long bfread(struct Vars *v, UBYTE *buf, long length)
- *
- * 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);
- 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);
- /* If we hit the EOF, return with however much we read so far */
- if (!v->Filebufcnt)
- break;
- }
- }
- return total;
- } /* End of long bfread() */
-
- /**********************************************************
- * long bfwrite(struct Vars *v, UBYTE *buf, long length)
- *
- * 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);
- 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);
- if (count < v->Filebufcnt)
- return -1;
- v->Filebufptr = v->Filebuf;
- v->Filebufcnt = 0;
- v->Fileflush = FALSE;
- }
- }
- return total;
- } /* End of long bfwrite() */
-
- /**********************************************************
- * void ioerr(struct XPR_IO *io, char *msg)
- *
- * 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);
- }
- } /* End of void ioerr() */
-
- /**********************************************************
- * void upderr(struct Vars *v, char *msg)
- *
- * 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 = (STRPTR) msg;
- if ((STRPTR) msg == v->Msgbuf) /* Ensure message length < 50 */
- msg[48] = '\0';
- (*v->io.xpr_update) (&v->xpru);
- } /* End of void upderr() */
-
- /**********************************************************
- * void updmsg(struct Vars *v,char *msg)
- *
- * 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 = (STRPTR) msg;
- if ((STRPTR) msg == v->Msgbuf) /* Ensure message length < 50 */
- msg[48] = '\0';
- (*v->io.xpr_update) (&v->xpru);
- } /* End of void updmsg() */
-
- /**********************************************************
- * long getfree(void)
- *
- * 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(struct Vars *v)
- {
- LONG Space = 0x7FFFFFFF; /* = Unknown */
-
- /*
- UBYTE NameBuffer[256],*Index;
- BPTR FileLock;
- strcpy(NameBuffer,v -> Filename);
-
- Index = PathPart(NameBuffer);
-
- *Index = 0;
-
- if(FileLock = Lock(NameBuffer,ACCESS_READ))
- {
- struct InfoData __aligned InfoData;
-
- if(Info(FileLock,&InfoData))
- {
- if(InfoData . id_NumBlocks >= InfoData . id_NumBlocksUsed)
- Space = (InfoData . id_NumBlocks - InfoData . id_NumBlocksUsed) * InfoData . id_BytesPerBlock;
- }
-
- UnLock(FileLock);
- }
- */
- return (Space);
-
- } /* End of long getfree() */
-
- /**********************************************************
- * char exist(struct Vars *v)
- *
- * Check whether file already exists; used to detect
- * potential overwrites
- **********************************************************/
- char exist(struct Vars *v)
- {
- long file;
-
- file = (*v->io.xpr_fopen) (v->Filename, "r");
- if (file)
- {
- (*v->io.xpr_fclose) (file);
- return TRUE;
- }
- else
- return FALSE;
- } /* End of char exist() */
-
- /* End of Utils.c source */
-