[comp.sources.amiga] v89i170: xpr - external file transfer protocol library, Part01/02

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