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