[comp.sources.d] missing xmodem files

andrews@hpcupt1.HP.COM (Edward E. Andrews) (03/25/88)

/*
 *  XMODEM -- Implements the Christensen XMODEM protocol, 
 *            for packetized file up/downloading.    
 *
 *	I have tried to keep the 4.2isms (select system call, 4.2BSD/v7 tty
 *	structures, gettimeofday system call, etc.) in the source file
 *	getput.c; but I make no guarantees.  Also, I have made no attempt to
 *	keep variable names under 7 characters (although a cursory check
 *	shows that all variables are unique within 7 first characters).
 *	See the README file for some notes on SYS V adaptations.
 *	The program has been successfully run on VAXes (4.3BSD) and SUN-3s
 *	(2.x/3.x) against MEX-PC and ZCOMM/DSZ.
 *
 *   -- Based on UMODEM 3.5 by Lauren Weinstein, Richard Conn, and others.
 *
 *  XMODEM Version 1.0  - by Brian Kantor, UCSD (3/84)
 *
 *  Version 2.0 (CRC-16 and Modem7 batch file transfer) -- Steve Grandi, NOAO (5/85)
 *
 *  Version 2.1 (1K packets) -- Steve Grandi, NOAO (7/85)
 *
 *  Version 2.2 (general clean-ups and multi-character read speed-ups) -- Steve Grandi, NOAO (9/85)
 *
 *  Version 2.3 (napping while reading packet; split into several source files) -- Steve Grandi, NOAO (1/86)
 *
 *  Version 3.0 (Ymodem batch receive; associated changes) -- Steve Grandi, NOAO (2/86)
 *
 *  Version 3.1 (Ymodem batch send; associated changes) -- Steve Grandi, NOAO (8/86)
 *
 *  Version 3.2 (general cleanups) -- Steve Grandi, NOAO (9/86)
 *
 *  Released to the world (1/87)
 *
 *  Version 3.3 (see update.doc) -- Steve Grandi, NOAO (5/87)
 *
 *  Version 3.4 (see update.doc) -- Steve Grandi, NOAO (10/87)
 *
 *  Released to the world (1/88)
 *
 *  Please send bug fixes, additions and comments to:
 *	{ihnp4,hao}!noao!grandi   grandi@noao.arizona.edu
 */

#include "xmodem.h"

