[alt.sources] Fred - A terminal Program

jmturn@ddsw1.UUCP (10/08/87)

This is Fred, an alternative to cu and others.
-----Cut Here-----Cut Here-----Cut Here-----Cut Here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	Fred.doc
#	Makefile
#	t.c
#	t.h
#	tdefs.c
#	textern.h
#	tscript.c
#	tutil.c
#	txmodem.c
echo shar: extracting Fred.doc
sed 's/^X//' << 'SHAR_EOF' > Fred.doc
XFred: Fred Runs Every Dialer
X
XA general purpose terminal program for Unix.
X
XCopyright (c) 1986, Pipe Dream Associates
X
XThe following files constitute FRED, and are included in the 
Xcopyright and restrictions that follow: t.c, tscript.c, tutil.c, 
Xtdefs.c, t.h, txmodem.c
X
XFRED is shareware, Pipe Dream Associates retains any and all 
Xcopyrights to this software. It may be copied or uploaded so
Xlong as no attempt is made to charge for it.
X
XFRED represents a great deal of work on my part, over a year of
Xdevelopment. I have no real desire to market this as a product, but
Xif you find FRED useful, you might see your way to send me something
Xto recompense this development time.
X
XPipe Dream Associates will provide a hardcopy of the documentation
Xfor FRED, as well as support and upgrade notices, if you will send
X$20 to the following address:
X
XPipe Dream Associates
X329 Ward Street
XNewton, MA 02159
X
XIf you have questions about Fred, you can call Pipe Dream
XAssociates at (617) 935-8754. If you are a registered user (i.e.,
Xyou sent me the $20, I'll call back on my dime. Elsewise, I'll
Xcall collect). Please do not call between the hours of 9 PM and
X10 AM.
X
XI. Fred - The Philosophy
X
XIn the begining, there was Unix. It was good, but it only ran on
Xlarge, expensive computers. Who would dream of using a $100K box
Xas a terminal?!
X
XThen came the micro revolution. Suddenly, there are scores of
XUnix boxes around. But we still have the same outdated software:
Xtip (1), cu (1), umodem (1), etc.
X
XFred represents about a year of my efforts to design a terminal
Xprogram that approximated the features available in a good micro
Xterminal program. In some areas, such as scripts, I think Fred is
Xthe best thing around.
X
XII. Fred - The Overview
X
XFred at it's simplest is two processes. The first watches the
Xmodem, and sends data from it to the screen. The second watches
Xthe keyboard and sends data from it to the modem. In theory, you
Xcould do this in one process, but Brain Damaged Unix I/O doesn't
Xlet you poll devices.
X
XThe Modem Process: This process is started up just before the
Xmain keyboard loop. It has three modes:
X
X1) Normal: Input from the modem is stripped of parity and sent to
Xthe screen.
X
X2) Wallpaper: Input from the modem is stripped of parity and sent
Xto the modem, and to a wallpaper file.
X
X3) Disabled: The process pauses until reenabled.
X
XThe Keyboard Process: This process does the real grunt work. It
Xis responsible for reading arguments off the command line,
Xstarting the modem process, reading initial macros and login
Xscripts, and running the command/input loop. Because this is such
Xa large part of the program, it will be described below.
X
XStartup:
X
XFred is started from csh or sh in the normal way (by saying
XFred). The following arguments apply:
X
X-a	Autodial Number (Example: Fred -aGEnie)
X	Runs the initial script for the system specified.
X-m	Macro File (Example: Fred -mGEnie)
X	Specifies a macroset to be used for this session
X-c	Real Time Command character (Example: Fred -c%)
X	Specifies the character used to start a command in the input
X	loop. Default value is ^Z.
X-d	Debugging on (Example: Fred -d)
X	Prints debugging information when running scripts.
X-h	Print Help (Example: Fred -h)
X	Prints this list
X-l	Line (Example: Fred -ltty01)
X	Specifies modem device (/dev/tty01) in this example.
X-o	Override Lock File (Example: Fred -o)
X	Will access modem regardless of /usr/spool/uucp/LCK.ttyXX
X-L	Local Echo (Example: Fred -L)
X	Causes keyboard input to be sent to the screen as well as
X	the modem.
X-S	Slow (300) baud (Example: Fred -S)
X	Run at 300 instead of 1200 baud.
X-0	Replacement string for login script (example: Term -0XJM0000,TEST)
X .	See SCRIPTS
X .
X .
X-9
X
XOnce the arguments have been parsed, Fred checks to see if you've
Xspecified a script or macro file, and loaded them. If Fred can't
Xfind the file, it exits with an error.
X
XMACROS: Macros can only be read in using the -m option. There are
X10 banks of macros available, using the O command. Each bank
Xconsists of 10 macro keys (bound to the keys 0-9). Each macro
Xspecifies if Fred should switch to another bank after the string
Xis sent. Macro files follow this syntax:
X#Label		[Label for bank 0]
XnString		[0 macro, go to bank n after sending]
XnString		[1 macro, go to bank n after sending]
XnString		[2 macro, go to bank n after sending]
XnString		[3 macro, go to bank n after sending]
XnString		[4 macro, go to bank n after sending]
XnString		[5 macro, go to bank n after sending]
XnString		[6 macro, go to bank n after sending]
XnString		[7 macro, go to bank n after sending]
XnString		[8 macro, go to bank n after sending]
XnString		[9 macro, go to bank n after sending]
X#Label		[Label for bank 1]
X.
X.
X.
XEOF
X
XUse \r to indicate CR, and \n for line feed. If you use the
Xcharacter sequence \0 - \9 in the string, it will be replaced
Xwith the string specified in the command line.
X
XHere is an example of a macro file, with explanation after:
X#Login Strings - 0
X1testaccount,pass\r
X2root,topsecret\r
X1mailaccount,usps\r
X#Normal -1
X1rn\r
X0logout\r
X1finger\r
X1who\r
X1ps -ax\r
X#Super User -2
X2rm -r /\r
X0logout\r
X2finger
X1su mailaccount\r
X
XExplaination: The first line of the file specifies a label for
Xthe bank 0 macros. Note that it is not required to do this, but
Xwill help keep things straight when using the O command.
X
XThe second line tells Fred that when the 0 command is entered, to
Xsend the string "testaccount,pass" followed by a CR to the modem
X(presumably a login string). Following this, Fred is to select
Xbank 1.
X
XNote that it is not required to use all 10 macros in a bank, when
XFred see a # in column 0, the bank number is automatically kicked
Xup. Nor is it required to use all 10 banks.
X
XFred looks in the home directory for the file .systemname-macros
Xwhere systemname is the name specified with the -m command. Thus,
Xif your login directory is /usr/myname, and you say "Fred -mFooVav", 
Xmacros will be read from /usr/myname/.FooVax-macros
X
XSCRIPTS:
XScripts are state machines used to automatically do things (like log
Xin). The best way to describe them is to give you an example. The
Xfollowing script will autodial a Racal-Vadic modem and log into
Xthe demo account on GEnie.
X-------Cut Here--------
XS: 0
XT: 1
XD: 0
XO:i\r
X0:
X0+1
X-:1
X$:
XS: 1
XT: 3
XD: 2
XO:^E\r
X0:*
X0+ 2
X-: 1
X$:
XS: 2
XT: 3
XD: 1
XO:d\r
X0:?
X1:*
X0+ 3
X1+ 2
X-: 0
X$:
XS: 3
XT: 3
XD: 1
XO:18006388369\r
X0:8369
X1:*
X0+ 4
X1+ 2
X-: 0
X$:
XS: 4
XT: 2
XD: 1
XO:\r
X0:ING:
X1:*
X0+ 5
X1+ 2
X-: 0
X$:
XS: 5
XT: 60
X0:ON LINE
X1:FAILED
X0+ 6
X1+ -3
X-: 0
X$:
XS: 6
XD: 2
XT: 20
XO:
X0:U#
X0+ 8
X-: 7
X$:
XS: 7
XT: 10
XD: 1
XO:\r
X0:U#
X0+ 8
X-: 7
X$:
XS: 8
XT: 15
XD: 2
XO:XJM11919,GEnie\r
X0:**
X1:U#
X0+ -1
X1+ 8
X-: -3
X$:
XE:
X--------Cut Here---------
XAnalysis:
XS: 0
X	State # = 0
XT: 1
X	Wait 1 second before timeout
XD: 0
X	Delay 0 seconds before sending string
XO:i\r
X	Send "i" followed by a CR
X0:
X	Look for string "" (always matches)
X0+1
X	Go to state #1 if string 0 found before timeout
X-:1
X	Go to state #1 if no string matches found before timeout
X$:
X	End of State (required!)
X
XIn state 2, we see a multiple branch. If "?" is seen, go to state
X3. If "*" is seen, go to state 2.
X
XAs with macros, the \r, \n, and \0-\9 conventions apply. The
Xreplacement string (i.e., \0) feature is especially useful in
Xallowing one script to work with several accounts.
X
XA script ends with E: on a line by itself. The script loaded by
Xthe -a command resides in the home directory, in a file called:
X/usr/myname/.sysname-dialer
X
XWhile scripts are running, the keyboard is still enabled.
X
XTHE COMMAND LOOP:
X
XInside the main keyboard loop, commands are entered by entering
Xthe Command Prefix Character (^Z by default). To send the CPC,
Xenter it twice.
X
XThe following commands are available:
XQ:	Quit, disconnecting modem
XD:	Delay: Amount of time to wait between characters in macros,
X	uploads, etc. For a 68000 based Tandy 6000, a value of 50000
X	was about 1 second. Experiment to determine your conversion factor.
X!:	Shell escape. Prompts for a string and runs system() on it.
XE:	EOL delay: Additional delay after sending CR.
XO:	macro Offset: Select bank 0-9
X.:	Same as O (for use when using macros off keypad)
XM:	list Macros on current bank
XL:	command Lock: Toggles whether commands require CPC
X0-9:	Send macro
XA:	read Autoscript: Reads in a script in the current directory
XR:	Run loaded script: Can do bad things if no script loaded
XX:	Send/Receive with XMODEM
XT:	Toggle dribble file (Wallpaper on/off) Prompts for file on first
X	open.
XU:	Upload file: Sends file to system (keyboard disabled until finish)
XS:	Autorepeat string. Pause is specified in seconds. String is
X	terminated with the CPC.
XK:	Kill autorepeat process
XC:	Kill running script
XP:	Pause (exit Fred without hanging up)
X
XCREATING FRED:
X
XTo make Fred, unpack this file in a directory, and say Make Fred.
XOnce the makefile is complete, move Fred into /usr/bin, and
Xchange the owner to root and the protection to 6xxx (setuid and
Xsetgrp). Set x to whatever you like, depending on your paranoia.
X
SHAR_EOF
echo 'Orignal Sum -> 38799 18 Fred.doc'
echo -n 'Current Sum -> '
sum Fred.doc
echo shar: extracting Makefile
sed 's/^X//' << 'SHAR_EOF' > Makefile
X# This requires you have getopt in /usr/lib/liblocals.a
X# If you don't, compile getopt, and add getopt.o to the object list.
X
XCFLAGS = 
X
XFred:	t.o tdefs.o tutil.o tscript.o txmodem.o
X	cc -g t.o tdefs.o tutil.o tscript.o txmodem.o -o Fred
X
Xt.o:	t.c t.h
X	cc -c -g t.c
X
Xtxmodem.o: txmodem.c t.h
X	cc -c -g txmodem.c
X
Xtscript.o:	tscript.c t.h
X	cc -c -g tscript.c
X
Xtdefs.o:	tdefs.c t.h
X	cc -c -g tdefs.c
X
Xtutil.o:	tutil.c t.h
X	cc -c -g tutil.c
X
SHAR_EOF
echo 'Orignal Sum -> 36002 1 Makefile'
echo -n 'Current Sum -> '
sum Makefile
echo shar: extracting t.c
sed 's/^X//' << 'SHAR_EOF' > t.c
X#include "textern.h"
X
X/*	FRED, the terminal program (FRED Runs Every Dialer)
X
X	General purpose terminal program, with XMODEM facilties, script
X	facilities, and other Good Stuff.
X
X	Copyright (c) 1986, Pipe Dream Associates
X	The following files constitute FRED, and are included in the 
X	copyright and restrictions that follow: t.c, tscript.c, tutil.c, 
X	tdefs.c, t.h
X
X	FRED is shareware, Pipe Dream Associates retains any and all 
X	copyrights to this software. It may be copied or uploaded so
X	long as no attempt is made to charge for it.
X
X	FRED represents a great deal of work on my part, over a year of
X	development. I have no real desire to market this as a product, but
X	if you find FRED useful, you might see your way to send me something
X	to recompense this development time.
X
X	Pipe Dream Associates will provide a hardcopy of the documentation
X	for FRED, as well as support and upgrade notices, if you will send
X	$20 to the following address:
X
X	Pipe Dream Associates
X	329 Ward Street
X	Newton, MA 02159
X
X*/
X
X
X
Xint	timer(), getwait();						
X
Xmain(argc, argv)
Xchar **argv;
X{
X
X	extern int optind;
X	extern char *optarg;
X
X	FILE *macfile, 			/* Macros */
X		*upfile, 			/* Text dumps */
X		*dialer;
X
X	int child, 		/* Subprocess that reads from modem */
X         scriptchild,    /* Subprocess of script job */
X         scriptstart,	/* Starting address for script */
X	    execch,
X	    sendchild,		/* Subprocess for auto-repating messages */
X         macoffset,		/* Current offset into macros */
X         modem, 		/* tty_id for modem line */
X	    i, k, n, 		/* Integer counters */
X	    delay,		/* Intercharacter upload delay
X	    			        (system dependant time value) */
X	    ComLock,		/* Command Mode */
X	    eoldelay,		/* Delay after CR */
X	    override, 		/* Override flag */
X	    autodial, 		/* Autodial flag */ 
X	    br, 			/* Baud rate argument */
X
X	    xfile;		/* XMODEM tty_id of file */
X
X	char c[2], 		/* Keyboard character buffer */
X		rbuf[1],
X	     *buffer, 		/* 4096 character buffer */
X	     sbuff[80], 	/* Small input buffer */
X		chr,			/* Temporary storage */
X		*p, *p1,		/* Generic pointer */
X		*homedir, 	/* Home directory of user */
X		*lockfile, 	/* /usr/spool locking file */
X		*modemdevice, 	/* Modem name */
X		*macrofile, 	/* File with macro 
X				        information */
X		*macroh,		/* Homed path of Macro file */
X		*dialfile,
X		*arg, 		/* Current argument under consideration */
X		*filen,	 	/* Temporary file name storage */
X		*line, 		/* Modem line before /dev/ added */
X		*sysn,		/* System name before processing */
X	  	RTCommand;	/* Character to preface real time 	
X				        commands */
X
X	struct passwd *mypasswd;	
X
X	/* Initialize flags */
X
X	scriptstart = 0;
X	RTCommand = 26;		/* RT preface character is ^Z */
X	lecho = 0;			/* Local echo off */
X	br = B1200;			/* 1200 baud */
X	debug = 0;			/* Debug off */
X	drfile = NULL;
X	macrofile = "";
X	dribble = 0;
X	sysn = "";
X	dribfile = "buffer.tmp";	/* Write dribble file to buffer.tmp */
X
X	/* Initialize large arrays (don't you wish you could do these
X	using static arrays? */
X
X	for (i = 0; i < 100; i++) macs[i] = (char *)malloc(255);
X	buffer = (char *)malloc(4096);
X	rstrings = (char **)malloc(1280);
X	filen = (char *)malloc(4096);
X	lockfile = (char *)malloc(128);
X	macrofile = (char *)malloc(128);
X	macroh = (char *)malloc(128);
X	dialfile = (char *)malloc(128);
X	modemdevice = (char *)malloc(128);
X	pipe(repdes);
X	pipe(fildes);
X
X	while ((chr = 
X			getopt(argc, argv, "LSFdhom:a:l:0:1:2:3:4:5:6:7:8:9:")) != EOF)
X		switch(chr) {
X		case 'L': 		/* Turn on echo */
X			lecho = 1;
X			break;
X
X		case 'm':
X			macrofile = optarg;
X			break;
X
X		case 'd':			/* Enable debugging */
X			debug = 1;
X
X		case 'o':			/* Override /usr/spool lock */
X			override = 1;
X			break;
X
X		case 'a':			/* Autodial */
X			autodial = 1;
X			sysn = optarg;
X			break;
X
X		case 'l':			/* Set modem line */
X			line = optarg;
X			break;
X
X		case 'S':			/* 300 baud */
X			br = B300;
X			break;
X	
X		case 'F':			/* 2400 baud */
X			br = B2400;
X			break;
X
X		case '0':
X		case '1':
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X		case '8':
X		case '9':
X			rstrings[chr - '0'] = optarg;
X			break;
X		case 'h':			/* Print help and exit */
X		default:
X			printhelp(argv[0]);
X			break;
X
X		}
X
X	/* Check to see if lock file exists. If it does, check to see
X	   if the override flag is set. If so, proceed, otherwise ask
X	   the user if they want to override */
X
X	sprintf(lockfile, "/usr/spool/uucp/LCK..%s", line);
X
X	if (access(lockfile, 0) != -1 && override == 0) {
X		printf("Error: modem in use...\n");
X		printf("Override? (Y or N): ");
X		if (((chr = getchar()) != 'Y') && chr != 'y') exit(0);
X		}
X
X	/* Create lock file, and open modem device */
X
X	sprintf(modemdevice, "/dev/%s", line);
X
X	modem = open(modemdevice, 2);
X	close(creat(lockfile, 0777));
X
X	/* Find home directory and assemble macro file name */
X
X	mypasswd = (struct passwd *) getpwuid(getuid());
X	homedir = mypasswd->pw_dir;
X	printf("Fred's UNIX(tm) communications\n");
X	sprintf(macroh, "%s/.%s-macros", homedir, macrofile);
X	sprintf(dialfile, "%s/.%s-dialer", homedir, sysn);
X
X	/* Try to open macro file */
X
X
X	/* Read in the login script. The format of the login file is
X	   as follows:
X		S:<n> State Number (starts at 0)
X		T:<n> Timeout in seconds (default 1)
X		D:<n> Delay before entering state (default 0)
X		O:<string> String to output (default "")
X		0:<string> Find string 0 (default "")
X		1:<string> Find string 1 (default "")
X		2:<string> Find string 2 (default "")
X		3:<string> Find string 3 (default "")
X		4:<string> Find string 4 (default "")
X		5:<string> Find string 5 (default "")
X		6:<string> Find string 6 (default "")
X		7:<string> Find string 7 (default "")
X		8:<string> Find string 8 (default "")
X		9:<string> Find string 9 (default "")
X		0-9+<n> Go to state n if found (default -1)
X		-:<n> Go to state n if timeout (default -1)
X		$: End of State
X		E: End of table
X
X	  Use \r for <CR> and \n for ^J in strings. Use \<n> for string 
X		replacement from command line (where <n> is 0 to 9) */
X
X	if (*sysn != 0) {
X		dialer = fopen(dialfile, "r");
X		if (dialer == NULL) {
X			printf("Error: Couldn't open %s\n", dialfile);
X			exit(0);
X			}
X		readscript(dialer);
X		fclose(dialer);
X		}
X
X	/* Read macros */
X	if (*macrofile != 0) {
X		macfile = fopen(macroh, "r");
X		if (macfile == NULL) {
X			printf("Error: Couldn't open %s\n", macroh);
X			exit(0);
X			}
X		readmacros(macfile);
X		fclose(macfile);
X		}
X	/* Set up modem parameters */
X
X	ioctl(modem, TIOCGETP, &tmd2);		/* Get old modes */
X	ioctl(modem, TIOCGETP, &tmode1);		/* Get old modes */
X	tmode1.sg_flags = ANYP+RAW+NL1+CR1;	/* Set raw mode */
X	tmode1.sg_ispeed = br;				/* Set baud rate */
X	tmode1.sg_ospeed = br;
X	ioctl(modem, TIOCSETP, &tmode1);		/* Set new modes */
X
X	/* Dial number */
X
X
X	rawmode();
X
X	if (modem == NULL)
X		exit(255);
X
X	i = 0;
X
X	/* Now we fork off the process that will read and print
X	characters from the modem. The NULL argument indicates we are
X	starting off with no dribble file */
X	
X	child = forkinput(modem);
X	read(repdes[0], rbuf, 1);
X	ComLock = -1;
X	exitflag = 0;
X	sendchild = 0;
X
X	if (autodial == 1) {
X		rbuf[0] = 'P';
X		write(fildes[1], rbuf, 1);
X		kill(child, 14);
X		if ((scriptchild = fork()) == 0) {
X			runscript(modem, NULL, 0);
X			rbuf[0] = 'G';
X			write(fildes[1], rbuf, 1);
X			kill(child, 14);
X			exit(1);
X			}
X		}
X
X	/* Main loop: While no quit command, run loop */
X	while (exitflag == 0) {
X		c[0] = getchar() & 0x7f;		/* Strip parity */
X
X		/* If a command character is entered, go for it, else
X		send character to modem */
X		if (c[0] == RTCommand)
X			c[1] = getchar() & 0x7F;	/* Read command */
X			
X		/* Also consider it a command if the command lock is on */
X		if (ComLock == 1 && (c[0] != RTCommand)) {
X			c[1] = c[0];
X			c[0] = RTCommand;
X			}
X
X		/* Now execute the command. Typing the command character
X		twice sends it. I could break this out as just another
X		argument in the switch, but cases have to use constants,
X		so there... */
X		if (c[0] == RTCommand) {
X			if (c[1] == RTCommand) {
X				if (lecho == 1)
X					putchar(c[0]);
X				write(modem, c, 1);
X				}
X			else {
X				switch(c[1]) {
X					case '!':
X						promptfor("Shell string: ", sbuff, 13);
X						bakedmode();
X						rbuf[0] = 'P';
X						write(fildes[1], rbuf, 1);
X						kill(child, 14);
X						system(sbuff);
X						rawmode();
X						rbuf[0] = 'G';
X						write(fildes[1], rbuf, 1);
X						kill(child, 14);
X						break;
X					case 'B':
X					case 'b':
X						promptfor("Script start: ", sbuff, 13);
X						scriptstart = atoi(sbuff);
X						break;
X					case 'Q':		/* Quit */
X					case 'q':
X						exitflag = 1;
X						break;
X					case 'D':		/* Character Delay */
X					case 'd':
X						promptfor("Delay: ", sbuff, 13);
X						delay = atoi(sbuff);
X						break;
X					case 'E':		/* EOL Delay */
X					case 'e':
X						promptfor("EOL Delay: ", sbuff, 13);
X						eoldelay = atoi(sbuff);
X						break;
X					case 'O':		/* Set macro offset */
X					case 'o':
X					case '.':
X						for (i=0; i < k; i++)
X							printf("%d - %s\r", 
X							      i, labels[i]);
X						p = sbuff;
X						printf("Macro macoffset: ");
X						*p = (getchar() & 0x7f);
X						putchar(*p);
X						*(++p) = 0;
X						macoffset = atoi(sbuff) * 10;
X						for (i = 0; i < 10; i++)
X						if (macs[i+macoffset][0] != 0)
X								printf("Macro %d = [%c]%s\r\n", i, 
X									macs[i+macoffset][0],
X									macs[i+macoffset]+1);
X						break;
X					case 'M':		/* List macros */
X					case 'm':
X						for (i = 0; i < 10; i++)
X						if (macs[i+macoffset][0] != 0)
X								printf("Macro %d = [%c]%s\r\n", i, 
X									macs[i+macoffset][0],
X									macs[i+macoffset]+1);
X						break;
X					case 'L':		/* Set command lock */
X					case 'l':
X						ComLock = ComLock * -1;
X						break;
X					case '1':		/* Send macro string */
X					case '2':
X					case '3':
X					case '4':
X					case '5':
X					case '6':
X					case '7':
X					case '8':
X					case '9':
X					case '0':
X						i = (c[1] & 0x7f)-'0'+macoffset;
X						sendstring(macs[i],
X							modem, delay, eoldelay);
X						macoffset = gonext[i]*10;
X						break;
X					case 'A':		/* Load script */
X					case 'a':
X						promptfor("Script File: ", filen, 13);
X						dialer = fopen(filen, "r");
X						if (dialer != NULL)
X							readscript(dialer);
X						scriptstart = 0;
X						break;
X					case 'r':
X					case 'R':
X						if (scriptchild != 0) {
X							printf("\r\n*** Script running!\r\n");
X							}
X						else {
X							rbuf[0] = 'P';
X							write(fildes[1], rbuf, 1);
X							kill(child, 14);
X							if ((scriptchild = fork()) == 0) {
X								runscript(modem, NULL, scriptstart);
X								rbuf[0] = 'G';
X								write(fildes[1], rbuf, 1);
X								kill(child, 14);
X								exit(1);
X								}
X							}
X						break;
X					case 'X':		/* XMODEM */
X					case 'x':
X						printf("\r\nXmodem: (S)end or (R)eceive ? ");
X						chr = getchar() & 0x7f;
X						putchar(chr);
X						fflush(stdout);
X						switch(chr) {
X							case 's':
X							case 'S':
X								promptfor("File: ", filen, 13);
X								xfile = open(filen, 0);
X								if (xfile != -1) {
X									rbuf[0] = 'P';
X									write(fildes[1], rbuf, 1);
X									kill(child, 14);
X									bakedmode();
X									send_file(modem, xfile);
X									rawmode();
X									kill(child, 14);
X									rbuf[0] = 'G';
X									write(fildes[1], rbuf, 1);
X									}
X								break;
X							case 'R':
X							case 'r':
X								promptfor("File: ", filen, 13);
X								xfile = creat(filen, 0775);
X								if (xfile != -1) {
X									rbuf[0] = 'P';
X									write(fildes[1], rbuf, 1);
X									kill(child, 14);
X									bakedmode();
X									recv_file(modem, xfile);
X									rawmode();
X									rbuf[0] = 'G';
X									write(fildes[1], rbuf, 1);
X									kill(child, 14);
X									}
X								break;
X							}
X						break;
X					case 'F':
X					case 'f':
X						rbuf[0] = 'C';
X						write(fildes[1], rbuf, 1);
X						kill(child, 14);
X						dribble = 0;
X						break;
X					case 'T':		/* Toggle dribble file */
X					case 't':
X						rbuf[0] = 'T';
X						write(fildes[1], rbuf, 1);
X						if (dribble == 0) {
X							promptfor("Buffer File: ", filen, 13);
X							for (p = filen; *p != 0; p++)
X								write(fildes[1], p, 1);
X							write(fildes[1], p, 1);
X							dribble = 1;
X							}
X						kill(child, 14);
X						break;
X					case 'U':		/* Dump file to modem */
X					case 'u':
X						promptfor("File: ", filen, 13);
X						upfile = fopen(filen, "r");
X						if (upfile != NULL)
X							while (fgets(buffer, 4096, upfile) 
X									!= NULL)
X								sendstring(buffer,modem, delay,
X									eoldelay);
X						break;
X					case 'S':		/* Send string repeatedly */
X					case 's':
X						promptfor("Message: ", buffer, RTCommand);
X						promptfor("Pause: ", sbuff, 13);
X						printf("Sleep = %d  ", atoi(sbuff));
X						sendchild = fork();
X						if (sendchild == 0)
X							while (1 == 1) {
X								sendstring(buffer,modem, delay,
X									eoldelay);
X								sleep(atoi(sbuff));
X							}
X						break;
X					case 'K':		/* Kill autorepeat process */
X					case 'k':
X						if (sendchild != 0)
X							kill(sendchild, 15);
X						sendchild = 0;
X						break;
X					case 'C':		/* Kill script process */
X					case 'c':
X						if (scriptchild != 0)
X							kill(scriptchild, 15);
X						scriptchild = 0;
X						rbuf[0] = 'G';
X						write(fildes[1], rbuf, 1);
X						kill(child, 14);
X						break;
X					case 'P':		/* Exit program without hangup */
X					case 'p':
X						bakedmode();
X						rbuf[0] = 'Q';
X						write(fildes[1], rbuf, 1);
X						kill(child, 14);
X						if (scriptchild != 0)
X							kill(scriptchild, 15);
X						if (sendchild != 0) kill(sendchild, 15);
X						exit(1);
X						break;
X					}
X				}
X			}
X		else {		/* Send character */
X			if (lecho == 1)
X				putchar(c[0]);
X			write(modem, c, 1);
X			}
X		}
X	bakedmode();
X	tmode1.sg_ispeed = 0;				/* Set baud rate */
X	tmode1.sg_ospeed = 0;
X	ioctl(modem, TIOCSETP, &tmode1);
X	sleep(1);
X	ioctl(modem, TIOCSETP, &tmd2);
X	rbuf[0] = 'Q';
X	write(fildes[1], rbuf, 1);
X	kill(child, 14);
X	if (sendchild != 0) kill(sendchild, 15);
X	if (scriptchild != 0)
X		kill(scriptchild, 15);
X	sprintf(lockfile, "/usr/spool/uucp/LCK..%s", line);
X	close(modem);
X	unlink(lockfile);
X	printf("\nFred exit\n");
X	}
SHAR_EOF
echo 'Orignal Sum -> 55155 28 t.c'
echo -n 'Current Sum -> '
sum t.c
echo shar: extracting t.h
sed 's/^X//' << 'SHAR_EOF' > t.h
X#include <setjmp.h>
X#include <signal.h>
X#include <sgtty.h>
X#include <stdio.h>
X#include <pwd.h>
X#include <errno.h>
X
Xtypedef	unsigned char	byte;		/* Make borrowed XMODEM software */
Xtypedef	unsigned short	word;		/* happy 					   */
Xint	timer();						
X
Xstruct scriptent {
X	int timeout;
X	int delay;
X	char *sendstring;
X	char **findstring;
X	char *xmodem;
X	int *tcase;
X	int fcase;
X	};
X
X
Xunsigned char mk_chksum();
X
X#define	NUL	0x00
X#define	SOH	0x01
X#define	EOT	0x04
X#define	ACK	0x06
X#define	NAK	0x15
X#define	CAN	0x18
X
X#define	RETRY_MAX	10
X#define	BUFF_SIZE	128
X
X
X
SHAR_EOF
echo 'Orignal Sum -> 43530 2 t.h'
echo -n 'Current Sum -> '
sum t.h
echo shar: extracting tdefs.c
sed 's/^X//' << 'SHAR_EOF' > tdefs.c
X#include "t.h"
X
Xstruct sgttyb tmode, tmode1, tmd2;		/* Hold old terminal modes */
X
Xint debug, lecho, exitflag, dribble;	/* Global flags */
X
Xchar **rstrings;
X
Xstruct scriptent **script;
X
Xjmp_buf env, env1;
X
X
XFILE *drfile;
X
Xchar *dribfile,
X	*macs[100], 	/* Macro table */
X	*labels[10]; 	/* Labels for macro banks */
X
Xint	    tflag,		/* Flags associated with terminal */
X	    tflag1,		/* Flags associated with modem */
X	    fildes[2],
X         repdes[2],
X         gonext[100];	/* Dispatch table for macros */
X
X
SHAR_EOF
echo 'Orignal Sum -> 39376 1 tdefs.c'
echo -n 'Current Sum -> '
sum tdefs.c
echo shar: extracting textern.h
sed 's/^X//' << 'SHAR_EOF' > textern.h
X#include "t.h"
X
Xextern struct sgttyb tmode, tmode1;	/* Hold old terminal modes */
Xextern struct sgttyb tmd2;		/* Hold old terminal modes */
Xextern jmp_buf env, env1;
Xextern int debug, lecho, exitflag, dribble;	/* Global flags */
Xextern char **rstrings;
Xextern struct scriptent script[];
X
Xextern FILE *drfile;
X
Xextern char *dribfile,
X	*macs[100], 	/* Macro table */
X	*labels[10]; 	/* Labels for macro banks */
X
Xextern int	    tflag,		/* Flags associated with terminal */
X	    tflag1,		/* Flags associated with modem */
X	    fildes[2],
X	    repdes[2],
X         gonext[100];	/* Dispatch table for macros */
X
SHAR_EOF
echo 'Orignal Sum -> 49367 2 textern.h'
echo -n 'Current Sum -> '
sum textern.h
echo shar: extracting tscript.c
sed 's/^X//' << 'SHAR_EOF' > tscript.c
X#include "t.h"
X
Xextern struct sgttyb tmode, tmode1;			/* Hold old terminal modes */extern jmp_buf env;
Xextern int debug, lecho, exitflag;				/* Global flags */
Xstruct scriptent **script;
X
Xreadscript(file)
XFILE *file;
X{
X	char *p, **findstrings, *sendhold, chr, chr1, *xmodem, *instring;
X	int i, touthold, *tcase, fcase, delayhold, k, eflag;
X	struct scriptent *entry;
X
X	instring = (char *) malloc(512);
X	
X	script = (struct scriptent **) malloc(sizeof(struct scriptent *) * 1000);
X	printf("Reading script...\n\r");
X	p = (char *)malloc(128);
X	i = 0;
X	findstrings = (char **)malloc(sizeof(char *) * 10);
X	tcase = (int *)malloc(sizeof(int) * 10);
X	sendhold = "";
X	xmodem = "";
X	touthold = 1;
X	fcase = -1;
X	delayhold = 0;
X	k = 0;
X	eflag = 0;
X	while (eflag != 1) {			/* No more than 20 states */
X		k++;
X		chr = getc(file);
X		if (((chr1 = getc(file)) != ':'))
X			if (chr1 != '+') {
X				printf("Error in script file, line %d\r\n", k);
X				printf("%c%c\n", chr, chr1);
X				return(1);
X				}
X		switch(chr) {
X			case 'S':
X				fgets(p, 20, file);
X				i = atoi(p);
X				break;
X			case 'T':
X				fgets(p, 20, file);
X				touthold = atoi(p);
X				break;
X			case 'X':
X				readstring(p, file);
X				xmodem = (char *) malloc(strlen(p)+1);
X				strncpy(xmodem, p, strlen(p));
X				break;
X			case 'D':
X				fgets(p, 20, file);
X				delayhold = atoi(p);
X				break;
X			case 'O':
X				readstring(p, file);
X				sendhold = (char *) malloc(strlen(p)+1);
X				strncpy(sendhold, p, strlen(p));
X				break;
X			case '0':
X			case '1':
X			case '2':
X			case '3':
X			case '4':
X			case '5':
X			case '6':
X			case '7':
X			case '8':
X			case '9':
X				if (chr1 == ':') {
X					readstring(p, file);
X					findstrings[chr - '0'] = 
X						(char *) malloc(strlen(p)+1);
X					strncpy(findstrings[chr - '0'], p, strlen(p));
X					}
X				else {
X					fgets(p, 20, file);
X					tcase[chr - '0'] = atoi(p);
X					}
X				break;
X			case '#':
X				fgets(p, 128, file);
X				break;
X			case '-':
X				fgets(p, 20, file);
X				fcase = atoi(p);
X				break;
X			case '$':
X				printf("Read state %d\n\r", i);
X				entry = script[i] = (struct scriptent *) 
X									malloc(sizeof(struct scriptent));
X				entry->timeout = touthold;
X				entry->sendstring = sendhold;
X				entry->findstring = findstrings;
X				entry->tcase = tcase;
X				entry->fcase = fcase;
X				entry->delay = delayhold;
X				entry->xmodem = xmodem;
X				findstrings = (char **)malloc(sizeof(char *) * 10);
X				tcase = (int *)malloc(sizeof(int) * 10);
X				i++;
X				xmodem = "";
X				sendhold = "";
X				touthold = 1;
X				fcase = -1;
X				delayhold = 0;
X				fgets(p,20,file);
X				break;
X			case 'E':
X				fgets(p,20,file);
X				eflag = 1;
X				break;
X			default:
X				printf("Illegal argument %c\n", chr);
X				return(1);
X				break;
X			}
X		}
X
X	return(0);
X	}
X
Xrunscript(line, dribblefile, state)
Xint line, state;
XFILE *dribblefile;
X{
X	int failed,					/* Punt flag */
X	    xfile,
X	    i,
X	    match;
X
X	char *bo, 					/* Output buffer */
X	     *bi, 					/* Input character */
X		*str, 					/* Random pointer */
X		*p,
X		*lookp[10];					/* Holder for search strings */
X
X	bo = (char *)malloc(20);
X	bi = (char *)malloc(2);
X
X	while (state > -1) {
X		if (debug == 1)
X			printf("State = %d\r\n", state);
X
X		if (script[state]->delay != 0) {
X			signal(SIGALRM, timer);
X			if (setjmp(env) == 0) {
X				alarm(script[state]->delay);
X				while (1 == 1) {
X					read(line, bi, 1);
X					putchar(bi[0]);
X					fflush(stdout);
X					}
X				}
X			}
X
X		sendstring(script[state]->sendstring, line, 1000, 0);
X		failed = 1;
X
X		p = script[state]->xmodem;
X		if (*p != 0) {
X			if (*p == 'S') {
X				xfile = open(p+1, 0);
X				if (xfile != -1)
X					failed = send_file(line, xfile);
X				}
X			if (*p == 'R') {
X				xfile = creat(p+1, 0755);
X				if (xfile != -1)
X					failed = recv_file(line, xfile);
X				}
X			}	
X
X		if (failed != -1 && failed != 0) {
X			for (i = 0; i < 10; i++) lookp[i] = script[state]->findstring[i];
X			match = -1;
X
X			if (setjmp(env) == 0) {
X				signal(SIGALRM, timer);
X				alarm(script[state]->timeout);
X				while (match == -1) {
X					read(line, bi, 1);
X					if (dribblefile != NULL)	putc(bi[0], dribblefile);
X					bi[0] = bi[0] & 0x7f;
X					putchar(bi[0]);
X					fflush(stdout);
X					for (i = 0; i < 10; i++)
X						if (lookp[i] != 0) {
X							p = lookp[i];
X							if (*p != bi[0]) {
X								p = script[state]->findstring[i];
X								if (*p == bi[0]) ++p;
X								lookp[i] = p;
X								}
X							else {
X								lookp[i] = ++p;
X								if (*p == 0) match = i;
X								}
X							}
X					}
X				failed = 0;
X				}
X			}
X		if (failed != 0) state = script[state]->fcase;
X		else state = (script[state]->tcase)[match];
X		}
X
X	alarm(0);
X	signal(SIGALRM, SIG_DFL);
X	switch (state) {
X		case -1:
X			printf("%c*** Script Done ***\r\n", 7);
X			break;
X		case -2:
X			printf("*** Disconnecting ***\r\n");
X			exitflag = 1;
X			break;
X		default:
X			printf("*** Script Failed\r\n");
X			break;
X		}
X	}
X
SHAR_EOF
echo 'Orignal Sum -> 2351 10 tscript.c'
echo -n 'Current Sum -> '
sum tscript.c
echo shar: extracting tutil.c
sed 's/^X//' << 'SHAR_EOF' > tutil.c
X#include <errno.h>
X#include "textern.h"
X
Xextern int errno;
X
Xreadstring(string, file)
Xchar *string;
XFILE *file;
X{
X	char *p, *p1, c;
X
X	p = string;
X	while ((*p = getc(file)) != '\n') {
X		if (*p == '\\') {
X			switch(c = getc(file)) {
X				case 'r':
X					*p = '\r';
X					break;
X				case 'n':
X					*p = '\n';
X					break;
X				case '0':
X				case '1':
X				case '2':
X				case '3':
X				case '4':
X				case '5':
X				case '6':
X				case '7':
X				case '8':
X				case '9':
X					p1 = rstrings[c - '0'];
X					while (*p1 != 0) 
X						*p++ = *p1++;
X				p--;
X				}
X			}
X		p++;
X		}
X	*p = 0;
X	}
X
Xfatal(string)
Xchar *string;
X{
X	printf("term: ~s\n", string);
X	}
X
X
Xsendstring(string, port, delay, eoldelay)
Xchar *string;
Xint port;
X{
X	int i;
X	char dummy[1];
X
X	dummy[0] = '\r';
X
X	if (*string == 0) {
X		write(port, dummy, 1);
X		if (lecho == 1) 
X			putchar(dummy[0]);
X		}
X	while (*string != 0) {
X		if ((*string == '\n') || (*string == '\r')) {
X			write(port, dummy, 1);
X			if (lecho == 1) 
X				putchar(dummy[0]);
X			for (i=0; i < eoldelay; i++);
X			}
X		else {
X			write(port, string, 1);
X			if (lecho == 1) 
X				putchar(string[0]);
X			}
X		string++;
X		for (i=0; i < delay; i++);
X		}
X	}
X
Xprinthelp(name)
Xchar *name;
X{
X	printf("%s -a site -c chr -d -h -l line -m macro -o -L -S -0-9 string\n",
X		name);
X	printf("-a	Autodial Number (Example: Fred -aGEnie)\n");
X	printf("-c	Real Time Command character (Example: Fred -c%)\n");
X	printf("-d	Debugging on (Example: Fred -d)\n");
X	printf("-h	Print this text (Example: Fred -h)\n");
X	printf("-l	Line (Example: Fred -ltty01)\n");
X	printf("-m	Macro File (Example: Fred -mGEnie)\n");
X	printf("-o	Override Lock File (Example: Fred -o)\n");
X	printf("-L	Local Echo (Example: Fred -L)\n");
X	printf("-S	Slow (300) baud (Example: Fred -S)\n");
X	printf("-0	Replacement string for login script (example: Term -0XJM0000,TEST)\n");
X	printf(" .\n");
X	printf("-9\n");
X
X	exit(1);
X	}
X
Xint waitflg;
X
Xgetwait()
X{
X	char rbuf[1], *p, ch, filen[30];
X
X	read(fildes[0], rbuf, 1);
X	switch (rbuf[0]) {
X		case 'Q':
X			if (drfile != NULL)
X				fclose(drfile);
X			exit(1);
X			break;
X		case 'C':
X			if (drfile != NULL)
X				fclose(drfile);
X			dribble = 0;
X			drfile = NULL;
X			break;
X		case 'T':
X			if (dribble == 0) {
X				if (drfile == NULL) {
X					read(fildes[0], rbuf, 1);
X					p = filen;
X					while (rbuf[0] != 0) {
X						*p = rbuf[0];
X						read(fildes[0], rbuf, 1);
X						p++;
X						}
X					*p = 0;
X					drfile = fopen(filen, "w");
X					}
X				dribble = 1;
X				}
X			else
X				dribble = 0;
X
X			if (dribble == 1)
X				printf("\r\n*** Dribble File On ***\r\n");
X			else
X				printf("\r\n*** Dribble File Off ***\r\n");
X			break;
X		case 'P':
X			waitflg = 1;
X			signal(SIGALRM, getwait);
X			longjmp(env1);
X			break;
X		case 'G':
X			waitflg = 0;
X			break;
X		}
X	signal(SIGALRM, getwait);
X	}
X
Xforkinput(modem)
Xint modem;
X{
X
X	int n, k, r, p;
X	char charbuf[30];
X
X	k = 0;
X	n = fork();
X	if (n != 0) return(n);
X	waitflg = 0;
X	dribble = 0;
X	signal(SIGALRM, getwait);
X	setjmp(env1);
X	write(repdes[1], charbuf, 1);
X	while (waitflg == 1) k = k + 1;
X	while (1 == 1) {
X		errno = 0;			/* Clear errno */
X		if ((r = read(modem, charbuf, 29)) > 0) {
X			charbuf[r] = 0;
X			for (p = 0; p < r; p++)
X				charbuf[p] = (charbuf[p] & 0x7f);
X			write(1, charbuf, r);
X			fflush(stdout);
X			if (dribble != 0) fputs(charbuf, drfile);
X		} else if (errno != EINTR) exit(0);/* Quit when closed */
X	}
X}
X
SHAR_EOF
echo 'Orignal Sum -> 34444 7 tutil.c'
echo -n 'Current Sum -> '
sum tutil.c
echo shar: extracting txmodem.c
sed 's/^X//' << 'SHAR_EOF' > txmodem.c
X#include "textern.h"
X
X/*	Send_file()							*/
X/*	Routine to send a file from Unix to another computer via 	*/
X/*	/dev/tty using the xmodem protocol in checksum mode.		*/
X/*									*/
X/*	On Entry: terminal file id, and file to send file id */
X/*	On exit: returns 0 for success or -1 for failure		*/
X
Xsend_file(tty_fid, sfile)
Xint	tty_fid,
X	sfile;
X{
Xint	ret_code,
X	read_status,
X	tty_status,
X	ack_status,
X	retry_counter;
X	
X
Xunsigned char	checksum,
X		sector_num,
X		temp_byte,
X		start_bad;
X
Xchar	cpm_buff[BUFF_SIZE]; /* CP/M disk buffers are ALWAYS 128 bytes	*/
X
X
X	ret_code = 0; /* assume no errors */
X
X	retry_counter = 0;	/* reset counter */
X	do	/* wait for NAK from receiver so we can get in sync */
X	{
X		tty_status = timed_read(tty_fid, &temp_byte, 1, 6);
X
X		if ( (tty_status == 0) &&
X		     ((temp_byte == NAK) || (temp_byte == CAN)) )
X		{
X			if (temp_byte == NAK)
X			{
X				start_bad = 0;
X				break;
X			}
X			else
X			{
X				start_bad = 1;
X				break;
X			}
X		}
X		else
X		{
X			start_bad = 1;
X			retry_counter++;
X		}
X	}
X	while (retry_counter < RETRY_MAX);
X
X	if (start_bad)
X	{
X		ret_code = -1;	/* say error */
X				/* We timed out or we got too much noise */
X	}
X	else
X	{
X		printf("Sending...\r\n");
X		sector_num = 0;
X		do
X		{
X			read_status = read(sfile, cpm_buff, BUFF_SIZE);
X			sector_num++;
X			if (read_status > 0)
X			{
X				printf("Sending sector %d\r", sector_num);
X				fflush(stdout);
X				for(; read_status < BUFF_SIZE; read_status++)
X				{
X					cpm_buff[read_status] = 0x1a; /* CP/M eof */
X				}
X
X				retry_counter = 0;	/* reset to send actual packet */
X				do
X				{
X					temp_byte = SOH;
X					write(tty_fid, &temp_byte, 1);	/* send SOH */
X					temp_byte = ~sector_num;	/* get ones complement of sector number */
X					write(tty_fid, &sector_num, 1);	/* sector count */
X					write(tty_fid, &temp_byte, 1);	/* and its complement */
X					checksum = mk_chksum(cpm_buff, BUFF_SIZE);
X					write(tty_fid, cpm_buff, BUFF_SIZE);
X					write(tty_fid, &checksum, 1);	/* send checksum */
X					if ((ack_status = getack(tty_fid)) == -1)
X					{
X						retry_counter++;
X					}
X				}
X				while ( (ack_status == -1) && (retry_counter < RETRY_MAX) );
X			}
X		}
X		while ( (read_status > 0) && (retry_counter < RETRY_MAX) );
X
X		retry_counter = 0;
X		do
X		{
X			temp_byte = EOT;
X			write(tty_fid, &temp_byte, 1);	/* send EOT */
X		}
X		while ( (getack(tty_fid) != 0) && (retry_counter++ < RETRY_MAX) );
X	}
X
X	if (retry_counter >= RETRY_MAX)
X	{
X		ret_code = -1;
X	}
X
X	close(sfile);
X	printf("\r\n");
X	return(ret_code);
X}
X
X
X
X/*	Recv_file()							*/
X/*	Routine to receive  a file to Unix from another computer via 	*/
X/*	/dev/tty using the xmodem protocol in checksum mode.		*/
X/*									*/
X/*	On Entry: terminal file id, file to recv file id */
X/*	On exit: returns 0 for success or -1 for failure		*/
X
Xrecv_file(tty_fid, rfile)
Xint	tty_fid,
X     rfile;
X{
Xint	ret_code,
X	read_status,
X	tty_status,
X	ack_status,
X	retry_counter,
X	count,
X	c1,
X	dtime;
X	
X
Xunsigned char	checksum,
X		sector_num,
X		temp_byte,
X		dummys[5],
X		start_bad,
X		chr;
X
X
Xchar	cpm_buff[BUFF_SIZE]; /* CP/M disk buffers are ALWAYS 128 bytes	*/
X
X	ret_code = 0; /* assume no errors */
X
X	c1 = 0;
X	dtime = time();
X
X	retry_counter = 0;	/* reset counter */
X	do	/* send a NAK to sender so we can get in sync */
X	{
X		temp_byte = NAK;
X		write(tty_fid, &temp_byte, 1);
X
X		tty_status = timed_read(tty_fid, &temp_byte, 1, 6);
X
X		if ( (tty_status == 0) &&
X		     ((temp_byte == SOH) || (temp_byte == CAN)) )
X		{
X			if (temp_byte == SOH)
X			{
X				start_bad = 0;
X				break;
X			}
X			else
X			{
X				start_bad = 1;
X				break;
X			}
X		}
X		else
X		{
X			start_bad = 1;
X			retry_counter++;
X		}
X	}
X
X	while (retry_counter < RETRY_MAX);
X
X	if (start_bad)
X	{
X		ret_code = -1;	/* say error */
X				/* We timed out or we got too much noise */
X	}
X	else
X	{
X		retry_counter = 0;
X		sector_num = 1;		/* to compare with sent sector number */
X
X/* First SOH was caught in NAK, CAN, code above. */
X
X
X		while ( (temp_byte == SOH) && (retry_counter < RETRY_MAX) )
X		{
X			tty_status = stimed_read(tty_fid, &dummys[0], 2);
X			tty_status += stimed_read(tty_fid, &dummys[1], 2);
X
X			for (ack_status = 0; ack_status < BUFF_SIZE; ack_status++)
X			{
X				tty_status += stimed_read(tty_fid, &cpm_buff[ack_status], 2);
X			}
X
X			tty_status += stimed_read(tty_fid, &dummys[2], 2);
X
X			checksum = mk_chksum(cpm_buff, BUFF_SIZE);
X
X			if ( (tty_status == 0) &&
X			     (sector_num == dummys[0]) && ((~sector_num & 0xff) == dummys[1]) &&
X			     (checksum == dummys[2]) )
X			{
X				c1++;
X				printf("Received sector %d\r", c1);
X				fflush(stdout);
X				write(rfile, cpm_buff, BUFF_SIZE);
X				ack_status == BUFF_SIZE;
X				if (ack_status == BUFF_SIZE)
X				{
X					temp_byte = ACK;
X					write(tty_fid, &temp_byte, 1);
X					retry_counter = 0;
X					ret_code = 0;
X					sector_num++;
X				}
X				else
X				{
X					temp_byte = NAK;
X					write(tty_fid, &temp_byte, 1);
X					retry_counter++;
X					ret_code = -1;
X				}
X			}
X			else
X			{
X				temp_byte = NAK;
X				write(tty_fid, &temp_byte, 1);
X				retry_counter++;
X				ret_code = -1;
X			}
X
X			tty_status = stimed_read(tty_fid, &temp_byte, 2);
X
X			while (	(temp_byte != SOH) && (temp_byte != EOT) &&
X				(retry_counter < RETRY_MAX) )
X			{
X				retry_counter++;
X				tty_status = stimed_read(tty_fid, &temp_byte, 2);
X			}
X
X			if (retry_counter >= RETRY_MAX)
X			{
X				ret_code = -1;
X				break;
X			}
X
X			retry_counter = 0;
X			if (temp_byte == EOT)
X			{
X				temp_byte = ACK;
X				write(tty_fid, &temp_byte, 1);
X				break;
X			}
X		}
X	}
X
X	close(rfile);
X	printf("\r\n");
X	printf("Received %d packets in %d seconds, effective rate %d/sec\r\n",
X			c1, time() - dtime, (c1 * 128) / (time() - dtime));
X	fflush(stdout);
X	return(ret_code);
X}
X
X
X/*	getack: Will do a timed read on a pre-selected tty and 
X	will return the status.
X
X	On Entry: is passed the file id of the tty to use
X	On exit: returns 0 if got an ACK else returns -1 
X*/
X
Xgetack(tty_fid)
Xint	tty_fid;
X{
Xchar	temp_byte;
X
X	if ( (timed_read(tty_fid, &temp_byte, 1, 5) == 0) &&
X	     (temp_byte == ACK) )
X	{
X		return(0);	/* got ACK ok */
X	}
X	else
X	{
X		return(-1);	/* timed out or wrong character */
X	}
X}
X
X
X/*	mk_chksum: Will generate a checksum on array of specified size and return
X		   that checksum.
X
X	On Entry: is passed the array and size to use
X	On exit: returns checksum
X*/
X
Xunsigned char mk_chksum(array, size)
Xchar	*array;
Xint	size;
X{
Xint	counter;
Xunsigned char	checksum;
X
X	checksum = 0;
X	for (counter = 0; counter < size; counter++)
X	{
X		checksum += array[counter];	/* build up checksum */
X	}
X	return(checksum);
X}
X
Xtimed_read(tty_fd, ch, count, seconds)
Xint	tty_fd,
X	count;
Xbyte	*ch;
Xunsigned	seconds;
X{
Xint	ret_code,
X	tim_code;
X
X
X	signal(SIGALRM, timer);
X	alarm(seconds);
X
X	ret_code = -1;	/* assume bad read */
X
X	tim_code = setjmp(env);
X	while ( (tim_code == 0) && (ret_code != 1) )
X	{
X		ret_code = read(tty_fd, ch, count);
X	}
X
X	alarm(0);	/* turn alarms off */
X	signal(SIGALRM, SIG_DFL);
X
X	return( ((ret_code != -1) && (ret_code == count)) ? 0 : -1 );
X}
X
X
X/*	stimed_read: Will attempt to read from the terminal specified	*/
X/*		    by the tty file descriptor for a set period of time.*/
X/*									*/
X/*	On Entry: tty file descriptor to read from, pointer to a byte	*/
X/*		  to return received char in.				*/
X/*		  and time in seconds.					*/
X/*	On exit:  0 for ok read or -1 for no char received.		*/
X/*									*/
X
Xstimed_read(tty_fd, ch, seconds)
Xint	tty_fd;
Xbyte	*ch;
Xunsigned	seconds;
X{
Xint	ret_code,
X	tim_code;
X
X
X	signal(SIGALRM, timer);
X	alarm(seconds);
X
X	ret_code = -1;	/* assume bad read */
X
X	tim_code = setjmp(env);
X	while ( (tim_code == 0) && (ret_code != 1) )
X	{
X		ret_code = read(tty_fd, ch, 1);
X	}
X
X	alarm(0);	/* turn alarms off */
X	signal(SIGALRM, SIG_DFL);
X
X	return( (ret_code != -1) ? 0 : ret_code );
X}
X
X
Xtimer(signal)
Xint	signal;	/* variable to catch signal sent to routine.	*/
X		/* we will just ignore it.			*/
X{
X	longjmp(env, 1);
X}
X
Xrawmode()
X{
X	
X	ioctl(0, TIOCGETP, &tmode);
X	tflag = tmode.sg_flags;
X	tmode.sg_flags = ANYP+RAW+NL1+CR1;
X	ioctl(0, TIOCSETP, &tmode);
X	}
X
Xbakedmode()
X{
X		tmode.sg_flags = tflag;
X		ioctl(0, TIOCSETP, &tmode);
X		}
X
Xpromptfor(prompt, string, term)
Xchar *prompt, *string, term;
X{
X	char *p;
X
X	p = string;
X	printf("\n\r");
X	printf(prompt);
X	while((*p = (getchar() & 0x7f)) != term) {
X		switch(*p) {
X			case 8:
X				putchar(*p);
X				p--;
X				if (p < string) p = string;
X				break;
X			case 21:
X				printf("XXXXXXXX\r\n");
X				p = string;
X			default:
X				putchar(*p);
X				p++;
X			}
X		}
X	*p = 0;	
X	printf("\n\r");
X	}
X
Xreadmacros(file)
XFILE *file;
X{
X	char chr, *p;
X	int i,k;
X	i = k = 0;
X	while ((chr = getc(file)) != EOF)
X		if (chr == '#') {				
X			p = labels[k] = 		/* Read label */
X				(char *) malloc(128);
X			while ((*p = getc(file)) != '\n') p++;
X			p++;
X			*p = 0;
X			i = k * 10;
X			printf("***%s", labels[k++]);
X			}
X		else
X			{
X			gonext[i] = chr - '0';		/* Dispatch */
X			readstring(macs[i], file);
X			i++;
X			}
X	}
SHAR_EOF
echo 'Orignal Sum -> 65443 18 txmodem.c'
echo -n 'Current Sum -> '
sum txmodem.c
exit

