From:	CSBVAX::MRGATE!info-vax-request@kl.sri.com@SMTP 30-JAN-1988 04:58
To:	ARISIA::EVERHART
Subj:	Re: Wanted: XMODEM/CKermit


Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Fri 29 Jan 88 20:18:12-PST
Received: by ucbvax.Berkeley.EDU (5.58/1.26)
	id AA08436; Fri, 29 Jan 88 19:20:38 PST
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 29 Jan 88 07:26:17 GMT
From: portal!cup.portal.com!DMasterson@uunet.uu.net
Organization: The Portal System (TM)
Subject: Re: Wanted: XMODEM/CKermit
Message-Id: <2804@cup.portal.com>
References: <543@naucse.UUCP>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

>1.  Does anyone have XMODEM (or YMODEM, or any Christenson protocol program)
>    that will run under VMS 4.6?
>
>jdc  (...!arizona!naucse!jdc)   (602) 523-6259
>John Campbell               ...!arizona!naucse!jdc
>
     Attached below is a shar file containing a C program that should allow
you to run the Xmodem protocol under VMS 4.6 (at least I used it that way).  I
forget if there are any necessary changes to this, but they should be very
minor.  One thing that I have found is that it sets the terminal
characteristics into a funny mode and this somehow prevents the umodem program
from working more than once per session (I just log off and log on again).  It
does not do anything other than transmit or receive a file using Xmodem.  Have
fun...

					David_Masterson@cup.portal.com