main(argc, argv)
int argc;
char **argv;
{
	char *getenv();
	FILE *fopen();
	char *unix_cpm();
	char *strcpy();
	char *strcat();
	
	char *fname = filename;		/* convenient place to stash file names */
	char *logfile = "xmodem.log";	/* Name of LOG File */
	
	char *stamptime();		/* for timestamp */

	char *defname = "xmodem.in";	/* default file name if none given */

	struct stat filestatbuf;	/* file status info */

	int index;
	char flag;
	long expsect;

	/* initialize option flags */

	XMITTYPE = 't';		/* assume text transfer */
	DEBUG = FALSE;		/* keep debugging info in log */
	RECVFLAG = FALSE;	/* not receive */
	SENDFLAG = FALSE;	/* not send either */
	BATCH = FALSE;		/* nor batch */
	CRCMODE = FALSE;	/* use checksums for now */
	DELFLAG = FALSE;	/* don't delete old log file */
	LOGFLAG = TRUE;		/* keep log */
	LONGPACK = FALSE; 	/* do not use long packets on transmit */
	MDM7BAT = FALSE;	/* no MODEM7 batch mode */
	YMDMBAT = FALSE;	/* no YMODEM batch mode */
	TOOBUSY = FALSE;	/* not too busy for sleeping in packet read */

	printf("XMODEM Version %d.%d", VERSION/10, VERSION%10);
	printf(" -- UNIX-Microcomputer Remote File Transfer Facility\n");

	if (argc == 1)
		{
		help();
		exit(-1);
		}

	index = 0;		/* set index for flag loop */

	while ((flag = argv[1][index++]) != '\0')
	    switch (flag) {
		case '-' : break;
		case 'X' :
		case 'x' : DEBUG = TRUE;  /* turn on debugging log */
			   break;
		case 'C' :
		case 'c' : CRCMODE = TRUE; /* enable CRC on receive */
			   break;
		case 'D' :
		case 'd' : DELFLAG = TRUE;  /* delete log file */
			   break;
		case 'L' :
		case 'l' : LOGFLAG = FALSE;  /* turn off log  */
			   break;
		case 'm' :
		case 'M' : MDM7BAT = TRUE;  /* turn on MODEM7 batch protocol */
			   BATCH   = TRUE;
			   break;
		case 'y' :
		case 'Y' : YMDMBAT = TRUE;  /* turn on YMODEM batch protocol */
			   BATCH   = TRUE;
			   break;
		case 'k' :
		case 'K' : LONGPACK = TRUE;  /* use 1K packets on transmit */
			   break;
		case 't' :
		case 'T' : TOOBUSY = TRUE;  /* turn off sleeping */
			   break;
		case 'R' :
		case 'r' : RECVFLAG = TRUE;  /* receive file */
			   XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
			   break;
		case 'S' :
		case 's' : SENDFLAG = TRUE;  /* send file */
			   XMITTYPE = gettype(argv[1][index++]);
			   break;
		default  : printf ("Invalid Flag %c ignored\n", flag);
			   break;
	   }

	if (DEBUG)
		LOGFLAG = TRUE;

	if (LOGFLAG)
	   { 
	     if ((fname = getenv("HOME")) == 0)	/* Get HOME variable */
		error("Fatal - Can't get Environment!", FALSE);
	     fname = strcat(fname, "/");
	     fname = strcat(fname, logfile);
	     if (!DELFLAG)
		LOGFP = fopen(fname, "a");  /* append to LOG file */
	     else
		LOGFP = fopen(fname, "w");  /* new LOG file */
	     if (!LOGFP)
		error("Fatal - Can't Open Log File", FALSE);

	     fprintf(LOGFP,"\n++++++++  %s", stamptime());
	     fprintf(LOGFP,"XMODEM Version %d.%d\n", VERSION/10, VERSION%10);
	     fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
	     for (index=2; index<argc; ++index)
		fprintf(LOGFP, " %s", argv[index]);
	     fprintf(LOGFP, "\n");
	   }

	getspeed();		/* get tty-speed for time estimates */

	if (RECVFLAG && SENDFLAG)
		error("Fatal - Both Send and Receive Functions Specified", FALSE);

	if (MDM7BAT && YMDMBAT)
		error("Fatal - Both YMODEM and MODEM7 Batch Protocols Specified", FALSE);

	if (!RECVFLAG && !SENDFLAG)
		error("Fatal - Either Send or Receive Function must be chosen!",FALSE);
	
	if (SENDFLAG && argc==2)
		error("Fatal - No file specified to send",FALSE);

	if (RECVFLAG && argc==2)
		{
		/* assume we really want CRC-16 in batch, unless we specify MODEM7 mode */ 
		CRCMODE = MDM7BAT ? FALSE : TRUE;
		printf("Ready for BATCH RECEIVE");
		printf(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
		printf("Send several Control-X characters to cancel\n");
		logit("Batch Receive Started");
		logitarg(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
		strcpy(fname, defname);
		}

	if (RECVFLAG && argc>2)
		{
		if(open(argv[2], 0) != -1)  /* check for overwriting */
			{
			logit("Warning -- Target File Exists and is Being Overwritten\n");
			printf("Warning -- Target File Exists and is Being Overwritten\n");
			}
		printf("Ready to RECEIVE File %s", argv[2]);
		printf(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
		printf("Send several Control-X characters to cancel\n");
		logitarg("Receiving in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
		strcpy(fname,argv[2]);
		}

	if (RECVFLAG)
		{  
		setmodes();		/* set tty modes for transfer */

		while(rfile(fname) != FALSE);  /* receive files */

		restoremodes(FALSE);	/* restore normal tty modes */

		sleep(2);		/* give other side time to return to terminal mode */
		exit(0);
		}

	if (SENDFLAG && BATCH) 
		{
		if (YMDMBAT)
			{
			printf("Ready to YMODEM BATCH SEND");
			printf(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
			logit("YMODEM Batch Send Started");
			logitarg(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
			}
		else if (MDM7BAT)
			{
			printf("Ready to MODEM7 BATCH SEND");
			printf(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
			logit("MODEM7 Batch Send Started");
			logitarg(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
			}
		printf("Send several Control-X characters to cancel\n");

		setmodes();
		for (index=2; index<argc; index++) {
			if (stat(argv[index], &filestatbuf) < 0) {
				logitarg("\nFile %s not found\n", argv[index]);
				continue;
			}
			sfile(argv[index]);
		}
		sfile("");
		restoremodes(FALSE);

		logit("Batch Send Complete\n");
		sleep(2);
		exit (0);
		}

	if (SENDFLAG && !BATCH) 
		{
		if (stat(argv[2], &filestatbuf) < 0)
			error("Can't find requested file", FALSE);
		expsect = (filestatbuf.st_size/128)+1;
			
		printf("File %s Ready to SEND", argv[2]);
		printf(" in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");
		printf("Estimated File Size %ldK, %ld Sectors, %ld Bytes\n",
	    	  (filestatbuf.st_size/1024)+1, expsect,
	  	  filestatbuf.st_size);
		projtime(expsect, stdout);
		printf("Send several Control-X characters to cancel\n");
		logitarg("Sending in %s mode\n", (XMITTYPE == 't') ? "text" : "binary");

		setmodes();
		sfile(argv[2]);
		restoremodes(FALSE);

		sleep(2);
		exit(0);
		}
}

andrews@hpcupt1.HP.COM (Edward E. Andrews) (03/25/88)

#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sgtty.h>
#include <signal.h>

/* define macros to print messages in log file */
#define  logit(string) if(LOGFLAG)fprintf(LOGFP,string)
#define  logitarg(string,argument) if(LOGFLAG)fprintf(LOGFP,string,argument)

#define	     VERSION	34	/* Version Number */
#define      FALSE      0
#define      TRUE       1


/*  ASCII Constants  */
#define      SOH  	001 
#define	     STX	002
#define	     ETX	003
#define      EOT	004
#define	     ENQ	005
#define      ACK  	006
#define	     LF		012   /* Unix LF/NL */
#define	     CR		015  
#define      NAK  	025
#define	     SYN	026
#define	     CAN	030
#define	     ESC	033

/*  XMODEM Constants  */
#define      TIMEOUT  	-1
#define      ERRORMAX  	10    /* maximum errors tolerated while transferring a packet */
#define      WAITFIRST  1     /* seconds between startup characters in read */
#define      STERRORMAX	60    /* maximum "errors" tolerated in read startup */
#define      CRCSWMAX	30    /* maximum time to try CRC mode before switching */
#define      NAKMAX	120   /* maximum times to wait for initial NAK when sending */
#define      RETRYMAX  	5     /* maximum retries to be made certain handshaking routines */
#define      KSWMAX	5     /* maximum errors before switching to 128 byte packets */
#define      EOTMAX	10    /* maximum times sender will send an EOT to end transfer */
#define      SLEEPNUM	100   /* target number of characters to collect during sleepy time */
#define	     BBUFSIZ	1024  /* buffer size */
#define      NAMSIZ	11    /* length of a CP/M file name string */
#define	     CTRLZ	032   /* CP/M EOF for text (usually!) */
#define      CRCCHR	'C'   /* CRC request character */
#define      KCHR	'K'   /* 1K block request character */
#define      BAD_NAME	'u'   /* Bad filename indicator */

#define      CREATMODE	0644  /* mode for created files */

/* GLOBAL VARIABLES */

int ttyspeed;		/* tty speed (bits per second) */
unsigned char buff[BBUFSIZ];	/* buffer for data */
int nbchr;		/* number of chars read so far for buffered read */
long filelength;	/* length specified in YMODEM header */
long fileread;		/* characters actually read so far in file */
char filename[256];	/* place to construct filenames */
FILE *LOGFP;		/* descriptor for LOG file */

/* option flags and state variables */
char	XMITTYPE;	/* text or binary? */
int	DEBUG;		/* keep debugging info in log? */
int	RECVFLAG;	/* receive? */
int	SENDFLAG;	/* send? */
int	BATCH;		/* batch? (Now used as a state variable) */
int	CRCMODE;	/* CRC or checksums? */
int	DELFLAG;	/* don't delete old log file? */
int	LOGFLAG;	/* keep log? */
int	LONGPACK; 	/* do not use long packets on transmit? */
int	MDM7BAT;	/* MODEM7 batch protocol */
int	YMDMBAT;	/* YMODEM batch protocol */
int	TOOBUSY;	/* turn off sleeping in packet read routine */
int	CHECKLENGTH;	/* Are we truncating a file to a YMODEM length? */


/*   CRC-16 constants.  From Usenet contribution by Mark G. Mendel, 
     Network Systems Corp.  (ihnp4!umn-cs!hyper!mark)
*/

    /* the CRC polynomial. */
#define	P	0x1021

    /* number of bits in CRC */
#define W	16

    /* the number of bits per char */
#define B	8