page%swap@Sun.COM (Bob Page) (08/21/89)
Submitted-by: papa@pollux.usc.edu (Marco Papa) Posting-number: Volume 89, Issue 170 Archive-name: comm/xpr.1 This is a standard method of using Amiga shared libraries for the implementation of external file transfer protocols, as (partially) implemented in the Amiga terminal emulator VLT (but applicable to any terminal emulator). [uuencoded library enclosed. ..bob] # This is a shell archive. # Remove anything above and including the cut line. # Then run the rest of the file through 'sh'. # Unpacked files will be owned by you and have default permissions. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: SHell ARchive # Run the following text through 'sh' to create: # funky.asm # libface.asm # liblink.asm # makefile # protolib.c # protolib.h # rtag.asm # timeout.c # vltface.asm # xprascii.c # xprfuncs.c # xprlib.uu # xproto.h # This is archive 1 of a 2-part kit. # This archive created: Sun Aug 20 23:01:47 1989 echo "extracting funky.asm" sed 's/^X//' << \SHAR_EOF > funky.asm X;;; funky.asm X; X; DESCRIPTION: X; =========== X; X; Initial startup routine for Aztec C. X; Copyright (C) 1986 by Manx Software Systems, Inc. X; X; But FUNKIFIED by Jim Mackraz. X; X;;; X X X; library base in D0 X; segment list in A0 X; execbase in A6 X X X; NOTE: code down to "start" must be placed at beginning of X; all programs linked with Aztec Linker using small X; code or small data. X X Xa4save dc.l 0 X X public .begin ; just to resolve label X.begin X public _funkyInit X_funkyInit: X X near code X X movem.l d0/d2/d3/d4-d7/a2-a6,-(sp) X X ; FUNKY use a0, not a1 for segment list X move.l a0,a4 ;BPTR to code seg X add.l a4,a4 X add.l a4,a4 ;now real address of code seg X X move.l (a4),a4 ;indirect to get data segment BPTR X add.l a4,a4 ;convert to real pointer X add.l a4,a4 ;real address of data seg link field X X ; same as crt0.a68 X add.l #32766+4,a4 ;bias appropriately (+4 is for link) X lea __H1_end,a1 X lea __H2_org,a2 X cmp.l a1,a2 ;check if BSS and DATA together X bne start ;no, don't have to clear X move.w #((__H2_end-__H2_org)/4)-1,d1 X bmi start ;skip if no bss X move.l #0,d2 Xloop X move.l d2,(a1)+ ;clear out memory X dbra d1,loop X Xstart X lea a4save,a1 ;get address of a4save X move.l a4,(a1) ;save a4 X; FUNKY X; move.l sp,__savsp ;save stack pointer (can't fexec) X; move.l 4,a6 ;get Exec's library base pointer X move.l a6,_SysBase ;put where we can get it X X movem.l d0/a0,-(sp) ; pass base and seglist X jsr _funkymain ; FUNKY X addq.l #8,sp ;pop args to funkymain() X ; can pop better (?) X X movem.l (sp)+,d0/d2/d3/d4-d7/a2-a6 X rts ;and return X X public _geta4 X_geta4: X move.l a4save,a4 X rts X X dseg X X X_SysBase dc.l 0 X X public _funkymain X public _SysBase X public __H1_end,__H2_org,__H2_end X X end X SHAR_EOF echo "extracting libface.asm" sed 's/^X//' << \SHAR_EOF > libface.asm X;;; libface.c X; X; DESCRIPTION: X; =========== X; X; This is the skeleton for an Amiga Exec library. X; This version is written for Aztec C. It is based on the example X; library by Jim Mackraz who got some stuff from Neil Katin. X; This library implements a protocol transfer library. X; All changes and additions by me. X; X; AUTHOR/DATE: W.G.J. Langeveld, February 1989. X; ============ X; X;;; X X include 'exec/types.i' X Xsetup macro X movem.l d2/d3/d4-d7/a2-a6,-(sp) X jsr _geta4 ;set up a4 for small model X endm X Xpush macro X move.l \1,-(sp) X endm X Xfix macro X ifc '\1','' X mexit X endc X ifle \1-8 X addq.l #\1,sp X endc X ifgt \1-8 X lea \1(sp),sp X endc X endm X Xrestore macro X fix \1 X movem.l (sp)+,d2/d3/d4-d7/a2-a6 X rts X endm X X dseg X X public _libfunctab X_libfunctab: X dc.l XPRopen X dc.l XPRclose X dc.l XPRexpunge X dc.l $0000 X dc.l XPRXProtocolCleanup X dc.l XPRXProtocolSetup X dc.l XPRXProtocolSend X dc.l XPRXProtocolReceive X dc.l $ffffffff X X cseg X X ;--- library functions X public _XPROpen X public _XPRClose X public _XPRExpunge X public _XProtocolCleanup X public _XProtocolSetup X public _XProtocolSend X public _XProtocolReceive X X public _geta4 X XXPRopen: X setup X push a6 X jsr _XPROpen X restore 4 X XXPRclose: X setup X push a6 X jsr _XPRClose X restore 4 X XXPRexpunge: X setup X push a6 X jsr _XPRExpunge X restore 4 X XXPRXProtocolCleanup: X setup X push a0 X jsr _XProtocolCleanup X restore 4 X XXPRXProtocolSetup: X setup X push a0 X jsr _XProtocolSetup X restore 4 X XXPRXProtocolSend: X setup X push a0 X jsr _XProtocolSend X restore 4 X XXPRXProtocolReceive: X setup X push a0 X jsr _XProtocolReceive X restore 4 X X X end SHAR_EOF echo "extracting liblink.asm" sed 's/^X//' << \SHAR_EOF > liblink.asm X; liblink.asm -- jimm mackraz, oct 28, 1986 X; application side interface for C-routines calling example library X X include 'exec/types.i' X include 'exec/libraries.i' X X LIBINIT X LIBDEF _LVOXProtocolCleanup X LIBDEF _LVOXProtocolSetup X LIBDEF _LVOXProtocolSend X LIBDEF _LVOXProtocolReceive X X ; --- xref from application X public _XProtocolBase X X ; --- xdef for application X public _XProtocolCleanup X public _XProtocolSetup X public _XProtocolSend X public _XProtocolReceive X X_XProtocolCleanup: X movea.l 4(sp),a0 ; First argument on stack X move.l _XProtocolBase,a6 X jmp _LVOXProtocolCleanup(a6) X X_XProtocolSetup: X movea.l 4(sp),a0 ; First argument on stack X move.l _XProtocolBase,a6 X jmp _LVOXProtocolSetup(a6) X X_XProtocolSend: X movea.l 4(sp),a0 ; First argument on stack X move.l _XProtocolBase,a6 X jmp _LVOXProtocolSend(a6) X X_XProtocolReceive: X movea.l 4(sp),a0 ; First argument on stack X move.l _XProtocolBase,a6 X jmp _LVOXProtocolReceive(a6) X SHAR_EOF echo "extracting makefile" sed 's/^X//' << \SHAR_EOF > makefile X### makefile X# X# DESCRIPTION: X# =========== X# X# This is the makefile for the xprascii.library. X# This version is written for Aztec C. It is based on the example X# library by Jim Mackraz who got some stuff from Neil Katin. X# All changes and additions by me. X# X# AUTHOR/DATE: W.G.J. Langeveld, February 1989. X# ============ X# X### X XAll: xprascii.library xpr.lib X X# The order in the following is important! Xxprascii.library: xprascii.o timeout.o funky.o protolib.o rtag.o libface.o X ln -g -o xprascii.library xprascii.o timeout.o funky.o protolib.o \ X rtag.o libface.o -lc X copy xprascii.library libs: X Xxpr.lib: liblink.o X lb xpr.lib -v liblink.o X copy xpr.lib disk2:lib X Xxprfuncs.o: xprfuncs.c xproto.h X cc xprfuncs.c X Xliblink.o: liblink.asm X as liblink.asm X Xxprascii.o: xprascii.c xproto.h X cc xprascii.c X Xtimeout.o: timeout.c X cc timeout.c X Xprotolib.o: protolib.c protolib.h X cc protolib.c X Xrtag.o: rtag.asm X as rtag.asm X Xfunky.o: funky.asm X as funky.asm X Xlibface.o: libface.asm X as libface.asm X SHAR_EOF echo "extracting protolib.c" sed 's/^X//' << \SHAR_EOF > protolib.c X/** protolib.c X* X* DESCRIPTION: X* =========== X* X* An exec library compiled with Aztec 3.40b, small model. X* X* Based on "elib", an example library: X* created by jim mackraz using mylib.asm by neil katin. X* May be used and distributed providing this comment block X* is retained in the source code. X* X* THIS VERSION: X* ============ X* X* X* This version implements a protocol transfer handler. X* This file only handles the calls to Open, Close and Expunge. X* X* AUTHOR/DATE: W.G.J. Langeveld, February 1989. X* ============ X* X**/ X X#include "protolib.h" X Xextern PFL libfunctab[]; /* XPR function table (libface.asm) */ Xextern LONG funkyInit(); /* hacked up version of Aztec crt0.a68 */ X XLONG XPRExpunge(); X Xstruct InitTable XPRInitTab = { X sizeof (struct XPRBase), X libfunctab, X NULL, /* will initialize XPR data in funkymain() */ X funkyInit X}; X Xextern UWORD XPRrevision; X Xextern char XPRname[]; Xextern char XPRid[]; Xextern struct Resident XPRRomTag; X Xunsigned long XPRO = ('X' << 24) | ('P' << 16) | ('R' << 8) | 'O'; X X/** X* X* This function is Jim's C-language library initRoutine. It is called X* by funkyInit() after register saves and small model initialization is X* done. X* X**/ XLONG funkymain(libbase, seglist) Xstruct XPRBase *libbase; XULONG seglist; X{ X register struct XPRBase *base; X/* X* Cookie X*/ X base = libbase; X/* X* Debug kind of stuff X*/ X base->mb_Cookie = XPRO; X base->mb_SegList = seglist; X/* X* init. library structure (since I don't do automatic data init.) X*/ X base->mb_Lib.lib_Node.ln_Type = NT_LIBRARY; X base->mb_Lib.lib_Node.ln_Name = (char *) XPRname; X base->mb_Lib.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED; X base->mb_Lib.lib_Version = XPRRomTag.rt_Version; X base->mb_Lib.lib_Revision = XPRrevision; X base->mb_Lib.lib_IdString = (APTR) XPRid; X X return; X} X X X/** X* X* Open library. Baseptr in A6, version in D0. X* X**/ XLONG XPROpen(base) Xstruct XPRBase *base; X{ X/* X* Don't allow more than one open on this one. These libraries are X* typically non-reentrant. X*/ X if (base->mb_Lib.lib_OpenCnt) return(NULL); X/* X* mark us as having another customer X*/ X base->mb_Lib.lib_OpenCnt++; X/* X* prevent delayed expunges (standard procedure) X*/ X base->mb_Lib.lib_Flags &= ~LIBF_DELEXP; X X return ((LONG) base); X} X X/** X* X* Close library X* X**/ XLONG XPRClose(base) Xstruct XPRBase *base; X{ X LONG retval = 0; X X if ((--base->mb_Lib.lib_OpenCnt == 0) && X (base->mb_Lib.lib_Flags & LIBF_DELEXP)) { X/* X* No more people have me open, X* and I have a delayed expunge pending: X* return segment list. X*/ X retval = XPRExpunge(); X } X X return (retval); X} X X/** X* X* Expunge library X* X**/ XLONG XPRExpunge(base) Xstruct XPRBase *base; X{ X ULONG seglist = 0; X LONG libsize; X X if (base->mb_Lib.lib_OpenCnt == 0) { X/* X* Really expunge: remove libbase and freemem X*/ X seglist = base->mb_SegList; X X Remove(base); X X libsize = base->mb_Lib.lib_NegSize + base->mb_Lib.lib_PosSize; X X FreeMem((char *) base - base->mb_Lib.lib_NegSize, (LONG) libsize); X } X else { X base->mb_Lib.lib_Flags |= LIBF_DELEXP; X } X/* X* Return NULL or real seglist X*/ X return ((LONG) seglist); X} X X SHAR_EOF echo "extracting protolib.h" sed 's/^X//' << \SHAR_EOF > protolib.h X/** protolib.h X* X* DESCRIPTION: X* =========== X* X* Header file for protolib.c. X* X**/ X X#include <exec/types.h> X#include <exec/nodes.h> X#include <exec/resident.h> X#include <exec/libraries.h> X X#include <functions.h> X Xtypedef LONG (*PFL)(); /* pointer to function returning 32-bit int */ X X/* library initialization table, used for AUTOINIT libraries */ Xstruct InitTable { X ULONG it_DataSize; /* library data space size */ X PFL *it_FuncTable; /* table of entry points */ X APTR it_DataInit; /* table of data initializers */ X PFL it_InitFunc; /* initialization function to run */ X}; X Xstruct XPRBase { X struct Library mb_Lib; X ULONG mb_Cookie; /* looks good */ X ULONG mb_SegList; X ULONG mb_Flags; X APTR mb_ExecBase; /* pointer to exec base */ X APTR mb_A4; /* proper value of A4 for aztec small model */ X}; X X SHAR_EOF echo "extracting rtag.asm" sed 's/^X//' << \SHAR_EOF > rtag.asm X;;; rtag.asm X; X; DESCRIPTION: X; =========== X; X; This is the romtag structure for an Amiga Exec library. X; This version is written for Aztec C by Jim Mackraz. X; X;;; X X include 'exec/types.i' X include 'exec/resident.i' X include 'exec/nodes.i' X include 'exec/libraries.i' X XXPRVERSION equ 0 XXPRPRI equ 0 X X cseg ; romtag must be in first hunk X X public _XPRname X public _XPRid X public _XPRInitTab X X ds 0 X public _XPRRomTag X_XPRRomTag: X dc.w RTC_MATCHWORD X dc.l _XPRRomTag X dc.l endtag X dc.b RTF_AUTOINIT X dc.b XPRVERSION X dc.b NT_LIBRARY X dc.b XPRPRI X dc.l _XPRname X dc.l _XPRid X dc.l _XPRInitTab Xendtag: X X X end SHAR_EOF echo "extracting timeout.c" sed 's/^X//' << \SHAR_EOF > timeout.c X/** timeout.c X* X* Roll-yer-own Delay() function. X* X**/ X#include <exec/exec.h> X#include <devices/timer.h> X#include <functions.h> X X#define TRSIZE ((long) sizeof(struct timerequest)) X XTimeOut(ticks) Xlong ticks; X{ X long secs, micros; X struct timerequest *Timereq = NULL; X struct MsgPort *Timerport = 0L; X X if (ticks == 0L) return; X X Timerport = CreatePort(0L, 0L); X if (Timerport == NULL) goto cleanup; X X Timereq = (struct timerequest *) AllocMem(TRSIZE, MEMF_PUBLIC | MEMF_CLEAR); X if (Timereq == NULL) goto cleanup; X X if (OpenDevice(TIMERNAME, UNIT_VBLANK, Timereq, 0L) != NULL) goto cleanup; X/* X* Set up timer request. X*/ X secs = ticks / 50L; X micros = (ticks % 50L) * 20000L; X X Timereq->tr_node.io_Message.mn_ReplyPort = Timerport; X Timereq->tr_node.io_Command = TR_ADDREQUEST; X Timereq->tr_node.io_Flags = 0; X Timereq->tr_node.io_Error = 0; X Timereq->tr_time.tv_secs = secs; X Timereq->tr_time.tv_micro = micros; X/* X* Time out X*/ X SendIO(Timereq); X Wait(1L << Timerport->mp_SigBit); X/* X* Handle timer events. X*/ X GetMsg(Timerport); X/* X* Clean up X*/ Xcleanup: X if (Timereq) { X if (Timereq->tr_node.io_Message.mn_ReplyPort) CloseDevice(Timereq); X FreeMem(Timereq, TRSIZE); X } X if (Timerport) DeletePort(Timerport); X X return; X} SHAR_EOF echo "extracting vltface.asm" sed 's/^X//' << \SHAR_EOF > vltface.asm X;;; vltface.asm X; X; DESCRIPTION: X; =========== X; X; This is an interface to VLT callback functions to be handed to X; external protocol libraries. X; X; AUTHOR/DATE: W.G.J. Langeveld, March 1989. X; ============ X; X;;; X X public _geta4 X Xsetup macro X movem.l d2/d3/d4-d7/a2-a6,-(sp) X jsr _geta4 ; Get a4. X endm X Xpush macro X move.l \1,-(sp) X endm X Xfix macro X ifc '\1','' X mexit X endc X ifle \1-8 X addq.l #\1,sp X endc X ifgt \1-8 X lea \1(sp),sp X endc X endm X Xrestore macro X fix \1 X movem.l (sp)+,d2/d3/d4-d7/a2-a6 X rts X endm X X public _avlt_fopen X public _vlt_fopen X public _avlt_fclose X public _vlt_fclose X public _avlt_fread X public _vlt_fread X public _avlt_fwrite X public _vlt_fwrite X public _avlt_fseek X public _vlt_fseek X public _avlt_sread X public _vlt_sread X public _avlt_swrite X public _vlt_swrite X public _avlt_update X public _vlt_update X public _avlt_chkabort X public _vlt_chkabort X public _avlt_chkmisc X public _vlt_chkmisc X public _avlt_gets X public _vlt_gets X public _avlt_setserial X public _vlt_setserial X public _avlt_ffirst X public _vlt_ffirst X public _avlt_fnext X public _vlt_fnext X public _avlt_finfo X public _vlt_finfo X public _avlt_sflush X public _vlt_sflush X public _avlt_options X public _vlt_options X X_avlt_fopen: X setup X push a1 X push a0 X jsr _vlt_fopen X restore 8 X X_avlt_fclose: X setup X push a0 X jsr _vlt_fclose X restore 4 X X_avlt_fread: X setup X push a1 X push d1 X push d0 X push a0 X jsr _vlt_fread X restore 16 X X_avlt_fwrite: X setup X push a1 X push d1 X push d0 X push a0 X jsr _vlt_fwrite X restore 16 X X_avlt_fseek: X setup X push d1 X push d0 X push a0 X jsr _vlt_fseek X restore 12 X X_avlt_sread: X setup X push d1 X push d0 X push a0 X jsr _vlt_sread X restore 12 X X_avlt_swrite: X setup X push d0 X push a0 X jsr _vlt_swrite X restore 8 X X_avlt_update: X setup X push a0 X jsr _vlt_update X restore 4 X X_avlt_chkabort: X setup X jsr _vlt_chkabort X restore X X_avlt_chkmisc: X setup X jsr _vlt_chkmisc X restore X X_avlt_gets: X setup X push a1 X push a0 X jsr _vlt_gets X restore 8 X X_avlt_ffirst X setup X push a1 X push a0 X jsr _vlt_ffirst X restore 8 X X_avlt_fnext X setup X push a1 X push a0 X push d0 X jsr _vlt_fnext X restore 12 X X_avlt_sflush X setup X jsr _vlt_sflush X restore X X_avlt_setserial X setup X push d0 X jsr _vlt_setserial X restore 4 X X_avlt_finfo X setup X push d0 X push a0 X jsr _vlt_finfo X restore 8 X X_avlt_options X setup X push a0 X push d0 X jsr _vlt_options X restore 8 X SHAR_EOF echo "extracting xprascii.c" sed 's/^X//' << \SHAR_EOF > xprascii.c X/** xprascii.c X* X* These are the protocol transfer routines for a simple ASCII upload. X* X**/ X#include <exec/exec.h> X#include <functions.h> X#include <stdio.h> X/* X* xproto.h is the include file given in Appendix B. X*/ X#include "xproto.h" X/* X* The following two strings must exist. X*/ Xchar XPRname[] = "xprascii.library"; Xchar XPRid[] = "xprascii 0.9 (May 89)\r\n"; XUWORD XPRrevision = 9; X Xlong atol(); X/* X* The callxx...() routines are described later. They provide the X* assembler interface from the XPR library to the call-back routines. X*/ Xlong calla(), callaa(), callad(), calladd(), calladda(); X Xchar *malloc(); X X X/** X* X* Send a file X* X**/ Xlong XProtocolSend(IO) Xstruct XPR_IO *IO; X{ X long fp, r, i; X long brkflag = 0, fl = 0L, sd = 0L; X long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfread)(), X (*xsread)(), (*xchkabort)(); X unsigned char *buff = NULL, *serbuff = NULL; X struct XPR_UPDATE xpru; X X/* X* These are the call-backs we need. If any of them isn't provided, quit. X* Could do some error reporting if at least xupdate is there. X*/ X if ((xupdate = IO->xpr_update) == NULL) return(0L); X if ((xswrite = IO->xpr_swrite) == NULL) return(0L); X if ((xfopen = IO->xpr_fopen) == NULL) return(0L); X if ((xfclose = IO->xpr_fclose) == NULL) return(0L); X if ((xfread = IO->xpr_fread) == NULL) return(0L); X if ((xsread = IO->xpr_sread) == NULL) return(0L); X if ((xchkabort = IO->xpr_chkabort) == NULL) return(0L); X/* X* Allocate a few buffers. X*/ X buff = (unsigned char *) malloc(80); X serbuff = (unsigned char *) malloc(80); X/* X* If we ran out of memory, print a message. X* The argument needs to go in A0: calla does this for us. X*/ X if (buff == NULL || serbuff == NULL) { X xpru.xpru_updatemask = XPRU_ERRORMSG; X xpru.xpru_errormsg = "Ran out of memory!"; X calla(xupdate, &xpru); X return(0L); X } X/* X* Read the send delay, if a XProtocolSetup() was done before. X* If send delay is too large, cut it off at 10 seconds. X* In this example, the xpr_data field contains a null terminated string X* containing the number of ticks to delay each 80 characters. X*/ X if (IO->xpr_data) { X sd = atol(IO->xpr_data); X if (sd > 500L) sd = 500L; X } X/* X* Open the file. One could do wild card detection here. X* xfopen requires two arguments, in a0 and a1 respectively. X* Again, this must be done in assembler, and callaa does it. X*/ X fp = callaa(xfopen, IO->xpr_filename, "r"); X if (fp == NULL) { X free(buff); X free(serbuff); X xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME; X xpru.xpru_errormsg = "Failed to open input file"; X xpru.xpru_filename = IO->xpr_filename; X calla(xupdate, &xpru); X return(0L); X } X/* X* Start the transfer. See 3.8 for a discussion on how to implement X* xupdate. X*/ X xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME; X xpru.xpru_msg = "Starting ASCII Send"; X xpru.xpru_filename = IO->xpr_filename; X calla(xupdate, &xpru); X/* X* Now read 80 byte chunks from the file using xfread. X* xfread requires four arguments, a0, d0, d1 and a1. X*/ X xpru.xpru_blocks = 0L; X while (r = calladda(xfread, buff, 1L, 80L, fp)) { X/* X* Convert line feeds to carriage returns before sending to host. X* fl counts the characters. Display how many characters are sent. X*/ X for (i = 0L; i < r; i++) if (buff[i] == '\n') buff[i] = '\r'; X fl += r; X xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE; X xpru.xpru_bytes = fl; X xpru.xpru_blocks++; X xpru.xpru_blocksize = r; X calla(xupdate, &xpru); X callad(xswrite, buff, r); X/* X* Every 80 bytes, put out a message and delay if requested. X*/ X xpru.xpru_updatemask = XPRU_PACKETDELAY; X xpru.xpru_packetdelay = sd * 20L; /* msec! */ X calla(xupdate, &xpru); X/* X* Can't use Delay() here, because Delay() is in dos.library! X* However writing an equivalent function using the timer.device is X* trivial. X*/ X TimeOut(sd); X/* X* Eat any characters that might arrive from the serial port. X* calladd stores arg1 in a0, arg2 in d0, arg3 in d1. X* We're not really waiting for any characters: use a timeout of 0L. X*/ X while (calladd(xsread, serbuff, 80L, 0L) > 0L) ; X/* X* Check for "abort" here. Perhaps should call chkmisc() as well. X*/ X if (brkflag = xchkabort()) break; X } X/* X* Close the file X*/ X calla(xfclose, fp); X free(buff); X free(serbuff); X/* X* If we got here through chkabort() say Aborted. X*/ X xpru.xpru_updatemask = XPRU_MSG; X if (brkflag) xpru.xpru_msg = "Aborted"; X else xpru.xpru_msg = "Done"; X calla(xupdate, &xpru); X if (brkflag) return(0L); X else return(1L); X} X X X/** X* X* Receive a file. X* X**/ Xlong XProtocolReceive(IO) Xstruct XPR_IO *IO; X{ X long fp, r, i; X long brkflag = 0, fl = 0L, sd = 0L; X long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfwrite)(), X (*xsread)(), (*xchkabort)(); X unsigned char *serbuff = NULL; X struct XPR_UPDATE xpru; X X/* X* These are the call-backs we need. If any of them isn't provided, quit. X* Could do some error reporting if at least xupdate is there. X*/ X if ((xupdate = IO->xpr_update) == NULL) return(0L); X if ((xswrite = IO->xpr_swrite) == NULL) return(0L); X if ((xfopen = IO->xpr_fopen) == NULL) return(0L); X if ((xfclose = IO->xpr_fclose) == NULL) return(0L); X if ((xfwrite = IO->xpr_fwrite) == NULL) return(0L); X if ((xsread = IO->xpr_sread) == NULL) return(0L); X if ((xchkabort = IO->xpr_chkabort) == NULL) return(0L); X/* X* Allocate a buffer. X*/ X serbuff = (unsigned char *) malloc(80); X/* X* If we ran out of memory, print a message. X* The argument needs to go in A0: calla does this for us. X*/ X if (serbuff == NULL) { X xpru.xpru_updatemask = XPRU_ERRORMSG; X xpru.xpru_errormsg = "Ran out of memory!"; X calla(xupdate, &xpru); X return(0L); X } X/* X* Open the file. One could do wild card detection here. X* xfopen requires two arguments, in a0 and a1 respectively. X* Again, this must be done in assembler, and callaa does it. X*/ X fp = callaa(xfopen, IO->xpr_filename, "w"); X if (fp == NULL) { X free(serbuff); X xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME; X xpru.xpru_errormsg = "Failed to open output file"; X xpru.xpru_filename = IO->xpr_filename; X calla(xupdate, &xpru); X return(0L); X } X/* X* Start the transfer. See 3.8 for a discussion on how to implement X* xupdate. X*/ X xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME; X xpru.xpru_msg = "Starting ASCII Receive"; X xpru.xpru_filename = IO->xpr_filename; X calla(xupdate, &xpru); X/* X* Now read 80 byte chunks from the serial port using xsread. Stop X* when no characters arrive for 5 sec. X*/ X xpru.xpru_blocks = 0L; X while ((r = calladd(xsread, serbuff, 80L, 5000000L)) > 0L) { X/* X* Strip high-bit before storing in file. X* fl counts the characters. Display how many characters are received. X*/ X for (i = 0L; i < r; i++) serbuff[i] &= 0177; X fl += r; X xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE; X xpru.xpru_bytes = fl; X xpru.xpru_blocks++; X xpru.xpru_blocksize = r; X calla(xupdate, &xpru); X/* X* Write 80 byte chunks to the file using xwrite X*/ X calladda(xfwrite, serbuff, 1L, r, fp); X X/* X* Check for "abort" here. Perhaps should call chkmisc() as well. X*/ X if (brkflag = xchkabort()) break; X } X/* X* Close the file X*/ X calla(xfclose, fp); X free(serbuff); X/* X* If we got here through chkabort() say Aborted. X*/ X xpru.xpru_updatemask = XPRU_MSG; X if (brkflag) xpru.xpru_msg = "Aborted"; X else xpru.xpru_msg = "Done"; X calla(xupdate, &xpru); X if (brkflag) return(0L); X else return(1L); X} X X X/** X* X* Setup X* X**/ Xlong XProtocolSetup(IO) Xstruct XPR_IO *IO; X{ X long (*xupdate)(), (*xgets)(); X struct XPR_UPDATE xpru; X X if ((xupdate = IO->xpr_update) == NULL) return(0L); X if ((xgets = IO->xpr_gets) == NULL) return(0L); X/* X* Allocate a bit of memory for a data buffer X*/ X if (IO->xpr_data == NULL) { X if ((IO->xpr_data = (long *) malloc(256)) == NULL) { X xpru.xpru_updatemask = XPRU_ERRORMSG; X xpru.xpru_errormsg = "ASCII - Out of memory!"; X calla(xupdate, &xpru); X return(0L); X } X } X/* X* If setup string isn't handed to us, ask questions X*/ X if (IO->xpr_filename == NULL) { X/* X* Get the value for the send dealy X*/ X callaa(xgets, "Enter ASCII send delay (ticks, 1 tick = 20 msec)", X IO->xpr_data); X } X else { X strcpy(IO->xpr_data, IO->xpr_filename); X } X X return(1L); X} X X/** X* X* Cleanup X* X**/ Xlong XProtocolCleanup(IO) Xstruct XPR_IO *IO; X{ X if (IO->xpr_data) free(IO->xpr_data); X IO->xpr_data = NULL; X X return(1L); X} X X/** X* X* The following functions setup the proper registers for the call-back X* functions. X* X**/ X#asm X public _callad X_callad: X movea.l 8(sp),a0 ; Second argument goes in a0 X move.l 12(sp),d0 ; Third argument goes in d0 X/* X* Now this is a trick to avoid using another register. X* Charlie taught me this... X*/ X move.l 4(sp),-(sp) ; First argument is function X rts X X public _calladda X_calladda: X movea.l 8(sp),a0 ; Second argument goes in a0 X move.l 12(sp),d0 ; Third argument goes in d0 X move.l 16(sp),d1 ; Fourth argument goes in d1 X movea.l 20(sp),a1 ; Fifth argument goes in a1 X move.l 4(sp),-(sp) ; First argument is function X rts X X public _calla X_calla: X movea.l 8(sp),a0 ; Second argument goes in a0 X move.l 4(sp),-(sp) ; First argument is function X rts X X public _callaa X_callaa: X movea.l 8(sp),a0 ; Second argument goes in a0 X movea.l 12(sp),a1 ; Third argument goes in a1 X move.l 4(sp),-(sp) ; First argument is function X rts X X public _calladd X_calladd: X move.l 8(sp),a0 ; Second argument goes in a0 X move.l 12(sp),d0 ; Third argument goes in d0 X move.l 16(sp),d1 ; Fourth argument goes in d1 X move.l 4(sp),-(sp) ; First argument is function X rts X X#endasm X/* X* Could have added any other functions needed for other call-backs. X* Could have written a fancier single one... Could've... X*/ SHAR_EOF echo "extracting xprfuncs.c" sed 's/^X//' << \SHAR_EOF > xprfuncs.c X/** xprfuncs.c X* X* Call-back functions for eXternal PRotocol support X* X**/ X#include "vt100.h" X#include <stat.h> X/* X* xproto.h is given in Appendix B X*/ X#include "xproto.h" X/* X* xfer.h is a VLT private header file containing some information for X* file transfer protocols X*/ X#include "xfer.h" X X/* X* These are the C versions of the interface X*/ Xlong vlt_update(), vlt_swrite(), vlt_fread(), vlt_fopen(), X vlt_fclose(), vlt_gets(), vlt_sread(), vlt_chkabort(), X vlt_fwrite(), vlt_fseek(), vlt_ffirst(), vlt_fnext(), X vlt_sflush(), vlt_chkmisc(), vlt_setserial(), vlt_finfo(), X vlt_options(); X/* X* These are the assembly level glue functions, see vltface.asm X*/ Xextern long avlt_update(), avlt_swrite(), avlt_fread(), avlt_fopen(), X avlt_fclose(), avlt_gets(), avlt_sread(), avlt_chkabort(), X avlt_fwrite(), avlt_fseek(), avlt_ffirst(), avlt_fnext(), X avlt_sflush(), avlt_chkmisc(), avlt_setserial(), avlt_finfo(), X avlt_options(); X X/** X* X* This function initializes an XPR_IO structure. X* X**/ Xxpr_setup(IO) Xstruct XPR_IO *IO; X{ X/* X* NULL out all the functions we don't do yet. X* Fill the other ones with the addresses to the assembler glue version X* of the interface routines. See vltface.asm X*/ X IO->xpr_filename = NULL; X IO->xpr_fopen = avlt_fopen; X IO->xpr_fclose = avlt_fclose; X IO->xpr_fread = avlt_fread; X IO->xpr_fwrite = avlt_fwrite; X IO->xpr_sread = avlt_sread; X IO->xpr_swrite = avlt_swrite; X IO->xpr_sflush = avlt_sflush; X IO->xpr_update = avlt_update; X IO->xpr_chkabort = avlt_chkabort; X IO->xpr_chkmisc = avlt_chkmisc; X IO->xpr_gets = avlt_gets; X IO->xpr_setserial = avlt_setserial; X IO->xpr_ffirst = avlt_ffirst; X IO->xpr_fnext = avlt_fnext; X IO->xpr_finfo = avlt_finfo; X IO->xpr_fseek = avlt_fseek; X/* X* We support 1 extension field X*/ X IO->xpr_extension = 1L; X IO->xpr_options = avlt_options; X/* X* NULL out the XPR private data field. X*/ X IO->xpr_data = NULL; X X return; X} X X/** X* X* Interface to VLT's MsgDisplay() function. X* X**/ X/* X* These are formats for VLT's requester X*/ Xstatic char *xprnamfmt = "%s\n%s\n\n\n\n"; Xstatic char *filnamfmt = "\n\n%s\n\n\n"; Xstatic char *blksizfmt = "\n\n\n\nBlock: %6ld -- Block Size: %6ld\n"; Xstatic char *errtimfmt = "\n\n\n\n\nErrors: %6ld -- Timeouts: %6ld"; Xstatic char *delayfmt = "\n\n\n\n\nPacket delay %ld"; X/* X* Below are some VLT globals to orchestrate the display X*/ Xlong xpr_blocks = 0L, xpr_blocksize = 0L, xpr_errors = 0L, xpr_timeouts = 0L; X/* X* The function X*/ Xlong vlt_update(x) Xstruct XPR_UPDATE *x; X{ X extern struct Window *mywindow; X extern char *XPR_Name; X/* X* First time, determine the window size (50 chars wide, 5 lines tall). X*/ X SetMsgWindow(mywindow, 50, 6); X/* X* Use VLT's PostMsg function to display all the information. X*/ X if (x->xpru_updatemask & XPRU_PROTOCOL) { X PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_protocol); X } X if (x->xpru_updatemask & XPRU_MSG) { X PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_msg); X } X if (x->xpru_updatemask & XPRU_ERRORMSG) { X PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_errormsg); X } X if (x->xpru_updatemask & XPRU_FILENAME) { X PostMsg(mywindow, filnamfmt, x->xpru_filename); X } X if (x->xpru_updatemask & XPRU_PACKETDELAY) { X PostMsg(mywindow, delayfmt, x->xpru_packetdelay); X } X if (x->xpru_updatemask & (XPRU_BLOCKS | XPRU_BLOCKSIZE)) { X if (x->xpru_updatemask & XPRU_BLOCKS) xpr_blocks = x->xpru_blocks; X if (x->xpru_updatemask & XPRU_BLOCKSIZE) xpr_blocksize = x->xpru_blocksize; X PostMsg(mywindow, blksizfmt, xpr_blocks, xpr_blocksize); X } X if (x->xpru_updatemask & (XPRU_ERRORS | XPRU_TIMEOUTS)) { X if (x->xpru_updatemask & XPRU_ERRORS) xpr_errors = x->xpru_errors; X if (x->xpru_updatemask & XPRU_TIMEOUTS) xpr_timeouts = x->xpru_timeouts; X PostMsg(mywindow, errtimfmt, xpr_errors, xpr_timeouts); X } X return(0L); X} X X/** X* X* Prompt the user for input X* X**/ Xlong vlt_gets(s, t) Xchar *s, *t; X{ X/* X* Use VLT's DoRequest() function X*/ X return((long) DoRequest(mywindow, t, s, NULL, " Cancel ")); X} X X/** X* X* Write a string to the serial port X* X**/ Xlong vlt_swrite(s, n) Xchar *s; Xlong n; X{ X/* X* Use VLT's SendString() function X*/ X SendString(s, (int) n); X return(0L); X} X X/** X* X* Read characters from the serial port X* X**/ Xlong vlt_sread(buff, length, micros) Xunsigned char *buff; Xlong length, micros; X{ X extern int timeout; X long secs = 0L; X X if (buff == NULL) return(-1L); X/* X* Convert timeout to seconds and micros if necessary X*/ X if (micros) { X if (micros > 1000000L) { X secs = micros / 1000000L; X micros = micros % 1000000L; X } X } X/* X* Cheat! Only return a single character since we have such a nice X* readchar() function in VLT. One day I'll have to modify this to X* save the odd microsecond... X*/ X buff[0] = (unsigned char) readchar(secs, micros); X/* X* VLT has a global called timeout. This comes in xfer.h. X* If the read was successful, return having read a single character. X*/ X if (timeout == GOODREAD) return(1L); X/* X* Else return error condition X*/ X return(-1L); X} X X/** X* X* Flush the serial buffer. X* X**/ Xlong vlt_sflush() X{ X ClearBuffer(); X return(0L); X} X X/** X* X* Interfaces to stdio X* X**/ Xlong vlt_fopen(s, t) Xchar *s, *t; X{ X return((long) fopen(s, t)); X} X Xlong vlt_fclose(fp) XFILE *fp; X{ X return((long) fclose(fp)); X} X Xlong vlt_fread(buff, size, count, fp) Xchar *buff; Xlong size, count; XFILE *fp; X{ X int res; X res = fread(buff, (int) size, (int) count, fp); X return((long) res); X} X Xlong vlt_fwrite(buff, size, count, fp) Xchar *buff; Xlong size, count; XFILE *fp; X{ X int res; X res = fwrite(buff, (int) size, (int) count, fp); X return((long) res); X} X Xlong vlt_fseek(fp, offset, origin) XFILE *fp; Xlong offset; Xlong origin; X{ X int res; X res = fseek(fp, offset, (int) origin); X return((long) res); X} X X/* X* File name match (Marco's version). X*/ Xextern char *scdir(); /* MANX pattern matching function */ X Xlong vlt_ffirst(buff, pattern) Xchar *buff; Xchar *pattern; X{ X char *name; X X name = scdir(pattern); X if (name) { X strcpy(buff, name); X return(1L); X } X else return(0L); X} X Xlong vlt_fnext(oldstate, buff, pattern) Xlong oldstate; Xchar *buff; Xchar *pattern; X{ X return(vlt_ffirst(buff, pattern)); X} X X/** X* X* Check for Abort X* X**/ Xlong vlt_chkabort() X{ X/* X* VLT aborts its protocols when the escape key is pressed. X* CheckForKey loops over the UserPort messages looking for an escape. X*/ X return((long) CheckForKey(69)); X} X X/** X* X* Check for miscellaneous items X* X**/ Xlong vlt_chkmisc() X{ X/* X* VLT does nothing X*/ X return(0L); X} X X/** X* X* File information X* X**/ Xlong vlt_finfo(filename, infotype) Xchar *filename; Xlong infotype; X{ X struct stat st; X X if (infotype == 1L) { X if (stat(filename, &st) != -1) return(st.st_size); X else return(0L); X } X else if (infotype == 2L) { X return((long) (p_xlatemode + 1)); X } X} X X/** X* X* This function set the serial port and returns the current status. X* X**/ Xlong vlt_setserial(newstatus) Xlong newstatus; X{ X long oldstatus, getserial(); X X/* X* If only want to know current status return it X*/ X if (newstatus == -1L) return(getserial()); X/* X* Fields we don't support X*/ X if ( newstatus & 0xFF00E070L) return(-1L); X/* X* Baud rates we don't support X*/ X if ( ((newstatus & 0x00FF0000L) >> 16L) > 6L) return(-1L); X/* X* Otherwise get old status X*/ X oldstatus = getserial(); X/* X* Set new status X*/ X setserial(newstatus); X/* X* And return old status X*/ X return(oldstatus); X} X X/** X* X* Get current serial status X* X**/ Xstatic long getserial() X{ X static long pariarr[] = { 0x0000L, 0x0301L, 0x0101L, 0x0001L, 0x0003L, X 0x0400L, 0x1B01L, 0x1901L, 0x1801L, 0x1803L, X 0x1C00L, 0x1F01L, 0x1D01L, 0x1C01L, 0x1C03L }; X long oldstatus; X X oldstatus = pariarr[p_parity]; X/* X* No Xon/Xoff X*/ X if ((p_handshake & 1) == 0) oldstatus |= 0x0080L; X/* X* 7-wire X*/ X if (p_handshake & 2) oldstatus |= 0x0040L; X/* X* Baud rate X*/ X oldstatus |= ( ((long) p_baud) << 16L ); X} X X/** X* X* Set new serial status X* X**/ Xstatic int setserial(newstatus) Xlong newstatus; X{ X/* X* Parity X*/ X switch (newstatus & 0xFFFFL) { X case 0x0000L : X p_parity = 0; X break; X case 0x0301L : X p_parity = 1; X break; X case 0x0101L : X p_parity = 2; X break; X case 0x0001L : X p_parity = 3; X break; X case 0x0003L : X p_parity = 4; X break; X case 0x0400L : X p_parity = 5; X break; X case 0x1B01L : X p_parity = 6; X break; X case 0x1901L : X p_parity = 7; X break; X case 0x1801L : X p_parity = 8; X break; X case 0x1803L : X p_parity = 9; X break; X case 0x1C00L : X p_parity = 10; X break; X case 0x1F01L : X p_parity = 11; X break; X case 0x1D01L : X p_parity = 12; X break; X case 0x1C01L : X p_parity = 13; X break; X case 0x1C03L : X p_parity = 14; X break; X } X BaudService(4, p_parity); X/* X* Protocol X*/ X p_handshake = 0; X X if ((newstatus & 0x0080L) == 0) p_handshake = 1; X if ( newstatus & 0x0004L ) p_handshake |= 2; X X BaudService(3, p_handshake); X/* X* Baud rate X*/ X p_baud = (newstatus & 0x00FF0000) >> 16L; X BaudService(2, p_baud); X X return; X} X X/** X* X* Options function X* X**/ Xlong vlt_options(n, opt) Xlong n; Xstruct xpr_option *opt[]; X{ X char buff[256]; X long changed = 0L, i; X/* X* Just loop over the options until we have time to implement a single X* requester. X*/ X for (i = 0L; i < n; i++) { X strncpy(buff, opt[i]->xpro_value, (int) opt[i]->xpro_length); X if (DoRequest(mywindow, buff, opt[i]->xpro_description, NULL, " Cancel ")) { X strncpy(opt[i]->xpro_value, buff, (int) opt[i]->xpro_length); X changed |= (1L << i); X } X } X return(changed); X} SHAR_EOF echo "extracting xprlib.uu" sed 's/^X//' << \SHAR_EOF > xprlib.uu X Xbegin 644 xprascii.library XM```#\P`````````#``````````(```/Y````3@````$```/I```#^4Y5_VA"Z XMK?_P0JW_[$*M_^A"K?_(0JW_Q"!M``@K:``@_^1F!G``3EU.=2!M``@K:``8I XM_^!F!'``8.P@;0`(*V@`!/_<9@1P`&#<(&T`""MH``C_V&8$<`!@S"!M``@KO XM:``,_]1F!'``8+P@;0`(*V@`%/_09@1P`&"L(&T`""MH`"3_S&8$<`!@G#\\6 XM`%!.N@NP5$\K0/_(/SP`4$ZZ"Z)43RM`_\1*K?_(9P9*K?_$9B0K?````!#_> XM:$'Z`B8K2/]\2&W_:"\M_^1.N@8F4$]P`&``_U(@;0`(2J@`2&<D(&T`""\H. XM`$A.N@F26$\K0/_H#*T```'T_^AO""M\```!]/_H2'H![R!M``@O$"\M_]Q.^ XMN@7H3^\`#"M`__Q*K?_\9D`O+?_(3KH+*EA/+RW_Q$ZZ"R!83RM\````$O]H/ XM0?H!M2M(_WP@;0`(*U#_<$AM_V@O+?_D3KH%F%!/<`!@`/[$*WP````*_VA!H XM^@&C*TC_>"!M``@K4/]P2&W_:"\M_^1.N@5L4$]"K?^`+RW__$AX`%!(>``!0 XM+RW_R"\M_]1.N@4X3^\`%"M`__AG``#00JW_]&`B("W_]"!M_\@,,``*"`!FN XM#B`M__0@;?_($;P`#0@`4JW_]"`M__2PK?_X;=0@+?_XT:W_["M\````X/]HF XM*VW_[/^(4JW_@"MM__C_A$AM_V@O+?_D3KH$Y%!/+RW_^"\M_\@O+?_@3KH$! XMKD_O``PK?```"`#_:'(4("W_Z$ZZ",PK0/^82&W_:"\M_^1.N@2L4$\O+?_H; XM3KH$S%A/0J=(>`!0+RW_Q"\M_]!.N@2F3^\`$$J`;P)@Y"!M_\Q.D"M`__!FW XM!&``_Q`O+?_\+RW_V$ZZ!&A03R\M_\A.N@G`6$\O+?_$3KH)MEA/*WP````(G XM_VA*K?_P9PI!^@!S*TC_>&`(0?H`<2M(_WA(;?]H+RW_Y$ZZ!"903TJM__!G- XM!G``8`#]3'`!8`#]1E)A;B!O=70@;V8@;65M;W)Y(0!R`$9A:6QE9"!T;R!OD XM<&5N(&EN<'5T(&9I;&4`4W1A<G1I;F<@05-#24D@4V5N9`!!8F]R=&5D`$1O& XM;F4`3E7_;$*M__!"K?_L0JW_Z$*M_\@@;0`(*V@`(/_D9@9P`$Y=3G4@;0`(O XM*V@`&/_@9@1P`&#L(&T`""MH``3_W&8$<`!@W"!M``@K:``(_]AF!'``8,P@Z XM;0`(*V@`$/_49@1P`&"\(&T`""MH`!3_T&8$<`!@K"!M``@K:``D_\QF!'``# XM8)P_/`!03KH(@E1/*T#_R$JM_\AF)"M\````$/]L0?H!D"M(_X!(;?]L+RW_1 XMY$ZZ`PQ03W``8`#_9DAZ`8<@;0`(+Q`O+?_<3KH"_$_O``PK0/_\2JW__&8VH XM+RW_R$ZZ"#Y83RM\````$O]L0?H!5RM(_X`@;0`(*U#_=$AM_VPO+?_D3KH"M XMME!/<`!@`/\0*WP````*_VQ!^@%&*TC_?"!M``@K4/]T2&W_;"\M_^1.N@**V XM4$]"K?^$2'D`3$M`2'@`4"\M_\@O+?_03KH"AD_O`!`K0/_X2H!O?$*M__1@^ XM$B`M__0@;?_(T<`"$`!_4JW_]"`M__2PK?_X;>0@+?_XT:W_["M\````X/]L^ XM*VW_[/^,4JW_A"MM__C_B$AM_VPO+?_D3KH"%%!/+RW__"\M__A(>``!+RW_( XMR"\M_]1.N@'D3^\`%"!M_\Q.D"M`__!F!&``_V0O+?_\+RW_V$ZZ`=I03R\M; XM_\A.N@<R6$\K?`````C_;$JM__!G"D'Z`'<K2/]\8`A!^@!U*TC_?$AM_VPO5 XM+?_D3KH!HE!/2JW_\&<&<`!@`/WV<`%@`/WP4F%N(&]U="!O9B!M96UO<GDA6 XM`'<`1F%I;&5D('1O(&]P96X@;W5T<'5T(&9I;&4`4W1A<G1I;F<@05-#24D@7 XM4F5C96EV90!!8F]R=&5D`$1O;F4`3E7_G"!M``@K:``@__QF!G``3EU.=2!MB XM``@K:``L__AF!'``8.P@;0`(2J@`2&8V/SP!`$ZZ!E!43R!M``@A0`!(9B(K] XM?````!#_G$'Z`%0K2/^P2&W_G"\M__Q.N@#:4$]P`&"L(&T`"$J09AH@;0`(` XM+R@`2$AZ`$$O+?_X3KH`PD_O``Q@%"!M``@O$"!M``@O*`!(3KH$&E!/<`%@; XM`/]R05-#24D@+2!/=70@;V8@;65M;W)Y(0!%;G1E<B!!4T-)22!S96YD(&1E( XM;&%Y("AT:6-K<RP@,2!T:6-K(#T@,C`@;7-E8RD`3E4``"!M``A*J`!(9PX@+ XM;0`(+R@`2$ZZ!9A83R!M``A"J`!(<`%.74YU(&\`""`O``PO+P`$3G4@;P`(T XM("\`#"(O`!`B;P`4+R\`!$YU(&\`""\O``1.=2!O``@B;P`,+R\`!$YU(&\`J XM""`O``PB+P`0+R\`!$YU3E7_\$*M__1"K?_P2JT`"&8$3EU.=4*G0J=.N@<$W XM4$\K0/_P2JW_\&<``,)(>0`!``%(>``H3KH'TE!/*T#_]$JM__1G``"F0J<O@ XM+?_T2'@``4AZ`-1.N@@>3^\`$$J`9@``BG(R("T`"$ZZ`YXK0/_\<C(@+0`(N XM3KH#N"(\``!.($ZZ`V(K0/_X(&W_]"%M__``#B!M__0Q?``)`!P@;?_T0B@`E XM'B!M__1"*``?(&W_]"%M__P`("!M__0A;?_X`"0O+?_T3KH'Z%A/(&W_\'``2 XM$"@`#W(!X:$O`4ZZ!]Y83R\M__!.N@=L6$]*K?_T9R(@;?_T2J@`#F<*+RW_L XM]$ZZ!@983TAX`"@O+?_T3KH')%!/2JW_\&<*+RW_\$ZZ!HQ83V``_NQT:6UE4 XM<BYD979I8V4```````!(Y[\^*$C9S-G,*%39S-G,V?P``(`"0^R`]D7L@/:U4 XMR68.,CP`$&L(=``BPE')__Q#^O_*(HPI3H`N2.>`@$ZZ`!!0CTS??/U.=2AZC XM_[!.=4Y5```O"B1M``@E;(!"`"(E;0`,`"85?``)``A![(`")4@`"A5\``8`_ XM#G``$#H`[S5``!0U;(`L`!9![(`3)4@`&"1?3EU.=4Y5```@;0`(2F@`(&<&0 XM<`!.74YU(&T`"%)H`"`@;0`(`B@`]P`.("T`"&#D3E7__$*M__P@;0`(4V@`" XM($IH`"!F$B)M``@(*0`#``YG!F$,*T#__"`M__Q.74YU3E7_^$*M__P@;0`(2 XM2F@`(&9*(&T`""MH`";__"\M``A.N@8\6$\@;0`((FT`"#`H`!#0:0`2<@`RC XM`"M!__@O+?_X(&T`"'``,"@`$"!M``B1P"\(3KH%L%!/8`H@;0`(".@``P`.< XM("W__$Y=3G5*_```";@```G2@``)```````````1````,$CG/SY.NO[(+PY.G XMNO\06(],WWS\3G5(YS\^3KK^LB\.3KK_)EB/3-]\_$YU2.<_/DZZ_IPO#DZZ$ XM_T!8CTS??/Q.=4CG/SY.NOZ&+PA.NOR$6(],WWS\3G5(YS\^3KK^<"\(3KK[L XMA%B/3-]\_$YU2.<_/DZZ_EHO"$ZZ];18CTS??/Q.=4CG/SY.NOY$+PA.NOC0/ XM6(],WWS\3G4@;P`$(`@B;P`($-EF_$YU3E7__$CG""`D;0`(#!(`(&<&#!(`& XM"68$4HI@\'@`#!(`+68&>`%2BF`(#!(`*V8"4HI"K?_\8"0@2E**$!!(@$C`\ XM<@HO`"`M__Q.N@`Z(A_2@)*\````,"M!__P0$DB`4D!![(!J"#```@``9LI*T XM1&<(("W__$2`8`0@+?_\3-\$$$Y=3G5(YW``-`'$P"8!2$/&P$A#0D/4@TA`7 XMP,%(0$)`T(),WP`.3G5(YT@`0H1*@&H$1(!21$J!:@9$@0I$``%A/DI$9P)$1 XM@$S?`!)*@$YU2.=(`$*$2H!J!$2`4D1*@6H"1(%A&B`!8-@O`6$2(`$B'TJ`X XM3G4O`6$&(A]*@$YU2.<P`$A!2D%F($A!-@$T`$)`2$"`PR(`2$`R`H+#,`%"X XM04A!3-\`#$YU2$$F`2(`0D%(04A`0D!T#]"`TX&V@6($DH-20%'*__),WP`,: XM3G5.50``2.<`,"1L@/9@%"92("H`!%"`+P`O"DZZ`VI03R1+(`IFZ$*L@/9,H XMWPP`3EU.=4Y5```O"D'Z_\8I2(#Z0J<@+0`(4(`O`$ZZ`Q`D0$J`4$]F"'``C XM)%].74YU)*R`]B5M``@`!"E*@/8@"E"`8.9.50``<``P+0`(+P!ALEA/3EU.8 XM=4Y5``!(YP`PE\LD;(#V8`X@;0`(48BQRF<2)DHD4B`*9NYP_TS?#`!.74YUG XM(`MG!":28`0I4H#V("H`!%"`+P`O"DZZ`KQP`%!/8-A.5?_\+P0P+0`(2,`K? XM0/_\2JR`_F<H>`!@"C\$3KH`_E1/4D2X;(#L;?`P+(#LP?P`!B\`+RR`_DZZJ XM`GI03TJL@/IG!B!L@/I.D$JL@/)G"B\L@/).N@$>6$]*K($"9P@@;($"(*R!4 XM!DJL@0IG"B\L@0I.N@$<6$]*K($.9PHO+($.3KH!#%A/2JR!$F<*+RR!$DZZV XM`/Q83TJL@19G"B\L@19.N@#L6$\L>``$""X`!`$I9Q0O#4OZ``I.KO_B*E]@& XM!D*G\U].<TJL@1IF,$JL@1YG*#`L@2)(P"\`+RR!'DZZ`=(P+($D4D!(P.6`8 XM+P`O+($F3KH!OD_O`!!@#DZZ`:@O+($:3KH"&%A/("W__"YL@2I.=2@?3EU.T XM=4Y5``!(YPX@."T`"#`$P?P`!B1`U>R`_DI$;0JX;(#L;`1*DF80.7P``H$NY XM</],WP1P3EU.=0@J``<`!&8(+Q).N@`*6$]"DG``8.(B+P`$+&R!,$[N_]Q.J XM^@`"(B\`!"QL@3!.[O^F(F\`!"QL@"Y.[OX^(F\`!"QL@"Y.[OYB3E4``$CG7 XM""!(>/__3KH`T"@`L+S_____6$]F"G``3-\$$$Y=3G5(>0`!``%(>``B3KH`O XMN"1`2H!03V8,+P1.N@#H<`!83V#6)6T`"``*%6T`#P`)%7P`!``(0BH`#A5$5 XM``]"ITZZ`)8E0``02JT`"%A/9PHO"DZZ`%I83V`*2&H`%$ZZ`,!83R`*8)).M XM50``+PHD;0`(2JH`"F<(+PI.N@#86$\5?`#_``@E?/____\`%'``$"H`#R\`% XM3KH`;$AX`"(O"DZZ`$Y/[P`,)%].74YU(F\`!"QL@"Y.[OZ>("\`!"QL@"Y.Z XM[OZV3OH``DSO``,`!"QL@"Y.[O\Z3OH``B)O``0L;(`N3N[^VBQL@"Y.[O]\? XM3OH``B)O``0@+P`(+&R`+D[N_RX@+P`$+&R`+D[N_K!.^@`"(&\`!"QL@"Y.9 XM[OZ,(&\`!""(6)!"J``$(4@`"$YU(&\`!$SO`@$`""(O`!`L;(`N3N[^1")O, XM``0L;(`N3N[_!")O``0L;(`N3N[^F")O``0L;(`N3N[^AB)O``0L;(`N3N[^F XM,B`O``0L;(`N3N[^P@```^P````#`````0``"<8```G*```)S@````(`````U XM```)N@``";X````````#\@```^H````]>'!R87-C:6DN;&EB<F%R>0!X<')AJ XM<V-I:2`P+CD@*$UA>2`X.2D-"@````D`````````-@```$0````````(5@``` XM4D\```G2```)Z```"?X````````*%```"BH```I````*5O____\`("`@("`@L XM("`@,#`P,#`@("`@("`@("`@("`@("`@(""00$!`0$!`0$!`0$!`0$!`#`P,$ XM#`P,#`P,#$!`0$!`0$`)"0D)"0D!`0$!`0$!`0$!`0$!`0$!`0$!`4!`0$!`> XM0`H*"@H*"@("`@("`@("`@("`@("`@("`@("0$!`0"```!0`````````````8 XM`^P````!`````0```#0````(`````````#P```!$````2````$P```!4````5 X=6````%P```!@`````````_(```/K`````0```_)$Q X`` Xend Xsize 4484 SHAR_EOF echo "extracting xproto.h" sed 's/^X//' << \SHAR_EOF > xproto.h X/** xproto.h X* X* Include file for External Protocol Handling X* X**/ X/* X* The structure X*/ Xstruct XPR_IO { X char *xpr_filename; /* File name(s) */ X long (*xpr_fopen)(); /* Open file */ X long (*xpr_fclose)(); /* Close file */ X long (*xpr_fread)(); /* Get char from file */ X long (*xpr_fwrite)(); /* Put string to file */ X long (*xpr_sread)(); /* Get char from serial */ X long (*xpr_swrite)(); /* Put string to serial */ X long (*xpr_sflush)(); /* Flush serial input buffer*/ X long (*xpr_update)(); /* Print stuff */ X long (*xpr_chkabort)(); /* Check for abort */ X long (*xpr_chkmisc)(); /* Check misc. stuff */ X long (*xpr_gets)(); /* Get string interactively */ X long (*xpr_setserial)(); /* Set and Get serial info */ X long (*xpr_ffirst)(); /* Find first file name */ X long (*xpr_fnext)(); /* Find next file name */ X long (*xpr_finfo)(); /* Return file info */ X long (*xpr_fseek)(); /* Seek in a file */ X long *xpr_extension; /* Number of extensions */ X long *xpr_data; /* Initialized by Setup. */ X long (*xpr_options)(); /* Multiple XPR options. */ X }; X/* X* Number of defined extensions X*/ X#define XPR_EXTENSION 1L X X/* X* The functions X*/ Xextern long XProtocolSend(), XProtocolReceive(), X XProtocolSetup(), XProtocolCleanup(); X/* X* The update structure X*/ Xstruct XPR_UPDATE { long xpru_updatemask; X char *xpru_protocol; X char *xpru_filename; X long xpru_filesize; X char *xpru_msg; X char *xpru_errormsg; X long xpru_blocks; X long xpru_blocksize; X long xpru_bytes; X long xpru_errors; X long xpru_timeouts; X long xpru_packettype; X long xpru_packetdelay; X long xpru_chardelay; X char *xpru_blockcheck; X char *xpru_expecttime; X char *xpru_elapsedtime; X long xpru_datarate; X long xpru_reserved1; X long xpru_reserved2; X long xpru_reserved3; X long xpru_reserved4; X long xpru_reserved5; X }; X/* X* The possible bit values for the xpru_updatemask are: X*/ X#define XPRU_PROTOCOL 0x00000001L X#define XPRU_FILENAME 0x00000002L X#define XPRU_FILESIZE 0x00000004L X#define XPRU_MSG 0x00000008L X#define XPRU_ERRORMSG 0x00000010L X#define XPRU_BLOCKS 0x00000020L X#define XPRU_BLOCKSIZE 0x00000040L X#define XPRU_BYTES 0x00000080L X#define XPRU_ERRORS 0x00000100L X#define XPRU_TIMEOUTS 0x00000200L X#define XPRU_PACKETTYPE 0x00000400L X#define XPRU_PACKETDELAY 0x00000800L X#define XPRU_CHARDELAY 0x00001000L X#define XPRU_BLOCKCHECK 0x00002000L X#define XPRU_EXPECTTIME 0x00004000L X#define XPRU_ELAPSEDTIME 0x00008000L X#define XPRU_DATARATE 0x00010000L X/* X* The xpro_option structure X*/ Xstruct xpr_option { X char *xpro_description; /* description of the option */ X long xpro_type; /* type of option */ X char *xpro_value; /* pointer to a buffer with the current value */ X long xpro_length; /* buffer size */ X}; X/* X* Valid values for xpro_type are: X*/ X#define XPRO_BOOLEAN 1L /* xpro_value is "yes", "no", "on" or "off" */ X#define XPRO_LONG 2L /* xpro_value is string representing a number */ X#define XPRO_STRING 3L /* xpro_value is a string */ X SHAR_EOF echo "End of archive 1 (of 2)" # if you want to concatenate archives, remove anything after this line exit