--------------
#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	umodem.c
#	vmodem.c
#	vmodem.h
# This archive created: Mon Dec 21 11:35:21 1987
echo shar: extracting umodem.c
sed 's/^XX//' << \SHAR_EOF > umodem.c
XX#
XX
XX/*
XX *  UMODEM -- Implements the "CP/M User's Group XMODEM" protocol and 
XX *	      the TERM II File Transfer Protocol (FTP) Number 1 for
XX *            packetized file up/downloading.    
XX *
XX *    Note: UNIX System-Dependent values are indicated by the string [SD]
XX *          in a comment field one the same line as the values.
XX *
XX *         -- Lauren Weinstein, 6/81
XX *	   -- (Version 2.0) Modified for JHU/UNIX by Richard Conn, 8/1/81
XX *	   -- Version 2.1 Mods by Richard Conn, 8/2/81
XX *		. File Size Included on Send Option
XX *	   -- Version 2.2 Mods by Richard Conn, 8/2/81
XX *		. Log File Generation and Option Incorporated
XX *	   -- Version 2.3 Mods by Richard Conn, 8/3/81
XX *		. TERM II FTP 1 Supported
XX *		. Error Log Reports Enhanced
XX *		. CAN Function Added to FTP 3
XX *		. 'd' Option Added to Delete umodem.log File before starting
XX *	   -- Version 2.4 Mods by Richard Conn, 8/4/81
XX *		. 16K-extent sector number check error corrected
XX *		. Count of number of received sectors added
XX *	   -- Version 2.5 Mods by Richard Conn, 8/5/81
XX *		. ARPA Net Flag added
XX *		. ARPA Net parameter ('a') added to command line
XX *		. ARPA Net BIS, BIE, BOS, BOE added
XX *		. ARPA Net FFH escape added
XX *	   -- Version 2.6 Mods by Bennett Marks, 8/21/81 (Bucky @ CCA-UNIX)
XX *		. mods for UNIX V7 (Note: for JHU compilation define
XX *		  the variable JHU  during 'cc'
XX *		. added 'mungmode' flag to protect from inadvertant
XX *		  overwrite on file receive
XX *		. changed timeout handling prior to issuing checksum
XX 
XX*	   -- Version 2.7 Mods by Richard Conn, 8/25/81 (rconn @ BRL)
XX *		. correct minor "ifndef" error in which ifndef had no arg
XX *		. restructured "ifdef" references so that other versions
XX *		  of UNIX than Version 7 and JHU can be easily incorporated;
XX *		  previous ifdef references were for JHU/not JHU;
XX *		  to compile under Version 7 or JHU UNIX, the following
XX *		  command lines are recommended:
XX *			"cc -7 umodem.c -o umodem -DVER7" for Version 7
XX *			"cc -7 umodem.c -o umodem -DJHU" for JHU
XX 
XX*		. added 'y' file status display option; this option gives
XX *		  the user an estimate of the size of the target file to
XX *		  send from the UNIX system in terms of CP/M records (128
XX *		  bytes) and Kbytes (1024 byte units)
XX *		. added '7' option which modifies the transmission protocols
XX *		  for 7 significant bits rather than 8; modifies both FTP 1
XX *		  and FTP 3
XX *	   -- Version 2.8 mods by Walter Reiher, 3/12/83 (Harvard Chem. Dept.)
XX *		. Added definitions needed to run UMODEM under VMS.
XX *		  Support subroutines are in another file, VMODEM.C.  Both
XX *		  this file and VMODEM.C #include a third file, VMODEM.H,
XX *		  when being compiled under VMS.  All of the additions here
XX *		  are imbedded in "#ifdef vms" statements EXCEPT the addition
XX *		  of upper case synonyms for some of the command-line
XX *		  switches, since VMS changes the command line to upper case.
XX *		  To compile under VMS, no switches to the compiler are needed.
XX *		. Fixed bug in the handling of long files (i.e., >255 sectors).
XX *		  This file now falls into this category.
XX *		. Included code to cause the program to exit when in send
XX *		  mode and it receives a CAN instead of an ACK from the
XX *		  receiver.  This program, in receive mode, sends a CAN
XX *		  when it encounters a fatal error.  Comment out the
XX *		  "#define CAN_BOMB" line to disable this.
XX *		. Small patches to get it to work under 4.1 BSD VM/UNIX,
XX *		  as running in the Harvard Science Center, where there is
XX *		  tighter checking of addresses vs. ints.
XX *		  Use -DVER7 for VM/UNIX.
XX *		. Make text mode transfers accept lone CRs from CP/M (as
XX *		  opposed to CR/LF pairs) to UNIX.  This permits overstriking.
XX *		. Added report of estimated file transfer time.
XX *		. Removed some more [SD]'s which weren't marked that way;
XX *		  removed some unnecessary subroutine calls by pushing them
XX *		  into "JHU" or "VER7", as appropriate.
XX *
XX */
XX
XX#include <stdio.h>
XX
XX#ifdef vms
XX#include ssdef
XX#include tt2def
XX#include ttdef
XX#include "vmodem.h"
XX
XX/*  #includes for BOTH JHU and VER7  */
XX#else
XX#include <signal.h>
XX#include <sys/types.h>			/*  Ordering for these two  */
XX#include <sys/stat.h>			/*  lines is important      */
XX
XX/*  JHU UNIX tty parameter file  */
XX#ifdef JHU
XX#include <stty.h>
XX#endif
XX
XX/*  Version 7 UNIX tty parameter file  */
XX#ifdef VER7
XX#include <sgtty.h>
XX#endif
XX
XX#endif
XX
XX#define	VERSION		28	/* Version Number */
XX#define	TRUE		1		
XX#define	FALSE		0
XX#define	SOH		001
XX#define	STX		002
XX#define	ETX		003
XX#define	EOT		004
XX#define	ENQ		005
XX#define	ACK		006
XX#define	LF		012	/* Unix LF/NL */
XX#define	CR		015
XX#define	NAK		025
XX#define	SYN		026
XX#define	CAN		030
XX#define	ESC		033
XX#define	CTRLZ		032	/* CP/M EOF for text (usually!) */
XX#define	TIMEOUT		-1
XX#define	ERRORMAX	10	/* maximum errors tolerated */
XX#define	RETRYMAX	10	/* maximum retries to be made */
XX#define	BBUFSIZ		128	/* buffer size -- do not change! */
XX#define	CREATMODE	0644	/* mode for created files */
XX#define	CAN_BOMB		/* Enable bomb out on receipt of CAN */
XX
XX/*  ARPA Net Constants  */
XX#define	     IAC	0377
XX#define	     DO		0375
XX#define	     DONT	0376
XX#define	     WILL	0373
XX#define	     WONT	0374
XX#define	     TRBIN	0
XX
XX/*  JHU UNIX structures  */
XX#ifdef JHU
XXstruct sttybuf ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
XXstruct stat statbuf;		/* for terminal message on/off control */
XX#endif
XX
XX/*  Version 7 UNIX structures  */
XX#ifdef VER7
XXstruct sgttyb  ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
XX#endif
XX
XX/*  VMS structures  */
XX#ifdef vms
XX/*
XX *	TT_INFO structures are used for passing information about
XX *	the terminal.  Used in GTTY and STTY calls.
XX */
XXstruct	tt_info	ttys, ttysnew, ttystemp;
XX#endif
XX
XXFILE	*LOGFP, *fopen();
XXchar	buff[BBUFSIZ + 1];
XX
XX#ifdef JHU
XXint wason;
XX#endif
XX
XX#ifdef VER7
XXint pagelen;
XX#endif
XX
XX#ifndef vms
XXchar *tty, *ttyname();
XX#endif
XX
XXchar	XMITTYPE;
XXint	ARPA, BIT7, BITMASK, DELFLAG, FTP1, LOGFLAG;
XXint	MUNGMODE, PMSG, RECVFLAG, SENDFLAG, STATDISP;
XXint	delay;
XX
XXmain(argc, argv)
XXint argc;
XXchar **argv;
XX{
XX	char *logfile;
XX	int index;
XX	char flag;
XX
XX	logfile = "umodem.log";  /* Name of LOG File */
XX
XX	printf("\nUMODEM Version %d.%d", VERSION/10, VERSION%10);
XX	printf(" -- UNIX-Based Remote File Transfer Facility\n");
XX
XX	if (argc < 3 || *argv[1] != '-')
XX	{  printf("\nUsage:  \n\tumodem ");
XX#ifndef vms
XX		printf("-[rb!rt!sb!st][p][l][1][a][m][d][y][7]");
XX#else
XX		printf("-[rb!rt!sb!st][l][p][y][1][7]");
XX#endif
XX		printf(" filename\n");
XX	   printf("\n");
XX	   printf("\trb <-- Receive Binary\n");
XX	   printf("\trt <-- Receive Text\n");
XX	   printf("\tsb <-- Send    Binary\n");
XX	   printf("\tst <-- Send    Text\n");
XX	   printf("\tl  <-- (ell) Turn OFF LOG File Entries\n");
XX	   printf("\tp  <-- Turn ON Parameter Display\n");
XX	   printf("\ty  <-- Display file status (size) information only\n");
XX	   printf("\t1  <-- (one) Employ TERM II FTP 1\n");
XX	   printf("\t7  <-- Enable 7-bit transfer mask\n");
XX#ifndef vms
XX	   printf("\ta  <-- Turn ON ARPA Net Flag\n");
XX	   printf("\td  <-- Delete umodem.log File before starting\n");
XX	   printf("\tm  <-- Allow file overwiting on receive\n");
XX#endif
XX	   printf("\n");
XX
XX#ifdef vms
XX		exit(SS$_NORMAL);
XX#else
XX		exit(-1);
XX#endif
XX	}
XX
XX/*
XX *	Initializations
XX */
XX	index		= 1;		/* set index for loop */
XX	delay		= 3;		/* assume FTP 3 delay */
XX	RECVFLAG	= FALSE;	/* not receive */
XX	SENDFLAG	= FALSE;	/* not send either */
XX	XMITTYPE	= 't';		/* assume text */
XX	FTP1		= FALSE;	/* assume FTP 3 (CP/M UG XMODEM2) */
XX	LOGFLAG		= TRUE;		/* assume log messages */
XX	PMSG		= FALSE;	/* turn off flags */
XX	STATDISP	= FALSE;	/* assume not a status display */
XX	BIT7		= FALSE;	/* assume 8-bit communication */
XX	ARPA		= FALSE;	/* assume not on ARPA Net */
XX	DELFLAG		= FALSE;	/* do NOT delete log file
XX					 *   before starting */
XX	MUNGMODE	= FALSE;	/* protect files from overwriting */
XX
XX	while ((flag = argv[1][index++]) != '\0')
XX	    switch (flag) {
XX		case '1' : FTP1 = TRUE;  /* select FTP 1 */
XX			   delay = 5;  /* FTP 1 delay constant */
XX			   printf("\nUMODEM:  TERM II FTP 1 Selected\n");
XX			   break;
XX		case '7' : BIT7 = TRUE;  /* transfer only 7 bits */
XX			   break;
XX		case 'a' : ARPA = TRUE;  /* set ARPA Net */
XX			   break;
XX		case 'd' : DELFLAG = TRUE;  /* delete log file first */
XX			   break;
XX		case 'L':
XX		case 'l' : LOGFLAG = FALSE;  /* turn off log report */
XX			   break;
XX		case 'm' : MUNGMODE = TRUE; /* allow overwriting of files */
XX			   break;
XX		case 'P':
XX		case 'p' : PMSG = TRUE;  /* print all messages */
XX			   break;
XX		case 'R':
XX		case 'r' : RECVFLAG = TRUE;  /* receive file */
XX			   XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
XX			   break;
XX		case 'S':
XX		case 's' : SENDFLAG = TRUE;  /* send file */
XX			   XMITTYPE = gettype(argv[1][index++]);
XX			   break;
XX		case 'Y':
XX		case 'y' : STATDISP = TRUE;  /* display file status */
XX			   break;
XX		default  : error("Invalid Flag", FALSE);
XX		}
XX
XX	if (BIT7 && (XMITTYPE == 'b'))
XX	{  printf("\nUMODEM:  Fatal Error -- Both 7-Bit Transfer and ");
XX	   printf("Binary Transfer Selected");
XX#ifdef vms
XX	   exit(SS$_NORMAL);
XX#else
XX	   exit(-1);
XX#endif
XX	}
XX
XX	if (BIT7)  /* set MASK value */
XX	   BITMASK = 0177;  /* 7 significant bits */
XX	else
XX	   BITMASK = 0377;  /* 8 significant bits */
XX
XX	if (PMSG)
XX	   { printf("\nSupported File Transfer Protocols:");
XX	     printf("\n\tTERM II FTP 1");
XX	     printf("\n\tCP/M UG XMODEM2 (TERM II FTP 3)");
XX	     printf("\n\n");
XX	   }
XX
XX	if (LOGFLAG)
XX	   { if (!DELFLAG)
XX		LOGFP = fopen(logfile, "a");  /* append to LOG file */
XX	     else
XX		LOGFP = fopen(logfile, "w");  /* new LOG file */
XX	     fprintf(LOGFP,"\n\n++++++++\n");
XX	     fprintf(LOGFP,"\nUMODEM Version %d.%d\n", VERSION/10, VERSION%10);
XX	     printf("\nUMODEM:  LOG File '%s' is Open\n", logfile);
XX	   }
XX
XX	if (STATDISP) yfile(argv[2]);  /* status of a file */
XX
XX	if (RECVFLAG && SENDFLAG)
XX		error("Both Send and Receive Functions Specified", FALSE);
XX	if (!RECVFLAG && !SENDFLAG)
XX		error("Neither Send nor Receive Functions Specified", FALSE);
XX
XX/*
XX *	If receiving a file, first check to see if it exists.
XX *	If MUNGMODE is off, then abort with error unless we're running
XX *	under VMS, where CREAT() makes a file with a new version number.
XX */
XX	if (RECVFLAG)
XX		{
XX#ifndef vms
XX		if (open(argv[2], 0) != -1)	/*  If file exists  */
XX			{
XX			printf("\nUMODEM:  Warning -- Target File Exists\n");
XX			if ( MUNGMODE == FALSE )
XX				error("Fatal - Can't overwrite file\n", FALSE);
XX
XX			printf("UMODEM:  Overwriting Target File\n");
XX			}
XX#endif
XX		rfile(argv[2]);			/*  Receive file  */
XX		}
XX	else
XX		sfile(argv[2]);			/*  Send file  */
XX
XX}
XX
XXgettype(ichar)
XXchar ichar;
XX	{
XX	switch (ichar)
XX		{
XX		case 'b':	case 'B':
XX		case 't':	case 'T':
XX			return(ichar);
XX
XX		default:
XX			error("Invalid Send/Receive Parameter - not t or b",
XX								FALSE);
XX		}
XX
XX	return;
XX	}
XX
XX/* set tty modes for UMODEM transfers */
XXsetmodes()
XX{
XX
XX/*  Device characteristics for JHU UNIX  */
XX#ifdef JHU	
XX	if (gtty(0, &ttys) < 0)  /* get current tty params */
XX		error("Can't get TTY Parameters", TRUE);
XX
XX	tty = ttyname(0);  /* identify current tty */
XX
XX	/* duplicate current modes in ttysnew structure */
XX	ttysnew.ispeed = ttys.ispeed;	/* copy input speed */
XX	ttysnew.ospeed = ttys.ospeed;	/* copy output speed */
XX	ttysnew.xflags = ttys.xflags;	/* copy JHU/UNIX extended flags */
XX	ttysnew.mode   = ttys.mode;	/* copy standard terminal flags */
XX
XX	ttysnew.mode |= RAW;    /* set for RAW Mode */
XX			/* This ORs in the RAW mode value, thereby
XX			   setting RAW mode and leaving the other
XX			   mode settings unchanged */
XX	ttysnew.mode &= ~ECHO;  /* set for no echoing */
XX			/* This ANDs in the complement of the ECHO
XX			   setting (for NO echo), thereby leaving all
XX			   current parameters unchanged and turning
XX			   OFF ECHO only */
XX	ttysnew.mode &= ~XTABS;  /* set for no tab expansion */
XX	ttysnew.mode &= ~LCASE;  /* set for no upper-to-lower case xlate */
XX	ttysnew.mode |= ANYP;  /* set for ANY Parity */
XX	ttysnew.mode &= ~NL3;  /* turn off ALL delays - new line */
XX	ttysnew.mode &= ~TAB3; /* turn off tab delays */
XX	ttysnew.mode &= ~CR3;  /* turn off CR delays */
XX	ttysnew.mode &= ~FF1;  /* turn off FF delays */
XX	ttysnew.mode &= ~BS1;  /* turn off BS delays */
XX	/* the following are JHU/UNIX xflags settings; they are [SD] */
XX	ttysnew.xflags &= ~PAGE;  /* turn off paging */
XX	ttysnew.xflags &= ~STALL;  /* turn off ^S/^Q recognition */
XX	ttysnew.xflags &= ~TAPE;  /* turn off ^S/^Q input control */
XX	ttysnew.xflags &= ~FOLD;  /* turn off CR/LF folding at col 72 */
XX	ttysnew.xflags |= NB8;  /* turn on 8-bit input/output */
XX
XX	if (stty(0, &ttysnew) < 0)  /* set new params */
XX		error("Can't set new TTY Parameters", TRUE);
XX
XX	if (stat(tty, &statbuf) < 0)  /* get tty status */ 
XX		error("Can't get your TTY Status", TRUE);
XX
XX	if (statbuf.st_mode&011)  /* messages are on [SD] */
XX	{	wason = TRUE;
XX		if (chmod(tty, 020600) < 0)  /* turn off tty messages [SD] */
XX			error("Can't change TTY Mode", TRUE);
XX	}	
XX	else
XX		wason = FALSE;  /* messages are already off */
XX#endif		
XX
XX/*  Device characteristics for Version 7 UNIX  */
XX#ifdef VER7
XX	if (ioctl(0,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
XX		error("Can't get TTY Parameters", TRUE);
XX	tty = ttyname(0);  /* identify current tty */
XX	
XX	/* transfer current modes to new structure */
XX	ttysnew.sg_ispeed = ttys.sg_ispeed;	/* copy input speed */
XX	ttysnew.sg_ospeed = ttys.sg_ospeed;	/* copy output speed */
XX	ttysnew.sg_erase  = ttys.sg_erase;	/* copy erase flags */
XX	ttysnew.sg_flags  = ttys.sg_flags;	/* copy flags */
XX 	ttysnew.sg_kill   = ttys.sg_kill;	/* copy std terminal flags */
XX	
XX
XX	ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
XX			/* This ORs in the RAW mode value, thereby
XX			   setting RAW mode and leaving the other
XX			   mode settings unchanged */
XX	ttysnew.sg_flags &= ~ECHO;  /* set for no echoing */
XX			/* This ANDs in the complement of the ECHO
XX			   setting (for NO echo), thereby leaving all
XX			   current parameters unchanged and turning
XX			   OFF ECHO only */
XX	ttysnew.sg_flags &= ~XTABS;  /* set for no tab expansion */
XX	ttysnew.sg_flags &= ~LCASE;  /* set for no upper-to-lower case xlate */
XX	ttysnew.sg_flags |= ANYP;  /* set for ANY Parity */
XX	ttysnew.sg_flags &= ~NL3;  /* turn off ALL delays - new line */
XX	ttysnew.sg_flags &= ~TAB2; /* turn off tab delays */
XX	ttysnew.sg_flags &= ~CR3;  /* turn off CR delays */
XX	ttysnew.sg_flags &= ~FF1;  /* turn off FF delays */
XX	ttysnew.sg_flags &= ~BS1;  /* turn off BS delays */
XX	ttysnew.sg_flags &= ~TANDEM;  /* turn off flow control */
XX
XX	/* make sure page mode is off */
XX/*	ioctl(0,TIOCSSCR,&pagelen);		This is [SD]!  */
XX	
XX	/* set new paramters */
XX	if (ioctl(0,TIOCSETP,&ttysnew) < 0)
XX		error("Can't set new TTY Parameters", TRUE);
XX#endif	
XX
XX/*  Device characteristics for VMS  */
XX#ifdef vms
XX	int	*iptr, parameters;
XX
XX/*
XX *	Get current terminal parameters.
XX */
XX	if (gtty(&ttys) != SS$_NORMAL)
XX		error("SETMODES:  error return from GTTY (1)", FALSE);
XX	if (gtty(&ttysnew) != SS$_NORMAL)
XX		error("SETMODES:  error return from GTTY (2)", FALSE);
XX
XX/*
XX *	Set new terminal parameters.
XX *	Note that there are three bytes of terminal characteristics,
XX *	so we should make sure the fourth byte of the integer is unchanged.
XX */
XX	iptr	= &(ttysnew.dev_characteristics.bcharacteristics);
XX	parameters	= *iptr;
XX
XX	parameters	&= ~TT$M_ESCAPE;		/*  ESCAPE   OFF  */
XX	parameters	&= ~TT$M_HOSTSYNC;		/*  HOSTSYNC OFF  */
XX	parameters	|=  TT$M_NOECHO;		/*  NOECHO   ON   */
XX	parameters	|=  TT$M_PASSALL;		/*  PASSALL  ON   */
XX	parameters	&= ~TT$M_READSYNC;		/*  READSYNC OFF  */
XX	parameters	&= ~TT$M_TTSYNC;		/*  TTSYNC   OFF  */
XX	parameters	&= ~TT$M_WRAP;			/*  WRAP     OFF  */
XX	if (! BIT7)
XX		parameters	|= TT$M_EIGHTBIT;	/*  EIGHTBIT ON  */
XX
XX	*iptr		= parameters;
XX
XX	if (stty(&ttysnew) != SS$_NORMAL)
XX		error("SETMODES:  error return from STTY", TRUE);
XX#endif
XX
XX	if (PMSG)
XX		{ printf("\nUMODEM:  TTY Device Parameters Altered");
XX		  ttyparams();  /* print tty params */
XX		}
XX
XX	if (ARPA)  /* set 8-bit on ARPA Net */
XX		setarpa();
XX
XX	return;
XX}
XX
XX/*  set ARPA Net for 8-bit transfers  */
XXsetarpa()
XX{
XX	sendbyte(IAC);  /* set B O S (Binary Output Start) */
XX	sendbyte(WILL);
XX	sendbyte(TRBIN);
XX
XX	sendbyte(IAC);  /* set B I S (Binary Input Start) */
XX	sendbyte(DO);
XX	sendbyte(TRBIN);
XX
XX	sleep(3);  /* wait for TIP to configure */
XX
XX	return;
XX}
XX
XX/* restore normal tty modes */
XXrestoremodes(errcall)
XXint errcall;
XX{
XX	if (ARPA)  /* if ARPA Net, reconfigure */
XX		resetarpa();
XX
XX/*  Device characteristic restoration for JHU UNIX  */
XX#ifdef JHU
XX	if (wason)  /* if messages were on originally */
XX		if (chmod(tty, 020611) < 0)  /*  [SD]  */
XX			error("Can't change TTY Mode", FALSE);
XX
XX	if (stty(0, &ttys) < 0)  /* restore original tty modes */
XX		{ if (!errcall)
XX		   error("RESET - Can't restore normal TTY Params", FALSE);
XX		else
XX		   { printf("UMODEM:  ");
XX		     printf("RESET - Can't restore normal TTY Params\n");
XX		   }
XX		}
XX#endif
XX
XX/*  Device characteristic restoration for Version 7 UNIX  */
XX#ifdef VER7
XX	if (ioctl(0,TIOCSETP,&ttys) < 0)
XX		{ if (!errcall)
XX		   error("RESET - Can't restore normal TTY Params", FALSE);
XX		else
XX		   { printf("UMODEM:  ");
XX		     printf("RESET - Can't restore normal TTY Params\n");
XX		   }
XX		}
XX#endif
XX
XX/*  Device characteristic restoration for VMS  */
XX#ifdef vms
XX	if (stty(&ttys) != SS$_NORMAL)		/*  Restore original modes  */
XX		{
XX		if (!errcall)
XX			error("Error restoring original terminal params.",
XX									FALSE);
XX		else
XX			{
XX			printf("UMODEM/RESTOREMODES:  ");
XX			printf("Error restoring original terminal params.\n");
XX			}
XX		}
XX#endif
XX
XX	if (PMSG)
XX	
XX	{ printf("\nUMODEM:  TTY Device Parameters Restored");
XX		  ttyparams();  /* print tty params */
XX		}
XX
XX	return;
XX}
XX
XX/* reset the ARPA Net */
XXresetarpa()
XX{
XX	sendbyte(IAC);  /* send B O E (Binary Output End) */
XX	sendbyte(WONT);
XX	sendbyte(TRBIN);
XX
XX	sendbyte(IAC);  /* send B I E (Binary Input End) */
XX	sendbyte(DONT);
XX	sendbyte(TRBIN);
XX
XX	return;
XX}
XX
XX/* print error message and exit; if mode == TRUE, restore normal tty modes */
XXerror(msg, mode)
XXchar *msg;
XXint mode;
XX{
XX	if (mode)
XX		restoremodes(TRUE);  /* put back normal tty modes */
XX	printf("UMODEM:  %s\n", msg);
XX	if (LOGFLAG)
XX	{   fprintf(LOGFP, "UMODEM Fatal Error:  %s\n", msg);
XX	    fclose(LOGFP);
XX	}
XX#ifdef vms
XX	exit(SS$_NORMAL);
XX#else
XX	exit(-1);
XX#endif
XX}
XX
XX/**  print status (size) of a file  **/
XXyfile(name)
XXchar *name;
XX{
XX	printf("UMODEM File Status Display for %s\n", name);
XX	if (LOGFLAG) fprintf(LOGFP,"UMODEM File Status Display for %s\n",
XX	  name);
XX
XX	if (open(name,0) < 0)
XX	{  printf("File %s does not exist\n", name);
XX	   if (LOGFLAG) fprintf(LOGFP,"File %s does not exist\n", name);
XX#ifdef vms
XX	   exit(SS$_NORMAL);
XX#else
XX	   exit(-1);
XX#endif
XX	}
XX
XX	prfilestat(name);  /* print status */
XX	printf("\n");
XX	if (LOGFLAG)
XX	{  fprintf(LOGFP,"\n");
XX	   fclose(LOGFP);
XX	}
XX
XX#ifdef vms
XX	exit(SS$_NORMAL);
XX#else
XX	exit(0);
XX#endif
XX}
XX
XX/**  receive a file  **/
XXrfile(name)
XXchar *name;
XX{
XX	char mode;
XX	int fd, j, firstchar, sectnum, sectcurr, tmode;
XX	int sectcomp, errors, errorflag, recfin;
XX	register int bufctr, checksum;
XX	register int c;
XX	int errorchar, fatalerror, startstx, inchecksum, endetx, endenq;
XX	long recvsectcnt;
XX	int		lowlim, nlflag;
XX#ifdef vms
XX	char		inbuf[BBUFSIZ + 7];
XX#endif
XX
XX	mode = XMITTYPE;  /* set t/b mode */
XX	if ((fd = creat(name, CREATMODE)) < 0)
XX	  	error("Can't create file for receive", FALSE);
XX	printf("\r\nUMODEM:  File Name: %s", name);
XX	if (LOGFLAG)
XX	{    fprintf(LOGFP, "\n----\nUMODEM Receive Function\n");
XX	     fprintf(LOGFP, "File Name: %s\n", name);
XX	     if (FTP1)
XX	        fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
XX	     else
XX		fprintf(LOGFP,
XX		  "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
XX	     if (BIT7)
XX		fprintf(LOGFP, "7-Bit Transmission Enabled\n");
XX	     else
XX		fprintf(LOGFP, "8-Bit Transmission Enabled\n");
XX	}
XX	printf("\r\nUMODEM:  ");
XX	if (BIT7)
XX		printf("7-Bit");
XX	else
XX		printf("8-Bit");
XX	printf(" Transmission Enabled");
XX	printf("\r\nUMODEM:  Ready to RECEIVE File\r\n");
XX
XX	setmodes();  /* setup tty modes for xfer */
XX	recfin = FALSE;
XX	sectnum = errors = 0;
XX	fatalerror = FALSE;  /* NO fatal errors */
XX	recvsectcnt = 0;  /* number of received sectors */
XX
XX	if (mode == 't' || mode == 'T')
XX		tmode	= TRUE;
XX	else
XX		tmode	= FALSE;
XX
XX	if (FTP1)
XX	{
XX	  while (readbyte(4) != SYN);
XX	  sendbyte(ACK);  /* FTP 1 Sync */
XX	}
XX	else sendbyte(NAK);  /* FTP 3 Sync */
XX
XX	nlflag	= FALSE;
XX        do
XX        {   errorflag = FALSE;
XX            do {
XX                  firstchar = readbyte(6);
XX            } while ((firstchar != SOH) && (firstchar != EOT) && (firstchar 
XX		     != TIMEOUT));
XX            if (firstchar == TIMEOUT)
XX	    {  if (LOGFLAG)
XX		fprintf(LOGFP, "Timeout on Sector %d\n", sectnum);
XX               errorflag = TRUE;
XX	    }
XX
XX            if (firstchar == SOH)
XX	       {
XX#ifdef vms
XX/*
XX *	Under VMS, read the whole block at once.
XX */
XX	       if (FTP1)
XX			{
XX			raw_read(BBUFSIZ + 7, inbuf,
XX						5 + delay * (BBUFSIZ + 6));
XX		        sectcurr = inbuf[1] & BITMASK;
XX		        sectcomp = inbuf[2] & BITMASK;
XX			startstx = inbuf[3] & BITMASK;
XX			}
XX	       else
XX			{
XX			raw_read(BBUFSIZ + 3, inbuf, delay * (BBUFSIZ + 3));
XX		        sectcurr = inbuf[0] & BITMASK;
XX		        sectcomp = inbuf[1] & BITMASK;
XX			}
XX
XX#else
XX	       if (FTP1) readbyte(5);  /* discard leading zero */
XX               sectcurr = readbyte(delay);
XX               sectcomp = readbyte(delay);
XX	       if (FTP1) startstx = readbyte(delay);  /* get leading STX */
XX
XX#endif
XX               if ((sectcurr + sectcomp) == BITMASK)
XX               {  if (sectcurr == ((sectnum + 1) % 256) & BITMASK)
XX		  {  checksum = 0;
XX#ifdef vms
XX	      	     if (FTP1)
XX			lowlim	= 4;
XX		     else
XX			lowlim	= 2;
XX#else
XX		     lowlim	= 0;
XX#endif
XX
XX		     bufctr	= 0;
XX		     for (j = lowlim; j < lowlim + BBUFSIZ; j++)
XX			{
XX
XX#ifdef vms
XX	      	        buff[bufctr] = c = inbuf[j] & BITMASK;
XX#else
XX	      	        buff[bufctr] = c = readbyte(delay);
XX#endif
XX
XX		        checksum = (checksum+c)&BITMASK;
XX			if (!tmode)  /* binary mode */
XX			{  bufctr++;
XX		           continue;
XX		        }
XX
XX/*
XX *	Translate CP/M's CR/LF into UNIX's LF, but don't do it by
XX *	simply ignoring a CR from CP/M--it may indicate an
XX *	overstruck line!
XX */
XX			if (nlflag)
XX				{
XX/*
XX *	Last packet ended with a CR.  If the first character of this
XX *	packet ISN'T a LF, then be sure to send the CR.
XX */
XX				nlflag	= FALSE;
XX				if (c != LF)
XX					{
XX					buff[bufctr++]	= CR;
XX					buff[bufctr]	= c;
XX					}
XX				}
XX			if (j == lowlim + BBUFSIZ - 1 && c == CR)
XX				{
XX/*
XX *	Last character in the packet is a CR.  Don't send it, but
XX *	turn on NLFLAG to make sure we check the first character in
XX *	the next packet to see if it's a LF.
XX */
XX				nlflag	= TRUE;
XX				continue;
XX				}
XX			if (c == LF && bufctr && buff[bufctr - 1] == CR)
XX				{
XX/*
XX *	We have a CR/LF pair.  Discard the CR.
XX */
XX				buff[bufctr - 1]	= LF;
XX				continue;
XX				}
XX			if (c == CTRLZ)  /* skip CP/M EOF char */
XX			{  recfin = TRUE;  /* flag EOF */
XX		           continue;
XX		        }
XX		        if (!recfin)
XX	
XX		   bufctr++;
XX		     }
XX
XX#ifdef vms
XX		     if (FTP1)
XX			{
XX/*  Ending ETX  */	endetx		= inbuf[lowlim + BBUFSIZ] & BITMASK;
XX/*  Checksum  */	inchecksum	= inbuf[lowlim + BBUFSIZ + 1] & BITMASK;
XX/*  ENQ  */		endenq		= inbuf[lowlim + BBUFSIZ + 2] & BITMASK;
XX			}
XX		     else
XX/*  Checksum  */	inchecksum	= inbuf[lowlim + BBUFSIZ] & BITMASK;
XX			
XX#else
XX		     if (FTP1) endetx = readbyte(delay);  /* get ending ETX */
XX		     inchecksum = readbyte(delay);  /* get checksum */
XX		     if (FTP1) endenq = readbyte(delay); /* get ENQ */
XX#endif
XX
XX		     if (checksum == inchecksum)  /* good checksum */
XX		     {  errors = 0;
XX			recvsectcnt++;
XX		        sectnum = sectcurr;  /* update sector counter */
XX			if (write(fd, buff, bufctr) < 0)
XX			   error("File Write Error", TRUE);
XX		        else
XX			{  if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
XX			   sendbyte(ACK);
XX			}
XX		     }
XX		     else
XX		     {  if (LOGFLAG)
XX				fprintf(LOGFP, "Checksum Error on Sector %d\n",
XX				sectnum);
XX		        errorflag = TRUE;
XX		     }
XX                  }
XX                  else
XX                  { if (sectcurr == (sectnum % 256) & BITMASK)
XX                    {  while(readbyte(3) != TIMEOUT);
XX		       if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
XX            	       sendbyte(ACK);
XX                    }
XX                    else
XX		    {  if (LOGFLAG)
XX			{ fprintf(LOGFP, "Phase Error--received sector is %d ",
XX					sectcurr);
XX			  fprintf(LOGFP, "while expected sector is %d (%d)\n",
XX					((sectnum + 1) % 256) & BITMASK,
XX					sectnum);
XX			}
XX			errorflag = TRUE;
XX			fatalerror = TRUE;
XX			if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
XX			sendbyte(CAN);
XX		    }
XX	          }
XX           }
XX           else
XX	   {  if (LOGFLAG)
XX		fprintf(LOGFP, "Header Sector Number Error on Sector %d\n",
XX		   sectnum);
XX               errorflag = TRUE;
XX	   }
XX        }
XX	if (FTP1 && !errorflag)
XX	{  if (startstx != STX)
XX	   {  errorflag = TRUE;  /* FTP 1 STX missing */
XX	      errorchar = STX;
XX	   }
XX	   if (endetx != ETX)
XX	   {  errorflag = TRUE;  /* FTP 1 ETX missing */
XX	      errorchar = ETX;
XX	   }
XX	   if (endenq != ENQ)
XX	   {  errorflag = TRUE;  /* FTP 1 ENQ missing */
XX	      errorchar = ENQ;
XX	   }
XX	   if (errorflag && LOGFLAG)
XX	   {  fprintf(LOGFP, "Invalid Packet-Control Character:  ");
XX	      switch (errorchar) {
XX		case STX : fprintf(LOGFP, "STX"); break;
XX		case ETX : fprintf(LOGFP, "ETX"); break;
XX		case ENQ : fprintf(LOGFP, "ENQ"); break;
XX		default  : fprintf(LOGFP, "Error"); break;
XX	      }
XX	      fprintf(LOGFP, "\n");
XX	   }
XX	}
XX        if (errorflag == TRUE)
XX        {  errors++;
XX	   while (readbyte(3) != TIMEOUT);
XX           sendbyte(NAK);
XX        }
XX  }
XX  while ((firstchar != EOT) && (errors != ERRORMAX) && !fatalerror);
XX  if ((firstchar == EOT) && (errors < ERRORMAX))
XX  {  if (!FTP1) sendbyte(ACK);
XX     close(fd);
XX     restoremodes(FALSE);  /* restore normal tty modes */
XX     if (FTP1)
XX	while (readbyte(3) != TIMEOUT);  /* flush EOT's */
XX     sleep(3);  /* give other side time to return to terminal mode */
XX     if (LOGFLAG)
XX     {  fprintf(LOGFP, "\nReceive Complete\n");
XX	fprintf(LOGFP,"Number of Received CP/M Records is %ld\n", recvsectcnt);
XX        fclose(LOGFP);
XX     }
XX     printf("\n");
XX#ifdef vms
XX     exit(SS$_NORMAL);
XX#else
XX     exit(0);
XX#endif
XX  }
XX  else
XX  {  if (LOGFLAG && FTP1 && fatalerror) fprintf(LOGFP,
XX	"Synchronization Error");
XX     if (errors == ERRORMAX)
XX	     error("Too many errors", TRUE);
XX     if (fatalerror)
XX	     error("Fatal error", TRUE);
XX  }
XX}
XX
XX/**  send a file  **/
XXsfile(name)
XXchar *name;
XX{
XX	char mode;
XX	int fd, charval, attempts;
XX	int nlflag, sendfin, tmode;
XX	register int bufctr, checksum, sectnum;
XX	char c;
XX	int sendresp;  /* response char to sent block */
XX
XX	mode = XMITTYPE;  /* set t/b mode */
XX	if ((fd = open(name, 0)) < 0)
XX	{  if (LOGFLAG) fprintf(LOGFP, "Can't Open File\n");
XX     	   error("Can't open file for send", FALSE);
XX	}
XX	printf("\r\nUMODEM:  File Name: %s", name);
XX	if (LOGFLAG)
XX	{   fprintf(LOGFP, "\n----\nUMODEM Send Function\n");
XX	    fprintf(LOGFP, "File Name: %s\n", name);
XX	}
XX	prfilestat(name);  /* print file size statistics */
XX	if (LOGFLAG)
XX	{  if (FTP1)
XX		fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
XX	   else
XX		fprintf(LOGFP,
XX		   "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
XX	   if (BIT7)
XX		fprintf(LOGFP, "7-Bit Transmission Enabled\n");
XX	   else
XX		fprintf(LOGFP, "8-Bit Transmission Enabled\n");
XX	}
XX	printf("\r\nUMODEM:  ");
XX	if (BIT7)
XX		printf("7-Bit");
XX	else
XX		printf("8-Bit");
XX	printf(" Transmission Enabled");
XX	printf("\r\nUMODEM:  Ready to SEND File\r\n");
XX
XX	setmodes();  /* setup tty modes for xfer */	
XX	if (mode == 't' || mode == 'T')
XX		tmode	= TRUE;
XX	else
XX		tmode	= FALSE;
XX
XX        sendfin = nlflag = FALSE;
XX  	attempts = 0;
XX
XX	if (FTP1)
XX	{  sendbyte(SYN);  /* FTP 1 Synchronize with Receiver */
XX	   while (readbyte(5) != ACK)
XX	   {  if(++attempts > RETRYMAX*6) error("Remote System Not Responding",
XX		TRUE);
XX	      sendbyte(SYN);
XX	   }
XX	}
XX	else
XX	{  while (readbyte(30) != NAK)  /* FTP 3 Synchronize with Receiver */
XX	   if (++attempts > RETRYMAX) error("Remote System Not Responding",
XX		TRUE);
XX	}
XX
XX	sectnum = 1;  /* first sector number */
XX	attempts = 0;
XX
XX        do 
XX	{   for (bufctr=0; bufctr < BBUFSIZ;)
XX	    {   if (nlflag)
XX	        {  buff[bufctr++] = LF;  /* leftover newline */
XX	           nlflag = FALSE;
XX	        }
XX	        if ((charval = read(fd, &c, 1)) < 0)
XX		   error("File Read Error", TRUE);
XX		if (charval == 0)  /* EOF for read */	
XX		{  sendfin = TRUE;  /* this is the last sector */
XX		   if (tmode)
XX		      buff[bufctr++] = CTRLZ;  /* Control-Z for CP/M EOF */
XX	           else
XX		      bufctr++;
XX		   continue;
XX	        }
XX		if (tmode && c == LF)  /* text mode & Unix newline? */
XX	    	{  if (c == LF)  /* Unix newline? */
XX		   {  buff[bufctr++] = CR;  /* insert carriage return */
XX		      if (bufctr < BBUFSIZ)
XX	                 buff[bufctr++] = LF;  /* insert Unix newline */
XX	 	      else
XX		         nlflag = TRUE;  /* insert newline on next sector */
XX		   }
XX		   continue;
XX	   	}	
XX		buff[bufctr++] = c;  /* copy the char without change */
XX	    }
XX            attempts = 0;
XX            do
XX            {   sendbyte(SOH);  /* send start of packet header */
XX		if (FTP1) sendbyte(0);  /* FTP 1 Type 0 Packet */
XX                sendbyte(sectnum);       /* send current sector number */
XX		sendbyte(-sectnum-1);    /* and its complement */
XX
XX		if (FTP1) sendbyte(STX);  /* send STX */
XX                checksum = 0;  /* init checksum */
XX                for (bufctr=0; bufctr < BBUFSIZ; bufctr++)
XX                {  sendbyte(buff[bufctr]);  /* send the byte */
XX		   if (ARPA && (buff[bufctr]==0xff))  /* ARPA Net FFH esc */
XX			sendbyte(buff[bufctr]);  /* send 2 FFH's for one */
XX                   checksum = (checksum+buff[bufctr])&BITMASK;
XX	        }
XX/*		while (readbyte(3) != TIMEOUT);   flush chars from line */
XX		if (FTP1) sendbyte(ETX);  /* send ETX */
XX                sendbyte(checksum);  /* send the checksum */
XX		if (FTP1) sendbyte(ENQ);  /* send ENQ */
XX                attempts++;
XX		if (FTP1)
XX		{  sendresp = NAK;  /* prepare for NAK */
XX		   if (readbyte(10) == ESC) sendresp = readbyte(10);
XX		}
XX		else
XX		   sendresp = readbyte(10);  /* get response */
XX		if ((sendresp != ACK) && LOGFLAG)
XX		   { fprintf(LOGFP, "Non-ACK Received on Sector %d\n",
XX		      sectnum);
XX		     if (sendresp == TIMEOUT)
XX			fprintf(LOGFP, "This non-ACK was a TIMEOUT\n");
XX		     else if (sendresp == NAK)
XX			fprintf(LOGFP, "This non-ACK was a NAK\n");
XX		   }
XX		if (sendresp == CAN)
XX			{
XX			if (LOGFLAG)
XX				fprintf(LOGFP, "This non-ACK was a CAN\n");
XX
XX#ifdef CAN_BOMB
XX			if (LOGFLAG)
XX				fprintf(LOGFP,
XX					"Exiting:  got a CAN from receiver.\n");
XX			close(fd);
XX			restoremodes(TRUE);
XX			sleep(5);	/*  Allow other side to recover  */
XX			printf("Exiting:  got a CAN from receiver.\n\n");
XX#ifdef vms
XX			exit(SS$_NORMAL);
XX#else
XX			exit(-1);
XX#endif
XX
XX#endif
XX			}
XX            }   while((sendresp != ACK) && (attempts != RETRYMAX));
XX            sectnum++;  /* increment to next sector number */
XX    }  while (!sendfin && (attempts != RETRYMAX));
XX
XX    if (attempts == RETRYMAX)
XX	error("Remote System Not Responding", TRUE);
XX
XX    attempts = 0;
XX    if (FTP1)
XX	while (attempts++ < 10) sendbyte(EOT);
XX    else
XX    {	sendbyte(EOT);  /* send 1st EOT */
XX	while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX))
XX	   sendbyte(EOT);
XX	if (attempts >= RETRYMAX)
XX	   error("Remote System Not Responding on Completion", TRUE);
XX    }
XX
XX    close(fd);
XX    restoremodes(FALSE);  
XX    sleep(5);  /* give other side time to return to terminal mode */
XX    if (LOGFLAG)
XX    {  fprintf(LOGFP, "\nSend Complete\n");
XX       fclose(LOGFP);
XX    }
XX    printf("\n");
XX#ifdef vms
XX    exit(SS$_NORMAL);
XX#else
XX    exit(0);
XX#endif
XX
XX}
XX
XX/*  print file size status information  */
XXprfilestat(name)
XXchar *name;
XX{
XX	long		bytes, Kbytes, records;
XX
XX#ifdef vms
XX	bytes		= filestat(name);	/*  Gets file length  */
XX	if (bytes < 0)
XX		{
XX		printf("PRFILESTAT:  error return from FILESTAT\n");
XX		return;
XX		}
XX
XX#else
XX	struct stat	filestatbuf;		/*  File status info  */
XX
XX	stat(name, &filestatbuf);		/*  Get file status bytes  */
XX	bytes		= filestatbuf.st_size;
XX#endif
XX
XX	Kbytes		= (bytes / 1024) + 1;
XX	records		= (bytes /  128) + 1;
XX
XX	printf("\nUMODEM:  Estimated File Size %ldK, %ld Records, %ld Bytes",
XX				Kbytes, records, bytes);
XX	printf("\n         Estimated transfer time at 300 baud:  ");
XX	printf("%ld min, %ld sec.",
XX				bytes / (30*60), ((bytes % (30*60)) / 30) + 1);
XX
XX	if (LOGFLAG)
XX		fprintf(LOGFP,
XX			"Estimated File Size %ldK, %ld Records, %ld Bytes\n",
XX				Kbytes, records, bytes);
XX
XX	return;
XX}
XX
XX/* get a byte from data stream -- timeout if "seconds" elapses */
XX/*	NOTE, however, that this function returns an INT, not a BYTE!!!  */
XXreadbyte(seconds)
XXunsigned	seconds;
XX	{
XX	int	c;
XX
XX#ifdef vms
XX	c	= raw_read(1, &c, seconds);
XX
XX	if (c == SS$_TIMEOUT)
XX		return(TIMEOUT);
XX
XX#else
XX	int	alarmfunc();
XX	
XX	signal(SIGALRM,alarmfunc);  /* catch alarms */	
XX	alarm(seconds);  /* set the alarm clock */
XX
XX	if (read(0, &c, 1) < 0)     /* get a char; error means we timed out */
XX	  {
XX	     return(TIMEOUT);
XX	  }
XX	alarm(0);  /* turn off the alarm */
XX
XX#endif
XX
XX	return(c & BITMASK);  /* return the char */
XX	}
XX
XX/* send a byte to data stream */
XXsendbyte(data)
XXchar	data;
XX	{
XX	char	dataout;
XX
XX	dataout	= data & BITMASK;		/*  Mask for 7 or 8 bits  */
XX
XX#ifdef vms
XX	raw_write(dataout);
XX
XX#else
XX	write(1, &dataout, 1);  /* write the byte */
XX
XX#endif
XX
XX	return;
XX	}
XX
XX#ifndef vms
XX/* function for alarm clock timeouts */
XXalarmfunc()
XX{
XX	return;  /* this is basically a dummy function to force error */
XX		 /* status return on the "read" call in "readbyte"    */
XX}
XX#endif
XX
XX/* print data on TTY setting */
XXttyparams()
XX{
XX
XX/*  For VMS, report that no information is available and return  */
XX#ifdef vms
XX	printf("\nUMODEM/TTYPARAMS:  ");
XX	printf("TT device parameter display not implemented under VMS.\n");
XX
XX#else
XX
XX/*  Obtain TTY parameters for JHU UNIX  */
XX#ifdef JHU	
XX	gtty(0, &ttystemp);  /* get current tty params */
XX#endif
XX
XX/*  Obtain TTY parameters for Version 7 UNIX  */
XX#ifdef VER7
XX	ioctl(0,TIOCGETP,&ttystemp);
XX#endif
XX
XX	printf("\r\n\nTTY Device Parameter Display\r\n");
XX
XX	tty = ttyname(0);  /* get name of tty */
XX	  printf("\tTTY Device Name is %s\r\n\n", tty);
XX	  printf("\tAny Parity Allowed "); pryn(ANYP);
XX	  printf("\tEven Parity Allowed"); pryn(EVENP);
XX	  printf("\tOdd Parity Allowed "); pryn(ODDP);
XX	  printf("\tLower Case Map     "); pryn(LCASE);
XX	  printf("\tTabs Expanded      "); pryn(XTABS);
XX	  printf("\tCR Mode Enabled    "); pryn(CRMOD);
XX	  printf("\tEcho Enabled       "); pryn(ECHO);
XX	  printf("\tRAW Mode Enabled   "); pryn(RAW);
XX
XX/*  Print extended terminal characteristics for JHU UNIX  */
XX#ifdef JHU
XX	stat(tty, &statbuf);  /* get more tty params */
XX
XX	  printf("\tBinary Mode Enabled"); pryn1(NB8);
XX	  printf("\tCR/LF in Col 72    "); pryn1(FOLD);
XX	  printf("\tRecognize ^S/^Q    "); pryn1(STALL);
XX	  printf("\tSend ^S/^Q         "); pryn1(TAPE);
XX	  printf("\tTerminal can BS    "); pryn1(SCOPE);
XX	  printf("\r\n");  /* New line to separate topics */
XX	  printf("\tTerminal Paging is "); pryn1(PAGE);
XX	    if (ttystemp.xflags&PAGE)
XX		printf("\t  Lines/Page is %d\r\n", ttystemp.xflags&PAGE);
XX	  printf("\r\n");  /* New line to separate topics */
XX	  printf("\tTTY Input Rate     :   ");
XX	    prbaud(ttystemp.ispeed);  /* print baud rate */
XX	  printf("\tTTY Output Rate    :   ");
XX	    prbaud(ttystemp.ospeed);  /* print output baud rate */
XX	  printf("\r\n");  /* New line to separate topics */
XX	  printf("\tMessages Enabled   ");
XX		if (statbuf.st_mode&011)
XX		   printf(":   Yes\r\n");
XX		else
XX		   printf(":   No\r\n");
XX#endif
XX
XX/*  Print extended characteristics for Version 7 UNIX  */
XX#ifdef VER7
XX	  printf("\tTTY Input Rate     :   ");
XX	    prbaud(ttystemp.sg_ispeed);
XX	  printf("\tTTY Output Rate    :   ");
XX	    prbaud(ttystemp.sg_ospeed);  /* print output baud rate */
XX#endif
XX
XX#endif					/*  END #ifdef vms...#else...  */
XX}
XX
XX#ifndef vms
XXpryn(iflag)
XXint iflag;
XX{
XX
XX/*  JHU UNIX flag test  */
XX#ifdef JHU
XX	if (ttystemp.mode&iflag)
XX
XX/*  Version 7 UNIX and VMS flag test  */
XX#else
XX	if (ttystemp.sg_flags&iflag)
XX#endif
XX
XX	   printf(":   Yes\r\n");
XX	else
XX	   printf(":   No\r\n");
XX}
XX#endif
XX
XX/*  Extended flag test for JHU UNIX only  */
XX#ifdef JHU
XXpryn1(iflag)
XXint iflag;
XX{
XX	if (ttystemp.xflags&iflag)
XX	   printf(":   Yes\r\n");
XX	else
XX	   printf(":   No\r\n");
XX}
XX#endif
XX
XX#ifndef vms
XXprbaud(speed)
XXchar speed;
XX{
XX	switch (speed) {
XX
XX/*  JHU UNIX speed flag cases  */
XX#ifdef JHU		
XX		case B0050 : printf("50"); break;
XX		case B0075 : printf("75"); break;
XX		case B0110 : printf("110"); break;
XX		case B0134 : printf("134.5"); break;
XX		case B0150 : printf("150"); break;
XX		case B0200 : printf("200"); break;
XX		case B0300 : printf("300"); break;
XX		case B0600 : printf("600"); break;
XX		case B1200 : printf("1200"); break;
XX		case B1800 : printf("1800"); break;
XX		case B2400 : printf("2400"); break;
XX	
XX	case B4800 : printf("4800"); break;
XX		case B9600 : printf("9600"); break;
XX		case EXT_A : printf("External A"); break;
XX		case EXT_B : printf("External B"); break;
XX#endif
XX
XX/*  Version 7 UNIX speed flag cases  */
XX#ifdef VER7
XX		case B50 : printf("50"); break;
XX		case B75 : printf("75"); break;
XX		case B110 : printf("110"); break;
XX		case B134 : printf("134.5"); break;
XX		case B150 : printf("150"); break;
XX		case B200 : printf("200"); break;
XX		case B300 : printf("300"); break;
XX		case B600 : printf("600"); break;
XX		case B1200 : printf("1200"); break;
XX		case B1800 : printf("1800"); break;
XX		case B2400 : printf("2400"); break;
XX		case B4800 : printf("4800"); break;
XX		case B9600 : printf("9600"); break;
XX		case EXTA : printf("External A"); break;
XX		case EXTB : printf("External B"); break;
XX#endif
XX
XX		default    : printf("Error"); break;
XX	}
XX	printf(" Baud\r\n");
XX}
XX#endif
SHAR_EOF
if test 38796 -ne "`wc -c umodem.c`"
then
echo shar: error transmitting umodem.c '(should have been 38796 characters)'
fi
echo shar: extracting vmodem.c
sed 's/^XX//' << \SHAR_EOF > vmodem.c
XX/*
XX *  VMODEM
XX *  VMS support for UMODEM program
XX *
XX *	Defined herein are some utility routines to make the UNIX
XX *	program UMODEM run under VAX/VMS C:
XX *
XX *		ASSIGN_CHANNEL	Calls the VMS System Service $ASSIGN
XX *				to assign a channel to a device.
XX *				The routine currently has the device
XX *				"TT" hardwired into it.
XX *		GTTY		Gets terminal characteristics, almost
XX *				like the UNIX GTTY system call.
XX *		FILESTAT	Provide FILE STATistics under VMS:
XX *				calls RMS to find out the length of
XX *				the file specified in the argument.
XX *		RAW_READ	Reads characters from the terminal
XX *				without any echoing or interpretation
XX *				and with an optional timeout period.
XX *		RAW_WRITE	Writes a character to the terminal
XX *				without any interpretation.
XX *		STTY		Sets terminal characteristics, almost
XX *				like the UNIX STTY system call.
XX *
XX *	Some of the ideas used here were obtained from code written
XX *	by Max Benson and Robert Bruccoleri.
XX *
XX *  Walter Reiher
XX *  Harvard University
XX *  Department of Chemistry
XX *  12 Oxford Street
XX *  Cambridge, MA 02138
XX *  March 11, 1983
XX */
XX#include descrip
XX#include iodef
XX#include rms
XX#include ssdef
XX#include stdio
XX#include "vmodem.h"
XX
XX#define  TRUE	1
XX#define  FALSE	0
XX
XXstatic char	tt_name[]	= "TT";
XXstatic short	tt_chan		= -1;		/*  Terminal channel number  */
XX
XXstruct	tt_io_iosb				/*  Terminal I/O IOSB  */
XX		{
XX		short	status;
XX		short	byte_count;
XX		short	terminator;
XX		short	terminator_size;
XX		};
XX
XX/*
XX *	Terminator mask for PASSALL reads.
XX *	Permits reads of all possible 8-bit characters.
XX */
XXint	t_mask[32]	=  {	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
XX				 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
XX				 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
XX				 0,  0					};
XXstruct	terminator_mask
XX		{
XX		short	size ;
XX		short	unused ;
XX		int	*mask ;
XX		}
XX		termin_mask	= { 32, 0, t_mask };
XX/*
XX */
XXassign_channel()
XX	{
XX/*
XX *	ASSIGN a channel to the logical name TT, which is usually
XX *	the terminal.
XX */
XX	int	status;
XX	$DESCRIPTOR(tt_descriptor, tt_name);
XX
XX	if (tt_chan == -1)
XX		status	= sys$assign(&tt_descriptor, &tt_chan, 0, 0);
XX	else
XX		status	= SS$_NORMAL;
XX
XX	if (status != SS$_NORMAL || tt_chan == -1)
XX		error("ASSIGN_CHANNEL:  error in SYS$ASSIGN\n", FALSE);
XX
XX	return;
XX	}
XX
XXgtty(tt_characteristics)
XXstruct	tt_info	*tt_characteristics;
XX	{
XX/*
XX *	Gets terminal information from VMS.
XX */
XX	int				status;
XX
XX	if (tt_chan == -1)
XX		assign_channel();
XX
XX	status	= sys$qiow(0, tt_chan, IO$_SENSEMODE,
XX			&(tt_characteristics->dev_modes), NULL, 0,
XX			&(tt_characteristics->dev_characteristics), 12,
XX			0, 0, 0, 0);
XX	if (status != SS$_NORMAL ||
XX			tt_characteristics->dev_modes.status != SS$_NORMAL)
XX		error("GTTY:  sense mode QIO error return.\n", FALSE);
XX
XX	return(status);
XX	}
XX
XX/*
XX *  FILESTAT
XX *  Provide FILE STATistics under VMS
XX *
XX *	Calls RMS (ugh!) to find out something about the file whose
XX *	name is pointed to in the argument FILENAME.
XX *	Returns the number of bytes in the file, returns -1 on error.
XX */
XXlong	filestat(name)
XXchar	*name;
XX	{
XX	short		lastbyte;
XX	long		blocks, bytes;
XX	int		status;
XX	struct	FAB	fab;
XX	struct	XABFHC	xabfhc;
XX
XX	fab		= cc$rms_fab;
XX	xabfhc		= cc$rms_xabfhc;
XX
XX	fab.fab$l_xab	= &xabfhc;
XX	fab.fab$l_fna	= name;
XX	fab.fab$b_fns	= strlen(name);
XX
XX	status	= sys$open(&fab);
XX	if (status != RMS$_NORMAL && status != RMS$_KFF)
XX		{
XX		if (status == RMS$_FNF)
XX			printf("FILESTAT:  File %s not found.\n", name);
XX		else
XX			{
XX			printf("FILESTAT:  Error in $OPEN of ");
XX			printf("file %s, status = 0x%X\n", name, status);
XX			}
XX		return(-1);
XX		}
XX
XX/*
XX *	Pull out the end-of-file block and the first free byte in the
XX *	end-of-file block from the XAB.
XX */
XX	blocks		= fab.fab$l_xab->xab$l_ebk - 1;
XX	lastbyte	= fab.fab$l_xab->xab$w_ffb - 1;
XX
XX	bytes	= blocks * 512 + lastbyte;
XX
XX	status	= sys$close(&fab);
XX	if (status != RMS$_NORMAL)
XX		{
XX		printf("FILESTAT:  Error in $CLOSE of ");
XX		printf("file %s, status = 0x%X\n", name, status);
XX		return(-1);
XX		}
XX
XX	return(bytes);
XX	}
XX
XXint		raw_read(nchar, charbuf, seconds)
XXchar		*charbuf;
XXint		nchar;
XXunsigned	seconds;
XX	{
XX/*
XX *	Read NCHAR characters from the terminal without echoing or
XX *	interpretation.
XX *	If the argument SECONDS is non-zero, use that as the
XX *	timeout period in seconds for the read.
XX *
XX *	NOTE THAT THIS FUNCTION RETURNS AN INT, NOT A CHAR!
XX *	That is because of the possibility of a SS$_TIMEOUT return.
XX */
XX	short			function;
XX	int			status;
XX	struct	tt_io_iosb	iosb;
XX
XX	if (tt_chan == -1)
XX		assign_channel();
XX
XX	function	= IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR;
XX
XX	if (seconds)
XX		status	= sys$qiow(0, tt_chan, function | IO$M_TIMED,
XX				&iosb, NULL, 0,
XX				charbuf, nchar, seconds,
XX				&termin_mask, NULL, 0);
XX	else
XX		status	= sys$qiow(0, tt_chan, function,
XX				&iosb, NULL, 0,
XX				charbuf, nchar, 0,
XX				&termin_mask, NULL, 0);
XX
XX	if (status == SS$_TIMEOUT || iosb.status == SS$_TIMEOUT)
XX		return(SS$_TIMEOUT);
XX	else if (status != SS$_NORMAL || iosb.status != SS$_NORMAL)
XX		error("RAW_READ:  read QIO error return.\n", TRUE);
XX
XX	return((int)*charbuf);
XX	}
XX
XXraw_write(c)
XXchar	c;
XX	{
XX/*
XX *	Writes a character to the terminal without echoing or
XX *	interpretation.
XX */
XX	int			status;
XX	struct	tt_io_iosb	iosb;
XX
XX	if (tt_chan == -1)
XX		assign_channel();
XX
XX	status	= sys$qiow(0, tt_chan,
XX			IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT,
XX			&iosb, NULL, 0,
XX			&c, 1, 0, 0, 0, 0);
XX
XX	if (status != SS$_NORMAL || iosb.status != SS$_NORMAL)
XX		error("RAW_WRITE:  write QIO error return.\n", TRUE);
XX
XX	return;
XX	}
XX
XXstty(tt_characteristics)
XXstruct	tt_info	*tt_characteristics;
XX	{
XX/*
XX *	Sets terminal information from VMS.
XX */
XX	short			*f_ptr, *p_ptr, *s_ptr;
XX	int			status;
XX	struct	tt_mode_iosb	iosb;
XX
XX	if (tt_chan == -1)
XX		assign_channel();
XX
XX/*
XX *	We do the following in order to get a full short, concatenating
XX *	two adjacent chars:
XX */
XX	s_ptr	= &(tt_characteristics->dev_modes.t_speed);	/*  Speeds  */
XX	f_ptr	= &(tt_characteristics->dev_modes.CR_fill);	/*  Fills  */
XX	p_ptr	= &(tt_characteristics->dev_modes.parity_flags);
XX
XX	status	= sys$qiow(0, tt_chan, IO$_SETMODE,
XX			&iosb, NULL, 0,
XX			&(tt_characteristics->dev_characteristics), 12,
XX			*s_ptr, *f_ptr, *p_ptr, 0);
XX	if (status != SS$_NORMAL || iosb.status != SS$_NORMAL)
XX		printf(stderr, "STTY:  set mode QIO error return.\n");
XX
XX	return(status);
XX	}
SHAR_EOF
if test 6448 -ne "`wc -c vmodem.c`"
then
echo shar: error transmitting vmodem.c '(should have been 6448 characters)'
fi
echo shar: extracting vmodem.h
sed 's/^XX//' << \SHAR_EOF > vmodem.h
XX/*
XX *  VMODEM.H
XX *  VMS support for UMODEM program
XX *
XX *	#INCLUDE files defining structures associated with terminal
XX *	information structure TT_INFO.
XX *	Information about the terminal is passed around in UMODEM in a
XX *	STRUCT TT_INFO.
XX *
XX *  Walter Reiher
XX *  Harvard University
XX *  Department of Chemistry
XX *  12 Oxford Street
XX *  Cambridge, MA 02138
XX *  March 10, 1983
XX */
XX
XXstruct	tt_mode				/*  Info for a IO$_SETMODE call  */
XX		{
XX		char			class;
XX		char			type;
XX		short			page_width;
XX		char			bcharacteristics[3];
XX		char			page_length;
XX		int			echaracteristics;
XX		};
XX
XXstruct	tt_mode_iosb			/*  Terminal IO$_SENSEMODE IOSB  */
XX		{
XX		short			status;
XX		char			t_speed;
XX		char			r_speed;
XX		char			CR_fill;
XX		char			LF_fill;
XX		char			parity_flags;
XX		char			unused2;
XX		};
XX
XXstruct	tt_info				/*  Summary of terminal infomation  */
XX		{
XX		struct	tt_mode		dev_characteristics;
XX		struct	tt_mode_iosb	dev_modes;
XX		};
SHAR_EOF
if test 952 -ne "`wc -c vmodem.h`"
then
echo shar: error transmitting vmodem.h '(should have been 952 characters)'
fi
#	End of shell archive
exit 0