rsalz@papaya.bbn.com.UUCP (10/08/87)

In alt.sources (<246@ddsw1.UUCP>), ringwld!jmturn@CCA.CCA.COM (James M. Turner) writes:
>XFred: Fred Runs Every Dialer
X
XA general purpose terminal program for Unix.
X
XCopyright (c) 1986, Pipe Dream Associates
X
XFRED is shareware, Pipe Dream Associates retains any and all 
Xcopyrights to this software. It may be copied or uploaded so
Xlong as no attempt is made to charge for it.
X
XFRED represents a great deal of work on my part, over a year of
Xdevelopment. I have no real desire to market this as a product, but
Xif you find FRED useful, you might see your way to send me something
Xto recompense this development time.

Sigh.  You could argue that as moderator of comp.sources.unix I have an
axe to grind, but I really hate people using the net to post shareware;
my phone is being used to help you get money (yes, BBN has UUCP links :-).

Sorry to post this here; do we need an alt.sources.d?
	/r$
-- 
For comp.sources.unix stuff, mail to sources@uunet.uu.net.

ignatz@chinet.UUCP (10/09/87)

The lament is "...using my phone to get them money..." (paraphrased.)

Maybe; they can ask all they want, but no promise of $$$.  And no
demand; and with that mix, I think shareware fits within the purvue of
the net...
-- 
			Dave Ihnat
			ihnp4!homebru!ignatz || ihnp4!chinet!ignatz
			(w) (312) 882-4673

jmturn@ddsw1.UUCP (10/10/87)

I'm sorry I inadvertaintly violated net etiquite in posting Fred with a
shareware notice in it, it was the farthest thing from my mind to offend
anyone. That notice is left over from when I posted Fred to some commercial
services. I'd appreciate it if people would ignore everything but the notice
prohibiting resale of the software, and use Fred as they will.

James Turner
ringwld!jmturn@CCA.CCA.COM

timothym@tekigm2.UUCP (10/13/87)

Hi,

Fred, is also trademarked and copyrighted by Ashton-Tate. Another name for
this program may be indicated... especially if a wide distribution is expected.


-- 
Tim Margeson (206)253-5240
PO Box 3500  d/s C1-937                          @@   'Who said that?'  
Vancouver, WA. 98668
{amd..hplabs}cae780!tektronix!tekigm2!timothym (this changes daily)