[comp.sources.atari.st] v01i042: zmdm -- terminal program with file transfer part02/08

koreth@ssyx.ucsc.edu (Steven Grimm) (05/30/88)

Submitted-by: bammi@mandrill.ces.cwru.edu (Jwahar R. Bammi)
Posting-number: Volume 1, Issue 42
Archive-name: zmdm/part02

#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file COMMON.H continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file COMMON.H"
sed 's/^X//' << 'SHAR_EOF' >> COMMON.H
Xextern int Noeofseen;
Xextern int Totsecs;		/* total number of sectors this file */
Xextern int Filcnt;		/* count of number of files opened */
Xextern int Lfseen;
Xextern unsigned int Rxbuflen;	/* Receiver's max buffer length */
Xextern int Tframlen;		/* Override for tx frame length */
Xextern int blkopt;		/* Override value for zmodem blklen */
Xextern int Rxflags;
Xextern char Lzconv;		/* Local ZMODEM file conversion request */
Xextern char Lztrans;
Xextern int Command;		/* Send a command, then exit. */
Xextern char *Cmdstr;		/* Pointer to the command string */
Xextern int Cmdtries;
Xextern int Cmdack1;		/* Rx ACKs command, then do it */
Xextern int Exitcode;
Xextern int Testattn;		/* Force receiver to send Attn, etc with qbf. */
Xextern char *qbf;
Xextern long Lastread;		/* Beginning offset of last buffer read */
Xextern int Lastc;		/* Count of last buffer read or -1 */
Xextern int Dontread;		/* Don't read the buffer, it's still there */
Xextern jmp_buf intrjmp;		/* For the interrupt on RX CAN */
Xextern jmp_buf abrtjmp;		/* for force abort */
Xextern int siggi;		/* Line interrupt enable flag */
Xextern int Wantfcs32;		/* want to send 32 bit FCS */
Xextern int Znulls;		/* Number of nulls to send at beginning of ZDATA hdr */
X
X#ifndef REMOTE
Xextern int *aline_addr;		/* Base addr of aline variables */
X#endif
X
Xextern int hlines;		/* # of lines on screen		*/
Xextern int rez;			/* current resolution		*/
Xextern int scolor;			/* current fg/bg screen color toggle */
X
X#ifndef REMOTE
Xextern long *ms_ptr;			/* Pointer to my screen memory */
X#if (MWC || MANX)
Xextern long *m_screen;
X#else
Xextern long m_screen[];
X#endif /* MWC || MANX */
X#endif /* REMOTE */
X
X#ifdef MWC
Xextern long _stksize;
X#endif /* MWC */
X
X#ifdef DLIBS
Xextern long _STKSIZE;
X#endif /* DLIBS */
X
X#ifdef MANX
Xextern long _STKSIZ;
X#endif /* MANX */
X
Xextern struct stat statbuf;		  /* Disk Transfer address for Find first etc */
Xextern int Baudrate;			  /* Current baud rate			      */
Xextern long drv_map;			  /* bit vector of valid drives */
X
Xextern BAUDS vbauds[];
Xextern IOREC save,	/* the original Iorec is saved here for the duration
X			   of this process */
X 	*savep;		/* ptr returned by Iorec() */
X
Xextern char iobuf[]; /* My large Rs232 receive buffer */
X
Xextern char *substr();
X
X#ifdef DYNABUF
Xextern long BBUFSIZ;
Xextern unsigned char *dalloc();
X#endif /* DYNABUF */
X
Xextern long pr_time;
X
X/* -eof- */
SHAR_EOF
echo "File COMMON.H is complete"
chmod 0600 COMMON.H || echo "restore of COMMON.H fails"
echo "x - extracting CONFIG.H (Text)"
sed 's/^X//' << 'SHAR_EOF' > CONFIG.H &&
X/*
X * 	Common Configuration file
X *
X *		Jwahar Bammi
X *			usenet: mandrill!bammi@{decvax,sun}.UUCP
X *			csnet:  bammi@mandrill.ces.CWRU.edu
X *			arpa:   bammi@mandrill.ces.CWRU.edu
X *			CompuServe: 71515,155
X */
X
X
X/*
X *	Compiler Type
X *
X *		Mark Williams C
X *			V2.0 or higher REQUIRED
X *			V3 tested. (V 3.0.6 is what i got)
X *
X *		Alcyon C
X *			V 4.14 only tested
X *			DLIBS compatible
X *			ALN OK
X *
X *		MegaMax C/Laser C (or whatever they call it)
X *			I refuse to use braindamaged tools !!
X *
X *		Manx Aztec C
X *			Version 3.6a tested. Produces great code!
X *
X *		Lattice C
X *			Don't have a copy
X *
X *	Comment out one of the #if 0 lines below corresponding to your
X *	compiler.
X */
X
X	/************** if using Mark Williams C **************/
X
X/* #if 0 */	/* Comment Out this line if using Mark Williams C */
X
X#define COMPILER	"Compiled with Mark Williams C V3.0.6"
X#ifndef MWC
X#define MWC 1
X#endif /* MWC */
X#ifdef DLIBS
X#undef DLIBS		/* only Alcyon version of DLIBS tested */
X#endif /* DLIBS */
X#ifdef ALCYON
X#undef ALCYON
X#endif /* ALCYON */
X#ifdef MANX
X#undef MANX
X#endif /* MANX */
X
X/* #endif */	 /* Comment Out this line if using Mark Williams C */
X
X	/************** if using Alcyon C **************/
X
X#if 0	/* comment out this line if using Alcyon C */
X
X#define COMPILER	"Compiled with Alcyon C V4.14"
X#ifndef ALCYON
X#define ALCYON 1
X#endif /* ALCYON */
X#ifdef MWC
X#undef MWC
X#endif /* MWC */
X#ifdef MANX
X#undef MANX
X#endif /* MANX */
X
X#endif	/* Comment Out this line if using Alcyon C */
X
X	/************** if using MANX C **************/
X
X#if 0	/* comment out this line if using MANX C */
X
X#define COMPILER	"Compiled with Manx Aztec C V3.6a"
X#ifndef MANX
X#define MANX 1
X#endif /* MANX */
X#ifdef MWC
X#undef MWC
X#endif /* MWC */
X#ifdef ALCYON
X#undef ALCYON
X#endif /* ALCYON */
X
X#endif 	/* Comment Out this line if using MANX C */
X
X/* ------------------------------------------------------------------------ */
X
X/*
X * Compile Stand Alone  versions of RZ and SZ
X *
X *	STANDALONE is #define'd, to compile `stand alone' alone versions
X *	of RZ and SZ instead of the integrated ZMDM. A lot of folks
X *	requested this feature.
X */
X
X#ifndef STANDALONE
X/* #define STANDALONE 1 */	/* define for standalone compilation */
X#endif /* STANDALONE */
X
X/* ------------------------------------------------------------------------ */
X
X/*
X * Compile a REMOTE version of ZMDM
X *	REMOTE is #define'd to compile a `remote' version of ZMDM. A remote
X *	versions talks through the serial port, instead of the keyboard/screen
X *	Useful for dialing up your ST to download/upload files. One of the
X *	local BBS's has this version available through a door to enable
X *	people to Up/Down load batch using Zmodem protocol.
X *
X */
X#ifndef REMOTE
X/* #define REMOTE 1 */		/* define for remote version */
X#endif /* REMOTE */
X/* ------------------------------------------------------------------------ */
X
X/*
X * Phone Services
X *	PHONES is #define'd to compile in the Phone Services module.
X *	if PHONES is #define'd you must also define PREDIAL and
X *	REDIAL, your modems dial and re-dial commands respectively.
X *	NOTE: The REMOTE version of ZMDM does not support the
X *	phones module.
X */
X
X#ifndef REMOTE
X/* #if 0 */		/* comment this line if you want the PHONES module */
X
X#define PHONES 1
X	/*********** CAUTION: modem specific ***********/
X#define PREDIAL		"ATDT"	/* Modems dial command */
X#define REDIAL		"A/"	/* Modems Re-dial command */
X
X/* #endif */		/* comment this line if you want the PHONES module */
X#endif /* REMOTE */
X
X/* ------------------------------------------------------------------------ */
X
X/*
X * Do flow control while doing terminal emulation -
X * this only needs to be defined if you are
X * going to be running Zmdm at 19200 Baud AND
X * you are going to be sending it (from the host)
X * greater that 16k characters in one blast, without
X * any pause whatsoever. For 99.95 % of us mortals
X * this will never be required. Even if it is defined
X * its no big deal, as flow control will not happen
X * unless the condition described above exists.
X * NOTE: flow control is turned off during file transfers.
X */
X/* #define FLOW_CTRL	1 */	/* do flow control */
X
X/* ------------------------------------------------------------------------*/
X
X/*
X *  DYNABUF
X *	If #define'd use up rest up memory less LEAVEALONE bytes for
X *	file buffers. The minimum acceptable size is MINACC
X */
X/* #if 0 */	/* Comment this line to use DYNABUF */
X
X#ifndef DYNABUF
X#define DYNABUF 1
X#define LEAVEALONE 16384L
X#define MINACC 	   8096L
X#endif
X
X/* #endif */	/* Comment this line to use DYNABUF */
X
X/* ------------------------------------------------------------------------*/
X
X/*
X * Size of file buffer
X *
X *	Must be defined. Must be a long. (only define when
X *	DYNABUF is NOT define'd).
X *
X */
X#ifndef DYNABUF
X#define BBUFSIZ		32768L		/* Size of file/capture buffer */
X#endif /* DYNABUF */
X
X/* ------------------------------------------------------------------------*/
X
X/*
X * Size of Rs232 buffer
X *
X *	Must be defined. Must be int (16 bits).
X */
X#define IBUFSIZ		16*1024	/* Size of my Rs232 receive buffer */
X
X/* ------------------------------------------------------------------------*/
X
X/*
X * GMTDIFF
X *	Number of seconds from GMT (signed).
X *	Must be defined.
X *	Must be long.
X */
X#define GMTDIFF	(-5L*3600L)	/* EST (usa) -ve means behind GMT */
X
X/* ------------------------------------------------------------------------*/
X
X/*
X * Define RECURSE only if you want the expand a directory
X * to all its children feature for `sz', when you specify
X * a directory name as an arg to `sz'.
X *
X */
X#define RECURSE 1
X
X/* ------------------------------------------------------------------------*/
X
X/* 
X * define BIGSTACK if you have very deep directory hierarchies
X *
X */
X#ifdef RECURSE
X/* #define BIGSTACK 1 */
X#endif /* RECURSE */
X
X/* ------------------------------------------------------------------------*/
X
X
X/* -eof- */
SHAR_EOF
chmod 0600 CONFIG.H || echo "restore of CONFIG.H fails"
echo "x - extracting DECL.H (Text)"
sed 's/^X//' << 'SHAR_EOF' > DECL.H &&
X 	/***********************************************\
X 	*						*
X 	*  Decl.h - extern declarations for C libarary  *
X 	*      must come after <stdio.h> is included    *
X	*						*
X	*    Preprocessor symbol `MWC' should be        *
X	*    defined when using Mark Williams C		*
X	*						*
X	*    Preprocessor symbol `MANX' should be       *
X	*    defined when using Manx Aztec C		*
X 	*						*
X	\***********************************************/
X
X#ifndef DECL_H
X
Xextern	FILE *fopen(), *freopen(), *fdopen();
X#if (!(MANX || MWC))
X#ifndef DLIBS
Xextern	FILE *fopena(), *freopa();
Xextern	FILE *fopenb(), *freopb();
X#endif /* DLIBS */
X#endif /* MANX || MWC */
X
X#if MANX
Xextern FILE *tmpfile();
X#endif
X
Xextern	char	*etoa();
Xextern	char	*ftoa();
X#if (!(MWC || MANX))
X#ifndef DLIBS
Xextern	char	*getpass();
X#endif
X#endif
X
X#ifndef MANX
Xextern	char	*index();
Xextern	char	*rindex();
X#endif
X
Xextern	char	*mktemp();
Xextern	char	*strcat();
Xextern	char	*strcpy();
Xextern	char	*strncat();
Xextern	char	*strncpy();
Xextern	char	*calloc(), *malloc(), *realloc();
X#if (MWC || MANX || DLIBS)
Xextern char *getenv();
X#endif
X
X#if (!(MWC || MANX))
Xextern	char	*sbrk();
X#endif
Xextern	char 	*gets(), *fgets();
X#if (!(MWC || MANX))
X#ifndef DLIBS
Xextern	char 	*ttyname();
X#endif
X#endif
X
X#if (MWC || MANX)
Xextern  char    *lmalloc(), *lcalloc(), *lrealloc();
X#endif
X
Xextern	double	atan();
Xextern	double	atof();
Xextern	double	ceil();
Xextern	double	cos();
Xextern	double	exp();
Xextern	double	fabs();
Xextern	double	floor();
Xextern	double	fmod();
Xextern	double	log();
Xextern	double	pow();
Xextern	double	sin();
Xextern	double	sinh();
Xextern	double	sqrt();
Xextern	double	tan();
Xextern	double	tanh();
X
Xextern	int	strlen();
Xextern	int	(*signal())();
X
Xextern	long 	atol();
Xextern	long 	ftell();
Xextern	long	getl();
X
X#ifndef DLIBS
Xextern	long 	lseek(), tell();
X#endif
X
X#if (MWC || MANX)
Xextern char	*memchr(), *memcpy(), *memset();
Xextern char	*strchr(), *strerror(), *strpbrk(), *strrchr();
Xextern char	*strstr(), *strtok();
Xextern double	log10();
Xextern double	frexp();
Xextern double	ldexp();
Xextern double	modf();
Xextern double	asin(), acos(), atan2(), cosh();
X#endif /* MWC || MANX */
X
X#ifdef MANX
Xextern char	*memmove(), *memccpy(), *lmemccpy(), *lmemcpy();
Xextern char	*lmemmove(), *lmemchr(), *lmemset(), *strdup();
Xextern char	*scdir(), *tmpnam(), *bsearch();
Xextern long	labs();
Xextern double	cotan();
X
X#define index	strchr
X#define rindex	strrchr
X
X#endif /* MANX */
X
X#define DECL_H
X#endif
X
X/* -eof- */
SHAR_EOF
chmod 0600 DECL.H || echo "restore of DECL.H fails"
echo "x - extracting EXPANDAR.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > EXPANDAR.C &&
X
X	/* 
X	 * 	Examine each argument given to expandargs()
X	 * 	If it is a directory, then expand it
X	 *	to all its component files, recursively
X	 *	till you bottom out.
X	 *	If it is not a directory, then just pass it on.
X	 *
X	 *	Inputs: routine, argc, argv
X	 *	Outputs: nargc, nargv (calls routine(nargc, nargv))
X	 *	To test: compile with -DTEST
X	 *		 define MWC if using Mark Williams C
X	 *		 run with a directory as an arg
X	 *	Author: JRB	bammi@mandrill.ces.CWRU.edu
X	 *	Requirements: Mark Williams C or Alcyon C
X	 *		Wants lots of Dynamic memory. It
X	 *		all depends upon how many files you
X	 *		have. Use the -P option to prune
X	 *		out subdirectories and do things
X	 *		one at a time, if you keep running
X	 *		out of memory.
X	 *		With Mark Williams i use _stksize = 128K
X	 *		With Alcyon i use memory model 2 (half of
X	 *		of avail memory) in GEMSTART.S
X	 *
X         *      WARNINGS: Be CAREFUL about the 40 folder bug. Use
X	 *	          GEMBOOT or FOLDRXXX when dealing with
X	 *		  a deeply nested file structure.
X	 *
X	 *	Added -P name prune option at the suggestion of dietz@zhmti
X	 *	Multiple -P's may be given on the command line.
X	 *	-P name may be given anywhere on the command line. -P name
X	 *	will prune the subdirectories named as arguement to -P.
X	 *	ie: when the program is decending the file hierarchy it
X	 *	will not visit the pruned branches.
X	 * 	NOTE that the option is -P and not -p
X	 *	      (-p is a valid sz option).
X	 *	NOTE that the arguement given to -P can be the name
X	 * 	of a file or a directory. In case it is a file,
X	 *	that file is skipped.
X	 *
X	 */
X
X/*
X * Expand argc, so that the called routine(nargc,nargv) receives only
X * filenames, in nargv[][]
X *
X ************************************************************************
X *									*
X *      WARNING:  Be CAREFUL about the 40 folder bug. Use		*
X *	          GEMBOOT or FOLDRXXX when dealing with			*
X *		  a deeply nested file structure.			*
X *									*
X ************************************************************************
X *
X *	Jwahar R. Bammi
X *			usenet: mandrill!bammi@{decvax,sun}.UUCP
X *			csnet:  bammi@mandrill.ces.CWRU.edu
X *			arpa:   bammi@mandrill.ces.CWRU.edu
X *			CompuServe: 71515,155
X *
X */
X
X#ifdef TEST
X#include <stdio.h>
X#include <osbind.h>
X#include <ctype.h>
X#endif
X
X#ifdef TRUE
X#undef TRUE
X#endif
X#ifdef OK
X#undef OK
X#endif
X#ifdef FALSE
X#undef FALSE
X#endif
X
X#define TRUE	 1
X#define OK	 0
X#define FALSE	 0
X#define Realloc	 realloc
X
X#ifdef TEST
Xstruct	stat
X{
X	char	st_sp1[21];    /* Junk 	   */
X	char	st_mode;       /* File attributes */
X	int	st_time;       /* Mod Time	  */
X	int     st_date;       /* Mod date	  */
X	long	st_size;       /* File size	   */
X	char	st_name[14];   /* File name	   */
X};
X#endif
X
Xtypedef struct _prunelist {
X	char *name;			/* name of subdirectory to prune */
X	struct _prunelist *next;	/* ptr to next */
X} PRUNELIST;
X
Xstatic char *ProgName;
Xstatic PRUNELIST *PruneList = (PRUNELIST *)NULL; /* Head of PruneList */
X
Xstatic char **CopyToNargv();
Xstatic char **ExpandStack();
Xstatic void FreeStack();
Xstatic void FreeNargv();
Xstatic void FreePrune();
Xstatic void FreeUp();
Xstatic int PushDir();
Xstatic char *PopDir();
Xstatic int ProcessDirs();
Xstatic PRUNELIST *AddPrune();
Xstatic int OnPruneList();
Xstatic int isdir();
X
Xextern int existd();
X
Xexpandargs(routine, argc, argv)
Xint (*routine)();
Xint argc;
Xchar **argv;
X{
X	register int status;
X	int nargc;
X	char **nargv;
X	extern char **CopyToNargv();
X	extern PRUNELIST *AddPrune();
X	extern int existd();
X
X	nargc = 0;
X	nargv = (char **)NULL;
X	ProgName = *argv;
X	
X	/* copy argv[0] blindly */
X	if((nargv = CopyToNargv(*argv, nargc, nargv)) == (char **)NULL)
X	{
X	    FreeUp(nargc, nargv);
X	    return(~OK);
X	}
X
X	nargc++;
X	
X	while((--argc) > 0)
X	{
X		argv++;
X		if(**argv == '-')
X		{
X			/* copy any options except -P */
X#ifdef TEST
X			/* some shell pass -P as -p */
X			if( ((*argv)[1] == 'P') || ((*argv)[1] == 'p'))
X#else
X			if( (*argv)[1] == 'P')
X#endif
X			{
X				if((--argc) <= 0)
X				{
X					fprintf(STDERR,"no argument given to -P\n");
X					FreeUp(nargc, nargv);
X					return(~OK);
X				}
X				if((PruneList = AddPrune(PruneList,*++argv))
X				   == (PRUNELIST *)NULL)
X				{
X				    FreeUp(nargc, nargv);
X				    return(~OK);
X				}
X			}
X			else
X			{
X				if((nargv = CopyToNargv(*argv, nargc, nargv))
X				   == (char **)NULL)
X				{
X				    FreeUp(nargc, nargv);
X				    return(~OK);
X				}
X				else
X				    nargc++;
X			}
X			
X		}
X		else
X		{
X			/* If its not on the PruneList then */
X			if(!OnPruneList(PruneList, *argv))
X			{
X				/* if it is a directory, push it */
X				if(existd(*argv))
X				{
X					if((status = PushDir(*argv)) != OK)
X					{
X						FreeUp(nargc, nargv);
X						return(status);
X					}
X				}
X				else
X				{
X				    /* it is NOT a directory, copy to nargv */
X					if((nargv = CopyToNargv(*argv, nargc, nargv))
X					   == (char **)NULL)
X					{
X					    FreeUp(nargc, nargv);
X					    return(~OK);
X					}
X					else
X					    nargc++;
X				}
X			}
X		}
X	} /* while */
X
X	/* process pushed directories if any */
X	if((status = ProcessDirs(&nargc, &nargv)) != OK)
X	{
X	    FreeUp(nargc, nargv);
X	    return(status);
X	}
X	/* else Free the Stack and Prune List, call *routine */
X	FreeStack();
X	FreePrune();
X	status =  (*routine)(nargc, nargv);
X	FreeNargv(nargc, nargv);
X
X	return status;
X
X}
X
X/*
X * Expand nargv by an element and copy a String into the new element
X *
X */
Xstatic char **CopyToNargv(string, nargc, nargv)
Xchar *string;
Xint nargc;
Xchar **nargv;
X{
X	extern char *malloc(), *Realloc(), *strcpy();
X	extern int strlen();
X	
X	/* expand nargv by 1 element */
X	if(nargv == (char **)NULL)
X	    /* do it with malloc for the first one */
X	    nargv = (char **)malloc(sizeof(char **));
X	else
X	    /* do it with Realloc for others */
X	    nargv = (char **)Realloc(nargv, (nargc+1)*sizeof(char **));
X	
X	if(nargv == (char **)NULL)
X	{
X		/* failed to get memory */
X		fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
X		return ((char **)NULL);
X	}
X
X	/* Get mem for string */
X	if(( nargv[nargc] = malloc(strlen(string)+1)) == (char *)NULL)
X	{
X		/* failed to get memory */
X		fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
X		return ((char **)NULL);
X	}
X
X	/* copy string into nargv[nargc] */
X	(void)strcpy( nargv[nargc], string);
X	return(nargv);
X}
X
Xstatic char **Stack = (char **)NULL;	/* directory stack */
Xstatic char StackSize = 0;		/* Size of current Stack */
Xstatic int    Top   = -1;
X#define STACK_EMPTY	(Top < 0)
X#define CHUNKSIZE	16
X
X/*
X * Grow the Stack by one chunk of CHUNKSIZE elements
X *
X */
Xstatic char **ExpandStack(Stack)
Xchar **Stack;
X{
X	extern char *malloc(), *Realloc();
X	
X	/* Grow Stack */
X	if(Stack == (char **)NULL)
X	    /* with malloc */
X	    Stack = (char **)malloc(CHUNKSIZE * sizeof(char **));
X	else
X	    /* with Realloc */
X	    Stack = (char **)Realloc(Stack, (StackSize+CHUNKSIZE) *
X				             sizeof(char **));
X
X	if(Stack == (char **)NULL)
X	{
X		/* outa mem */
X		fprintf(STDERR,"%s(ExpandStack()): Out of Memory\n", ProgName);
X		return((char **)NULL);
X	}
X	StackSize += CHUNKSIZE;
X	return(Stack);
X}
X
X/*
X * Free the Stack
X *
X */
Xstatic void FreeStack()
X{
X	if(StackSize > 0)
X		(void)free(Stack);
X	Stack = (char **)NULL;
X	StackSize = 0;
X	Top   = -1;
X}
X
X/*
X * Free Nargv
X *
X */
Xstatic void FreeNargv(nargc, nargv)
Xint nargc;
Xchar *nargv[];
X{
X	register int i;
X
X	for(i = 0; i < nargc; i++)
X		(void)free(nargv[i]);
X	if(nargc > 0)
X		(void)free(nargv);
X}
X
X/*
X * Free the PruneList
X *
X */
Xstatic void FreePrune()
X{
X	register PRUNELIST *p, *next;
X
X	for(p = PruneList; p != (PRUNELIST *)NULL; p = next)
X	{
X		next = p->next;
X		(void)free(p);
X	}
X	PruneList = (PRUNELIST *)NULL;
X}
X
X/*
X * FreeUp before bad exit
X *
X */
Xstatic void FreeUp(nargc, nargv)
Xint nargc;
Xchar **nargv;
X{
X	FreeStack();
X	FreePrune();
X	FreeNargv(nargc, nargv);
X}
X
X/*
X * Push a directory name on Stack
X *
X */
Xstatic int PushDir(name)
Xchar *name;
X{
X	extern char *malloc(), *strcpy();
X	extern int strlen();
X	extern char **ExpandStack();
X
X#ifdef DDEBUG
Xprintf("PushDir: %s\n", name);
X#endif
X
X	++Top;
X	if(Top >= StackSize)
X	{
X		if((Stack = ExpandStack(Stack)) == (char **)NULL)
X		    return(~OK);
X	}
X	
X	if((Stack[Top] = malloc(strlen(name)+1)) == (char *)NULL)
X	{
X		/* outa mem */
X		fprintf(STDERR,"%s(PushDir()): Out of Memory\n", ProgName);
X		return(~OK);
X	}
X	(void)strcpy(Stack[Top], name);
X	return(OK);
X}
X
X/*
X * Pop a directory name from the stack
X *
X */
Xstatic char *PopDir()
X{
X	register char *r;
X	extern char **ShrinkStack();
X	
X	if(STACK_EMPTY)
X	    return ((char *)NULL);
X	
X	r = Stack[Top];
X	Top--;
X	return(r);
X}
X
Xstatic int BadStatus = FALSE;
X#define BADSTATUS (BadStatus != FALSE)
X#define MAXNAMLEN 128
X
X/*
X * Process directories on the Stack, by adding all the
X * files in a directory to nargv.
X */
Xstatic int ProcessDirs(nargc, nargv)
Xint *nargc;
Xchar ***nargv;
X{
X	register char *name;
X	register struct stat *dp;
X	register int status, slashp;
X	char path[MAXNAMLEN+1];
X	extern char **CopyToNargv();
X	extern char *PopDir();
X	extern char *alltolower();
X	
X	if(BADSTATUS)
X	    return(~OK);
X
X	if(STACK_EMPTY)
X	    /* Nothing more to do */
X	    return(OK);
X
X	/* Pop a directory from Stack and process */
X	if((name = PopDir()) == (char *)NULL)
X	{
X		/* Oh Oh */
X		fprintf(STDERR,"Internal Error (BUG), PopDir returns NULL\n");
X		BadStatus = (~FALSE);
X		return(~OK);
X	}
X	
X	strcpy(path, name);
X	if(path[(strlen(path)-1)] == '\\')
X	{
X		strcat(path,"*.*");
X		slashp = TRUE;
X	}
X	else
X	{
X		strcat(path,"\\*.*");
X		slashp = FALSE;
X	}
X		
X	/* Open the directory */
X	if(Fsfirst(path, 0x0020| 0x0010 | 0x0001) != 0)
X	{
X		/* trouble opening directory */
X		fprintf(STDERR,"Trouble opening %s\n",path);
X		/* set BADSTATUS and return */
X		BadStatus = (~FALSE);
X		return(~OK);
X	}
X
X	/* get the DTA */
X	dp = (struct stat *)Fgetdta();
X	
X	/* for each entry in the directory, if it is a file
X	   add to nargv. If it is a directory, Push it onto
X	   the directory stack.
X	 */
X	do
X	{
X		if(! ((strcmp(dp->st_name,".") == 0) ||
X		      (strcmp(dp->st_name,"..") == 0)) )
X		{
X			strcpy(path, name);
X			if(!slashp)
X				strcat(path,"\\");
X			strcat(path,dp->st_name);
X
X			/* If this path is on the PruneList skip */
X			if(OnPruneList(PruneList, alltolower(path)))
X			    continue;
X
X			if(!isdir(path, dp->st_mode))
X			{
X				/* not a dir -- add this to nargv */
X				if((*nargv = CopyToNargv(path, *nargc, *nargv))
X				    == (char **)NULL)
X				{
X					BadStatus = (~FALSE);
X					return(~OK);
X				}
X				else
X				{
X					*nargc += 1;
X				}
X				
X			}
X			else
X			{
X
X				/* Push This directory */
X				if((status = PushDir(path)) != OK)
X				{
X					BadStatus = (~FALSE);
X					return(status);
X				}
X			}
X		}
X	} while(Fsnext() == 0);
X
X	free(name);	/* done with this directory */
X	
X	/* go do the rest */
X	return (ProcessDirs(nargc, nargv));
X}
X
X/*
X * Add a name to PruneList
X *
X */
Xstatic PRUNELIST *AddPrune(list, name)
XPRUNELIST *list;
Xchar *name;
X{
X	extern char *malloc();
X	register PRUNELIST *new;
X	
X	if((new = (PRUNELIST *)malloc(sizeof(PRUNELIST))) == (PRUNELIST *)NULL)
X	{
X		/* outa mem */
X		fprintf(STDERR,"%s(AddPrune()): Out of Memory\n", ProgName);
X		return(new);
X	}
X
X	new->name = name;
X	new->next = list;
X	
X	return(new);
X}
X
X/*
X * Search for name on PruneList
X *
X */
Xstatic int OnPruneList(list, name)
Xregister PRUNELIST *list;
Xregister char *name;		
X{
X	for(; list != (PRUNELIST *)NULL; list = list->next)
X	{
X		if(strcmp(list->name, name) == 0)
X		    return(~FALSE);
X	}
X	
X	return(FALSE);
X}
X
X/*
X * test if a subdirectory exists, without touching the DTA
X * include special case of 'D:\' that Fsfirst does'nt handle correctly
X */
Xstatic int isdir(name, attr)
Xregister char *name;
Xregister int attr;
X{
X	/* assuming the DTA buffer is already set up */
X	extern long drv_map;
X	register int drive;
X	
X	if(attr & 0x0010)
X		return TRUE;
X
X	/* Gemdos doesn't like d:\ style dirs */
X	if((name[3] == '\0') && (name[2] == '\\') && (name[1] == ':'))
X	{
X		drive = name[0];
X		if(isupper(drive))
X			drive = tolower(drive);
X
X		drive = drive - 'a';
X		if((drv_map & (1L << drive)) == 0)
X			return FALSE;
X		else
X			return TRUE;
X	}
X	/* Nor does Gemdos understand '.' or '..' */
X	/* Hey Atari, don't you guys ever test anything */
X	if((strcmp(name,".") == 0) || (strcmp(name,"..") == 0) ||
X	   (strcmp(name,".\\") == 0) || (strcmp(name,"..\\") == 0))
X		return TRUE;
X
X	return FALSE;
X}
X
X
X#ifdef TEST
X
X/*
X * convert string to all lower case
X */
Xchar *alltolower(s)
Xchar *s;
X{
X	register char *p;
X
X	for(p = s; *p != '\0'; p++)
X		if(isupper(*p))
X			*p = tolower(*p);
X
X	return s;
X}
X	
X/*
X * test if a subdirectory exists
X * include special case of 'D:\' that Fsfirst does'nt handle correctly
X * (this routine not needed for zmdm, as it is defined in common.c)
X */
Xint existd(name)
Xregister char *name;
X{
X	/* assuming the DTA buffer is already set up */
X	/* assumes drv_map has been read in drv_map externally */
X	extern long drv_map;
X	register int drive;
X	extern struct stat statbuf;
X	
X	if (Fsfirst(name , 0x0021|0x0010) == 0)
X	{
X		if((statbuf.st_mode & 0x0010) == 0x0010)
X			return TRUE;
X	}
X
X	/* Gemdos doesn't like d:\ style dirs */
X	if((name[3] == '\0') && (name[2] == '\\') && (name[1] == ':'))
X	{
X		drive = name[0];
X		if(isupper(drive))
X			drive = tolower(drive);
X
X		drive = drive - 'a';
X		if((drv_map & (1L << drive)) == 0)
X			return FALSE;
X		else
X			return TRUE;
X	}
X	/* Nor does Gemdos understand '.' or '..' */
X	/* Hey Atari, don't you guys ever test anything */
X	if((strcmp(name,".") == 0) || (strcmp(name,"..") == 0) ||
X	   (strcmp(name,".\\") == 0) || (strcmp(name,"..\\") == 0))
X		return TRUE;
X
X	return FALSE;
X}
X
Xint MAIN(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register int i;
X	
X	for(i = 0; i < argc; i++)
X	    printf("%d:\t%s\n", i, argv[i]);
X
X
X	return(0);
X}
X
X
Xstruct stat statbuf;	  /* Disk Transfer address for Find first etc */
Xlong drv_map;
X
X#ifdef MWC
Xlong _stksize = 128L * 1024L;
X#endif
X
X#ifdef MANX
Xlong _STKSIZ = 128L * 1024L;
X#endif
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	/* Set up Dta */
X	Fsetdta(&statbuf);
X	drv_map = Drvmap();
X
X	exit(expandargs(MAIN, argc, argv));
X}
X
X#endif /* TEST */
X
X/* -eof- */
SHAR_EOF
chmod 0600 EXPANDAR.C || echo "restore of EXPANDAR.C fails"
echo "x - extracting FILEIO.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > FILEIO.C &&
X/*
X * 	File I/O (with large buffers) Module
X *
X *		Jwahar Bammi
X *			usenet: mandrill!bammi@{decvax,sun}.UUCP
X *			csnet:  bammi@mandrill.ces.CWRU.edu
X *			arpa:   bammi@mandrill.ces.CWRU.edu
X *			CompuServe: 71515,155
X */
X
X#include "config.h"
X
X#include "zmdm.h"
X#include "common.h"
X
X#define	O_RDONLY	1
X#define O_WRONLY	2
X#define O_APONLY	4
X#ifndef DYNABUF
X#define MBUFSIZ		(((long)BBUFSIZ)-1L)
X#else
Xstatic long MBUFSIZ;
X#endif /* DYNABUF */
X
Xstatic unsigned char *bptr;
X
Xstatic long flcount = (-1L);
Xstatic int bufmode;
X
Xint stfopen(name, mode)
Xchar *name, *mode;
X{
X	register int handl;
X
X	switch(*mode)
X	{
X	    case 'r':
X		if((handl = Fopen(name, 0)) <= 0)
X			return -1;
X		bufmode = O_RDONLY;
X		break;
X
X	    case 'w':
X		if((handl = Fcreate(name, 0)) <= 0)
X		{
X			if((handl = Fopen(name, 1)) <= 0)
X				return -1;
X		}
X		bufmode = O_WRONLY;
X		break;
X
X	    case 'a':
X		if((handl = Fopen(name, 2)) <= 0)
X			return -1;
X		Fseek(0L, handl, 2);
X		bufmode = O_APONLY;
X		break;
X
X	   default:
X		return -1;
X	}
X
X#ifdef DYNABUF
X	MBUFSIZ = BBUFSIZ - 1L;
X#endif /* DYNABUF */
X
X	bptr = bufr;
X	flcount = (-1L);
X	return handl;
X}
X
Xstfclose(handl)
Xint handl;
X{
X	if(bufmode == O_RDONLY)
X		return Fclose(handl);
X	if(stflush(handl))
X	{
X		Fclose(handl);
X		return -1;
X	}
X	return Fclose(handl);
X}
X
Xstputc(c, handl)
Xunsigned int c;
Xint handl;
X{
X	if(flcount >= MBUFSIZ)
X	{
X		if(Fwrite(handl, (long)BBUFSIZ, bufr) != (long)BBUFSIZ)
X			return -1;
X		flcount = (-1L);
X		bptr  = bufr;
X	}
X	flcount++;
X	*bptr++ = c;
X	return 0;
X}
X
Xstgetc(handl)
Xint handl;
X{
X	if(flcount <= 0)
X	{
X		if((flcount = Fread(handl, (long)BBUFSIZ, bufr)) == 0)
X			return EOF;
X		bptr = bufr;
X	}
X	flcount--;
X	return(*bptr++);
X}
X
Xstflush(handl)
Xint handl;
X{
X	if(flcount < 0)
X		return 0;
X
X	if(Fwrite(handl, (long)(flcount+1L), bufr) != (flcount+1L))
X		return -1;
X	flcount = (-1L);
X	bptr = bufr;
X	return 0;
X}
X		
Xstfseek(handl, disp, mode)
Xint handl;
Xlong disp;
Xint  mode;
X{
X	if(bufmode != O_RDONLY)
X		if(stflush(handl))
X			return -1;
X	Fseek(disp, handl, mode);
X	flcount = (-1L);
X	bptr = bufr;
X	return 0;
X}
X
X
X/* -eof- */
SHAR_EOF
chmod 0600 FILEIO.C || echo "restore of FILEIO.C fails"
echo "x - extracting HI5025.S (Text)"
sed 's/^X//' << 'SHAR_EOF' > HI5025.S &&
X/
X/  Make hi rez screen bios handle 50 lines of 8x8 characters
X/
X/  Adapted to Mark Williams C use from origional PD asm posting
X/  from atari corp.
X/
X/ 		Jwahar Bammi
X/ 			usenet: cwruecmp!bammi@decvax.UUCP
X/			csnet:  bammi@cwru.edu
X/			arpa:   bammi@cwru.edu
X/ 			CompuServe: 71515,155
X/ 
X/
X		.shri
X
X	.globl hi50_
X
Xhi50_:				  / switch to 50 line mode
X	link	a6,$0		  / routine preamble
X
X	.word	0xA000		  / get the important pointers (line A init)
X
X	movea.l    4(a1),a1	  / a1 -> 8x8 font header
X
X	move.l  72(a1),-0x0A(a0)  / v_off_ad <- 8x8 offset table addr
X	move.l  76(a1),-0x16(a0)  / v_fnt_ad <- 8x8 font data addr
X
X	move    $8,  -0x2E(a0)	  / v_cel_ht <- 8    8x8 cell height
X	move    $49, -0x2A(a0)	  / v_cel_my <- 49   maximum cell "Y"
X	move    $640,-0x28(a0)    / v_cel_wr <- 640  offset to cell Y+1
X
X	unlk	a6		  / routine postable
X	rts			  / and return
X
X   
X/
X/ Make hi rez screen bios handle 25 lines of 8x16 characters
X/
X
X	.globl hi25_
X
Xhi25_:				  / Switch to 25 lines display
X	link	a6,$0		  / routine preamble
X
X	.word   0xA000		  / get the important pointers
X	
X	movea.l    8(a1),a1	  / a1 -> 8x16 font header
X
X	move.l  72(a1),-0x0A(a0)  / v_off_ad <- 8x16 offset table addr
X	move.l  76(a1),-0x16(a0)  / v_fnt_ad <- 8x16 font data addr
X
X	move    $16,  -0x2E(a0)	  / v_cel_ht <- 16    8x16 cell height
X	move    $24,  -0x2A(a0)	  / v_cel_my <- 24    maximum cell "Y"
X	move    $1280,-0x28(a0)	  /  v_cel_wr <- 1280  vertical byte offset
X
X	unlk	a6		  / routine postamble
X	rts			  / bye
SHAR_EOF
chmod 0600 HI5025.S || echo "restore of HI5025.S fails"
echo "x - extracting LNK (Text)"
sed 's/^X//' << 'SHAR_EOF' > LNK &&
Xc:\lib\gemstart.o common.o rz.o sz.o transfer.o util.o main.o tyme.o
Xzm.o fileio.o phone.o c:\lib\osbind.o c:\lib\gemlib c:\lib\libf
SHAR_EOF
chmod 0600 LNK || echo "restore of LNK fails"
echo "x - extracting MAIN.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > MAIN.C &&
X/*
X * 	Main Module
X *
X *		Jwahar Bammi
X *			usenet: mandrill!bammi@{decvax,sun}.UUCP
X *			csnet:  bammi@mandrill.ces.CWRU.edu
X *			arpa:   bammi@mandrill.ces.CWRU.edu
X *			CompuServe: 71515,155
X */
X
X#include "config.h"
X
X#include "zmdm.h"
X#include "common.h"
X
X#ifndef Vsync 			/* Atari forgot these in osbind.h */
X#define Vsync()	xbios(37)
X#endif
X
X#define	esc	27
X#define cr	0x0d
X#define mvto(r,c)	EscSeq('Y');Bconout(2,r+040);Bconout(2,c+040)
X
X
X 	/* Globals belonging to this module only */
X
Xint	rs232 = 1,		/* Ports */
X        console = 2;
Xint	speed,			  /* rs232 setup parameters */
X#ifdef FLOW_CTRL
X 	flowctl = 1,
X#else
X	flowctl = 0,
X#endif
X	ucr = -1,
X	rsr = -1,
X	tsr = -1,
X	scr = -1;
X
X/*
X * setRs232() - set rs232 port configuration
X */
X#ifndef REMOTE
Xvoid setRs232 ()
X{
X	char ch;
X	long conin;
X	
X	Bconws("Baud rate: ");
X	EscSeq('p');
X	Bconws("0=19200 1=9600, 2=4800, 3=2400, 4=1200, 5=300\r\n");
X	EscSeq('q');
X	Bconout(2, '\t');
X	EscSeq('p');
X	Bconws("What speed==>");
X	EscSeq('q');
X	
X	conin = Bconin(console);	/* get speed */
X	if ((conin & 0x00FF0000L) == 0x00610000L)
X	{
X		his_screen();
X		ResetIoBuf();
X		finish();
X	}
X	ch = (char) (conin & 0x007f);
X	Bconout(2, ' ');
X	switch (ch)
X	{
X	    case '0':		/* 19200 */
X		speed = 0;
X		Bconws("19200");
X		Baudrate = 19200;
X		break;
X		
X	    case '1':
X		speed = 1;	/* 9600 */
X		Bconws("9600");
X		Baudrate = 9600;
X		break;
X		
X	    case '2':
X		speed = 2;	/* 4800 */
X		Bconws("4800");
X		Baudrate = 4800;
X		break;
X		
X	    case '3':
X		speed = 4;	/* 2400 */
X		Bconws("2400");
X		Baudrate = 2400;
X		break;
X		
X	    case '4':
X		speed = 7;	/* 1200 */
X		Bconws("1200");
X		Baudrate = 1200;
X		break;
X		
X	    case '5':
X		speed = 9;	/* 300 */
X		Bconws("300");
X		Baudrate = 300;
X		break;
X		
X	    default:
X		speed = getbaud();
X		Bconws(BAUD_STRING(speed));
X		Baudrate = BAUD_RATE(speed);
X	}
X	Bconws(" Baud\r\n");
X	
X	/* Set new Baud rate */
X
X/*	Txoff(); */
X	Rsconf(speed, flowctl, ucr, rsr, tsr, scr);
X	Vsync(); Vsync();
X/*	Txon(); */
X
X	
X}
X#else
Xvoid setRs232 ()
X{
X	char ch;
X	long conin;
X	
X	Bauxws("Baud rate: ");
X	Bauxws("0=19200 1=9600, 2=4800, 3=2400, 4=1200, 5=300\r\n");
X	Bconout(1, '\t');
X	Bauxws("What speed==>");
X	
X	conin = Bconin(1);	/* get speed */
X	if (((int)(conin & 0x007f) & CTRL('U')) == CTRL('U'))
X	{
X		his_screen();
X		ResetIoBuf();
X		finish();
X	}
X	ch = (char) (conin & 0x007f);
X	Bconout(1, ' ');
X	switch (ch)
X	{
X	    case '0':		/* 19200 */
X		speed = 0;
X		Bauxws("19200");
X		Baudrate = 19200;
X		break;
X		
X	    case '1':
X		speed = 1;	/* 9600 */
X		Bauxws("9600");
X		Baudrate = 9600;
X		break;
X		
X	    case '2':
X		speed = 2;	/* 4800 */
X		Bauxws("4800");
X		Baudrate = 4800;
X		break;
X		
X	    case '3':
X		speed = 4;	/* 2400 */
X		Bauxws("2400");
X		Baudrate = 2400;
X		break;
X		
X	    case '4':
X		speed = 7;	/* 1200 */
X		Bauxws("1200");
X		Baudrate = 1200;
X		break;
X		
X	    case '5':
X		speed = 9;	/* 300 */
X		Bauxws("300");
X		Baudrate = 300;
X		break;
X		
X	    default:
X		speed = getbaud();
X		Bauxws(BAUD_STRING(speed));
X		Baudrate = BAUD_RATE(speed);
X	}
X	Bauxws(" Baud\r\n");
X	
X	/* Set new Baud rate */
X
X/*	Txoff(); */
X	Rsconf(speed, flowctl, ucr, rsr, tsr, scr);
X	Vsync(); Vsync();
X/*	Txon(); */
X
X	
X}
X#endif /* REMOTE */
X
X/*
X * help() - display help info and menu
X */
X#ifndef REMOTE
Xvoid help ()
X{
X	register long conin;
X	register int x;
X	extern char *r_filename();
X	
X	my_screen();		/* Switch to my screen memory */
X	EscSeq('v');		/* wrap at end of line */
X	EscSeq('E');		/* clear screen */
X	
X	mvto(2,25);
X	EscSeq('p');
X	Bconws("ZMDM Version ");
X	Bconws(ZMDMVERSION);
X	EscSeq('q');
X	EscSeq('p');
X	x = strlen(COMPILER);
X	x = (80 - x)/2;
X	mvto(3,x);
X	Bconws(COMPILER);
X	EscSeq('q');
X	mvto(5,25);
X	Bconws("ST Enthusiasts @ ces.CWRU.edu\r\n\n");
X
X	/* Put up menu */
X	Bconws("\r\n\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("Undo");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" to exit.\r\n");
X	
X	Bconws("\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("Help");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" for this message.\r\n");
X
X	Bconws("\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("Escape");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" to send a break.\r\n");
X	
X	Bconws("\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("T or t");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" to do file transfers and local functions.\r\n");
X
X#ifdef PHONES
X	Bconws("\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("P or p");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" for Phone services.\r\n");
X#endif
X
X	if(rez == 2)
X	{
X		Bconws("\t");
X		EscSeq('p');		/* reverse video */
X		Bconws("H or h");
X		EscSeq('q');		/* quit reverse video */
X		Bconws(" for Hi Rez Toggle (25/50 Lines).\r\n");
X	}
X
X	Bconws("\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("I or i");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" to Invert screen colors.\r\n");
X	
X	Bconws("\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("Return");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" to do nothing.\r\n");
X	
X	Bconws("\t");
X	EscSeq('p');		/* reverse video */
X	Bconws("B or b");
X	EscSeq('q');		/* quit reverse video */
X	Bconws(" to set baud rate.     Currently is ");
X	EscSeq('p');
X	Bconws(BAUD_STRING(speed));
X	Bconws(" Baud.\r\n\r\n");
X	EscSeq('q');
X
X	/* get response */
X	conin = Bconin(console);
X
X	if ((conin & 0x00FF0000L) == 0x00610000L)
X	{
X		/* He hit <UNDO> */
X		his_screen();
X		ResetIoBuf();
X		finish();
X	}
X	
X	switch((int)(conin & 0x007f))
X	{
X	    case 'B':
X	    case 'b':
X		/* Set baud rate */
X		setRs232();
X		break;
X		
X	    case 'T':
X	    case 't':
X	        EscSeq('E');		/* clear screen */
X
X		    /* Set no flow Control */
X#ifdef FLOW_CTRL
X		    Rsconf(-1,0,-1,-1,-1,-1);
X		    Vsync(); Vsync();
X
X#endif
X		/* Go do transfers */
X		transfer();
X		    
X#ifdef FLOW_CTRL
X		    /* Flow Control On */
X/*		    Txoff(); */
X		    Rsconf(-1,1,-1,-1,-1,-1);
X		    Vsync(); Vsync();
X/*		    Txon(); */
X#endif
X		his_screen();
X		return;
X		
X	    case '\033':
X		/* Send a break */
X		sendbrk();
X		his_screen();	/* Don't wait for the key hit */
X
X		return;
X
X	    case 'i':
X	    case 'I':
X		/* Invert screen colors */
X		his_screen();
X		if(scolor == 0)
X		{
X			EscSeq('b');	/* Foreground color 0 */
X			Bconout(2, 0);
X			EscSeq('c');	/* Background color 1 */
X			Bconout(2, 1);
X			scolor = 1;
X		}
X		else
X		{
X			EscSeq('b');	/* Foreground color 1 */
X			Bconout(2, 1);
X			EscSeq('c');	/* Background color 0 */
X			Bconout(2, 0);
X			scolor = 0;
X		}
X		EscSeq('E');		/* Clear the screen */
X		return;
X
X#ifdef PHONES
X	    case 'p':
X	    case 'P':
X		/* Phone Services */
X		phone();
X		return;
X#endif
X	    case 'h':
X	    case 'H':
X		/* Hi rez 25/50 toggle */
X		if(rez == 2)
X		{
X			if(hlines == 25)
X			{
X				hlines = 50;
X				hi50();
X			}
X			else
X			{
X				hlines = 25;
X				hi25();
X			}
X			his_screen();
X			EscSeq('E');		/* clear screen */
X			return;
X		}
X		/* else fall Through */
X		
X	    default:
X		Bconws("No Change\r\n");
X	}
X
X	/* Wait for a key hit */
X	hit_key();
X	/* back to terminal screen */
X	his_screen();
X}
X#else
Xvoid help ()
X{
X	register long conin;
X	extern char *r_filename();
X	
X	my_screen();		/* Switch to my screen memory */
X	
X	Bauxws("\r\n\n");
X	Bauxws("                        RZMDM Version ");
X	Bauxws(ZMDMVERSION);
X	Bauxws("\r\n                         ");
X	Bauxws(COMPILER);
X	Bauxws("\r\n\n                        ST Enthusiasts @ ces.CWRU.edu\r\n\n");
X
X	/* Put up menu */
X	Bauxws("\r\n\t");
X	Bauxws("CTRL-U");
X	Bauxws(" to exit.\r\n");
X	
X	Bauxws("\t");
X	Bauxws("CTRL-Z");
X	Bauxws(" for this message.\r\n");
X
X	Bauxws("\t");
X	Bauxws("Escape");
X	Bauxws(" to send a break.\r\n");
X	
X	Bauxws("\t");
X	Bauxws("T or t");
X	Bauxws(" to do file transfers and local functions.\r\n");
X
X	Bauxws("\t");
X	Bauxws("Return");
X	Bauxws(" to do nothing.\r\n");
X	
X	Bauxws("\t");
X	Bauxws("B or b");
X	Bauxws(" to set baud rate.     Curently is ");
X	Bauxws(BAUD_STRING(speed));
X	Bauxws(" Baud.\r\n\r\n");
X
X	/* get response */
X	conin = Bconin(1);
X
X	if (((int)(conin & 0x007f) & CTRL('U')) == CTRL('U'))
X	{
X		/* He hit <UNDO> */
X		his_screen();
X		ResetIoBuf();
X		finish();
X	}
X	
X	switch((int)(conin & 0x007f))
SHAR_EOF
echo "End of part 2"
echo "File MAIN.C is continued in part 3"
echo "3" > s2_seq_.tmp
exit 0