v15i071: Xmodem release 3.6, Part02/05

Rich Salz rsalz at uunet.uu.net
Wed Jun 15 06:23:01 AEST 1988


Submitted-by: Steve Grandi <grandi at noao.arizona.edu>
Posting-number: Volume 15, Issue 71
Archive-name: xmodem3.6/part02

: This is a shar archive.  Extract with sh, not csh.
echo x - xmodem.c
sed -e 's/^X//' > xmodem.c << '!Funky!Stuff!'
X/*
X *  XMODEM -- Implements the Christensen XMODEM protocol, 
X *            for packetized file up/downloading.    
X *
X *	See the README file for some notes on SYS V adaptations.
X *	The program has been successfully run on VAXes (4.3BSD) and SUN-3/4s
X *	(SunOS 3.x) against MEX-PC and ZCOMM/DSZ.
X *
X *  See the README and update.doc files for history and change notes.
X *
X *  Please send bug fixes, additions and comments to:
X *	{ihnp4,ncar}!noao!grandi   grandi at noao.arizona.edu
X */
X
X#include "xmodem.h"
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	char *getenv();
X	FILE *fopen();
X	char *unix_cpm();
X	char *strcpy();
X	char *strcat();
X	char *prtype();
X	
X	char *fname = filename;		/* convenient place to stash file names */
X	char *logfile = "xmodem.log";	/* Name of LOG File */
X	
X	char *stamptime();		/* for timestamp */
X
X	char *defname = "xmodem.in";	/* default file name if none given */
X
X	struct stat filestatbuf;	/* file status info */
X
X	int index;
X	char flag;
X	long expsect;
X
X	/* initialize option flags */
X
X	XMITTYPE = 't';		/* assume text transfer */
X	DEBUG = FALSE;		/* keep debugging info in log */
X	RECVFLAG = FALSE;	/* not receive */
X	SENDFLAG = FALSE;	/* not send either */
X	BATCH = FALSE;		/* nor batch */
X	CRCMODE = FALSE;	/* use checksums for now */
X	DELFLAG = FALSE;	/* don't delete old log file */
X	LOGFLAG = TRUE;		/* keep log */
X	LONGPACK = FALSE; 	/* do not use long packets on transmit */
X	MDM7BAT = FALSE;	/* no MODEM7 batch mode */
X	YMDMBAT = FALSE;	/* no YMODEM batch mode */
X	TOOBUSY = FALSE;	/* not too busy for sleeping in packet read */
X
X	fprintf(stderr, "XMODEM Version %d.%d", VERSION/10, VERSION%10);
X	fprintf(stderr, " -- UNIX-Microcomputer Remote File Transfer Facility\n");
X
X	if (argc == 1)
X		{
X		help();
X		exit(-1);
X		}
X
X	index = 0;		/* set index for flag loop */
X
X	while ((flag = argv[1][index++]) != '\0')
X	    switch (flag) {
X		case '-' : break;
X		case 'X' :
X		case 'x' : DEBUG = TRUE;  /* turn on debugging log */
X			   break;
X		case 'C' :
X		case 'c' : CRCMODE = TRUE; /* enable CRC on receive */
X			   break;
X		case 'D' :
X		case 'd' : DELFLAG = TRUE;  /* delete log file */
X			   break;
X		case 'L' :
X		case 'l' : LOGFLAG = FALSE;  /* turn off log  */
X			   break;
X		case 'm' :
X		case 'M' : MDM7BAT = TRUE;  /* turn on MODEM7 batch protocol */
X			   BATCH   = TRUE;
X			   break;
X		case 'y' :
X		case 'Y' : YMDMBAT = TRUE;  /* turn on YMODEM batch protocol */
X			   BATCH   = TRUE;
X			   break;
X		case 'k' :
X		case 'K' : LONGPACK = TRUE;  /* use 1K packets on transmit */
X			   break;
X		case 't' :
X		case 'T' : TOOBUSY = TRUE;  /* turn off sleeping */
X			   break;
X		case 'R' :
X		case 'r' : RECVFLAG = TRUE;  /* receive file */
X			   XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
X			   break;
X		case 'S' :
X		case 's' : SENDFLAG = TRUE;  /* send file */
X			   XMITTYPE = gettype(argv[1][index++]);
X			   break;
X		default  : fprintf(stderr, "Invalid Flag %c ignored\n", flag);
X			   break;
X	   }
X
X	if (DEBUG)
X		LOGFLAG = TRUE;
X
X	if (LOGFLAG)
X	   { 
X	     if ((fname = getenv("HOME")) == 0)	/* Get HOME variable */
X		error("Fatal - Can't get Environment!", FALSE);
X	     fname = strcat(fname, "/");
X	     fname = strcat(fname, logfile);
X	     if (!DELFLAG)
X		LOGFP = fopen(fname, "a");  /* append to LOG file */
X	     else
X		LOGFP = fopen(fname, "w");  /* new LOG file */
X	     if (!LOGFP)
X		error("Fatal - Can't Open Log File", FALSE);
X
X	     fprintf(LOGFP,"\n++++++++  %s", stamptime());
X	     fprintf(LOGFP,"XMODEM Version %d.%d\n", VERSION/10, VERSION%10);
X	     fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
X	     for (index=2; index<argc; ++index)
X		fprintf(LOGFP, " %s", argv[index]);
X	     fprintf(LOGFP, "\n");
X	   }
X
X	getspeed();		/* get tty-speed for time estimates */
X
X	if (RECVFLAG && SENDFLAG)
X		error("Fatal - Both Send and Receive Functions Specified", FALSE);
X
X	if (MDM7BAT && YMDMBAT)
X		error("Fatal - Both YMODEM and MODEM7 Batch Protocols Specified", FALSE);
X
X	if (!RECVFLAG && !SENDFLAG)
X		error("Fatal - Either Send or Receive Function must be chosen!",FALSE);
X	
X	if (SENDFLAG && argc==2)
X		error("Fatal - No file specified to send",FALSE);
X
X	if (RECVFLAG && argc==2)
X		{
X		/* assume we really want CRC-16 in batch, unless we specify MODEM7 mode */ 
X		CRCMODE = MDM7BAT ? FALSE : TRUE;
X		fprintf(stderr, "Ready for BATCH RECEIVE");
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X		fprintf(stderr, "Send several Control-X characters to cancel\n");
X		logit("Batch Receive Started");
X		logitarg(" in %s mode\n", prtype(XMITTYPE));
X		strcpy(fname, defname);
X		}
X
X	if (RECVFLAG && argc>2)
X		{
X		if(open(argv[2], 0) != -1)  /* check for overwriting */
X			{
X			logit("Warning -- Target File Exists and is Being Overwritten\n");
X			fprintf(stderr, "Warning -- Target File Exists and is Being Overwritten\n");
X			}
X		fprintf(stderr, "Ready to RECEIVE File %s", argv[2]);
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X		fprintf(stderr, "Send several Control-X characters to cancel\n");
X		logitarg("Receiving in %s mode\n", prtype(XMITTYPE));
X		strcpy(fname,argv[2]);
X		}
X
X	if (RECVFLAG)
X		{  
X		setmodes();		/* set tty modes for transfer */
X
X		while(rfile(fname) != FALSE);  /* receive files */
X
X		flushin();
X		restoremodes(FALSE);	/* restore normal tty modes */
X
X		sleep(2);		/* give other side time to return to terminal mode */
X		exit(0);
X		}
X
X	if (SENDFLAG && BATCH) 
X		{
X		if (YMDMBAT)
X			{
X			fprintf(stderr, "Ready to YMODEM BATCH SEND");
X			fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X			logit("YMODEM Batch Send Started");
X			logitarg(" in %s mode\n", prtype(XMITTYPE));
X			}
X		else if (MDM7BAT)
X			{
X			fprintf(stderr, "Ready to MODEM7 BATCH SEND");
X			fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X			logit("MODEM7 Batch Send Started");
X			logitarg(" in %s mode\n", prtype(XMITTYPE));
X			}
X		fprintf(stderr, "Send several Control-X characters to cancel\n");
X
X		setmodes();
X		for (index=2; index<argc; index++) {
X			if (stat(argv[index], &filestatbuf) < 0) {
X				logitarg("\nFile %s not found\n", argv[index]);
X				continue;
X			}
X			sfile(argv[index]);
X		}
X		sfile("");
X		flushin();
X		restoremodes(FALSE);
X
X		logit("Batch Send Complete\n");
X		sleep(2);
X		exit (0);
X		}
X
X	if (SENDFLAG && !BATCH) 
X		{
X		if (stat(argv[2], &filestatbuf) < 0)
X			error("Can't find requested file", FALSE);
X		expsect = (filestatbuf.st_size/128)+1;
X			
X		fprintf(stderr, "File %s Ready to SEND", argv[2]);
X		fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
X		fprintf(stderr, "Estimated File Size %ldK, %ld Sectors, %ld Bytes\n",
X	    	  (filestatbuf.st_size/1024)+1, expsect,
X	  	  filestatbuf.st_size);
X		projtime(expsect, stdout);
X		fprintf(stderr, "Send several Control-X characters to cancel\n");
X		logitarg("Sending in %s mode\n", prtype(XMITTYPE));
X
X		setmodes();
X		sfile(argv[2]);
X		flushin();
X		restoremodes(FALSE);
X
X		sleep(2);
X		exit(0);
X		}
X}
!Funky!Stuff!
echo x - receive.c
sed -e 's/^X//' > receive.c << '!Funky!Stuff!'
X#include "xmodem.h"
X
X/**  receive a file  **/
X
X/* returns TRUE if in the midst of a batch transfer */
X/* returns FALSE if no more files are coming */
X
X/* This routine is one HUGE do-while loop with far to many indented levels.
X * I chose this route to facilitate error processing and to avoid GOTOs.
X * Given the troubles I've had keeping the nested IF statements straight,
X * I was probably mistaken...
X */
X
Xrfile(name)
Xchar *name;
X{
X
Xchar *sectdisp();
Xchar *cpm_unix();
Xchar *strcpy();
Xchar *ctime();
Xtime_t time();
X
Xint fd,     /* file descriptor for created file */
Xchecksum,   /* packet checksum */
Xfirstchar,  /* first character of a packet */
Xsectnum,    /* number of last received packet (modulo 128) */
Xsectcurr,   /* second byte of packet--should be packet number (mod 128) */
Xsectcomp,   /* third byte of packet--should be complement of sectcurr */
Xtmode,      /* text mode if true */
Xamode,      /* apple mode if true */
Xerrors,     /* count of errors for each packet */
Xsterrors,   /* count of errors during startup handshake */
Xerrorflag,  /* set true when packet (or first char of putative packet) is invalid */
Xfatalerror, /* set within main "read-packet" Do-While when bad error found */
Xinchecksum, /* incoming checksum or CRC */
Xexpsect,    /* expected number of sectors (YMODEM batch) */
Xfirstwait,  /* seconds to wait for first character in a packet */
Xbufsize;    /* packet size (128 or 1024) */
Xlong recvsectcnt;   /* running sector count (128 byte sectors) */
Xlong modtime;       /* Unix style file mod time from YMODEM header */
Xint filemode;       /* Unix style file mode from YMODEM header */
Xlong readbackup;    /* "backup" value for characters read in file */
Xtime_t timep[2];    /* used in setting mod time of received file */
Xchar *p;    /* generic pointer */
Xint bufctr; /* number of real chars in read packet */
Xunsigned char *nameptr; /* ptr in filename for MODEM7 protocol */
Xtime_t start;       /* starting time of transfer */
Xint openflag = FALSE;   /* is file open for writing? */
X
Xlogit("----\nXMODEM File Receive Function\n");
Xif (CRCMODE)
Xlogit("CRC mode requested\n");
X
XBATCH = FALSE;          /* don't know if really are in batch mode ! */
Xfatalerror = FALSE;
Xfirstwait = WAITFIRST;  /* For first packet, wait short time */
Xsectnum = errors = recvsectcnt = 0;
Xbufsize = 128;
Xmodtime = 0l; filemode = 0;
Xfilelength = 0l; fileread =0l; CHECKLENGTH = FALSE;
X
Xtmode = (XMITTYPE == 't') ? TRUE : FALSE;
Xamode = (XMITTYPE == 'a') ? TRUE : FALSE;
X
X/* start up transfer */
X
Xsterrors = 0;
Xflushin();         /* flush input queue */
X
Xif (CRCMODE)        
X{
X	sendbyte(CRCCHR);
X	if (LONGPACK && !MDM7BAT)
X		sendbyte(KCHR);
X}
Xelse
X	sendbyte(NAK);
X
X
Xdo                  /* start of MAIN Do-While loop to read packets */
X{   
X	errorflag = FALSE;
X	do              /* start by reading first byte in packet */
X	{
X		firstchar = readbyte(firstwait);
X	} 
X	while ((firstchar != SOH) 
X	    && (firstchar != STX) 
X	    && (firstchar != EOT) 
X	    && (firstchar != ACK || recvsectcnt > 0) 
X	    && (firstchar != TIMEOUT) 
X	    && (firstchar != CAN || recvsectcnt > 0));
X
X	if (firstchar == EOT)           /* check for REAL EOT */
X	{
X		flushin();
X		sendbyte(NAK);              /* NAK the EOT */
X		if ((firstchar = readbyte(3)) != EOT)   /* check next character */
X		{
X			logit("Spurious EOT detected; ignored\n");
X			if ((firstchar == SOH) || (firstchar == STX) ||
X			    (firstchar == ACK && recvsectcnt == 0) ||
X			    (firstchar == CAN && recvsectcnt == 0) ||
X			    (firstchar == TIMEOUT))
X				break;
X			else
X			{
X				firstchar = 0;
X				errorflag = TRUE;
X			}
X		}
X	}
X
X	if (firstchar == TIMEOUT)       /* timeout? */
X	{  
X		if (recvsectcnt > 0)
X			logitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
X		errorflag = TRUE;
X	}
X
X	if (firstchar == CAN)           /* bailing out? (only at beginning) */
X	{
X		if ((readbyte(3) & 0x7f) == CAN)
X			error("Reception canceled at user's request",TRUE);
X		else
X		{
X			errorflag = TRUE;
X			logit("Received single CAN character\n");
X		}
X	}
X
X	if (firstchar == ACK)           /* MODEM7 batch? (only at beginning) */
X	{
X		int i,c; 
X
X		logit("MODEM7 Batch Protocol\n");
X		nameptr = buff;
X		checksum = 0;
X
X		for (i=0; i<NAMSIZ; i++)
X		{
X			c = readbyte(3);
X
X			if (c == CAN)
X			{
X				if (readbyte(3) == CAN)
X					error("Program Canceled by User", TRUE);
X				else
X				{
X					logit("Received single CAN character in MODEM7 filename\n");
X					errorflag = TRUE;
X					break;
X				}
X			}
X
X			if (c == EOT && i == 0)
X			{
X				sendbyte(ACK);          /* acknowledge EOT */
X				logit("MODEM7 Batch Receive Complete\n");
X				return (FALSE);
X			}
X
X			if (c == TIMEOUT)
X			{
X				logit("Timeout waiting for MODEM7 filename character\n");
X				errorflag = TRUE;
X				break;
X			}
X
X			if (c == BAD_NAME)
X			{
X				logit("Error during MODEM7 filename transfer\n");
X				errorflag = TRUE;
X				break;
X			}
X
X			*nameptr++ = c;
X			checksum += c;
X			sendbyte(ACK);
X		}
X
X		if (!errorflag)
X		{
X			c = readbyte(3);
X			if (c == CTRLZ)     /* OK; end of string found */
X			{
X				sendbyte(checksum + CTRLZ);
X				if (readbyte(15) == ACK)     /* file name found! */
X				{
X					xmdebug("MODEM7 file name OK");
X					*nameptr = '\000';  /* unixify the file name */
X					name = cpm_unix(buff);
X					BATCH = TRUE;
X					logitarg("MODEM7 file name: %s\n", name);
X					errors = 0;     /* restart crc handshake */
X					sleep(2);       /* give other side a chance */
X				}
X				else
X				{
X					logit("Checksum error in MODEM7 filename\n");
X					errorflag = TRUE;
X				}
X			}
X			else
X			{
X				logit("Length error in MODEM7 filename\n");
X				errorflag = TRUE;
X			}
X		}
X	}
X
X
X	if (firstchar == SOH || firstchar == STX)  /* start reading packet */
X	{
X		bufsize = (firstchar == SOH) ? 128 : 1024;
X
X		if (recvsectcnt == 0)           /* 1st data packet, initialize */
X		{
X			if (bufsize == 1024)
X				logit("1K packet mode chosen\n");
X			start = time((time_t *) 0);
X			errors = 0;
X			firstwait = 5;
X		}
X
X		sectcurr = readbyte(3);
X		sectcomp = readbyte(3);
X		if ((sectcurr + sectcomp) == 0xff)  /* is packet number checksum correct? */
X		{  
X			if (sectcurr == ((sectnum+1) & 0xff))   /* is packet number correct? */
X			{  
X				if (DEBUG)
X					fprintf(LOGFP,"DEBUG: packet %d started\n", sectnum);
X
X				/* Read, process and calculate checksum for a buffer of data */
X
X				readbackup = fileread;
X				if (readbuf(bufsize, 1, tmode, amode, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
X				{
X
X					/* verify checksum or CRC */
X
X					if (CRCMODE) 
X					{
X						checksum &= 0xffff;
X						inchecksum = readbyte(3);  /* get 16-bit CRC */
X						inchecksum = (inchecksum<<8) | readbyte(3);
X					}
X
X					else
X						inchecksum = readbyte(3);  /* get simple 8-bit checksum */
X
X					if (inchecksum == checksum) /* good checksum, hence good packet */
X					{  
X						xmdebug("checksum ok");
X						errors = 0;
X						recvsectcnt += (bufsize == 128) ? 1 : 8;
X						sectnum = sectcurr; 
X
X						if (!openflag)      /* open output file if necessary */
X						{
X							openflag = TRUE;
X							if ((fd = creat(name, CREATMODE)) < 0)
X							{
X								sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X								error("Can't create file for receive", TRUE);
X							}
X							if (!BATCH)
X								logitarg("File Name: %s\n", name);
X						}
X
X						if (write(fd, (char *) buff, bufctr) != bufctr)
X						{
X							close(fd);
X							unlink(name);
X							error("File Write Error", TRUE);
X						}
X						else
X						{
X							flushin();          /* flush input */
X							sendbyte(ACK);      /* ACK the received packet */
X						}
X					}
X
X					/* Start handling various errors and special conditions */
X
X					else        /* bad checksum */
X					{  
X						logitarg("Checksum Error on Sector %s:  ", sectdisp(recvsectcnt,bufsize,1));
X						logitarg("sent=%x  ", inchecksum);
X						logitarg("recvd=%x\n", checksum);
X						fileread = readbackup;
X						errorflag = TRUE;
X					}
X				}
X
X				else    /* read timeout */
X				{
X					logitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
X					fileread = readbackup;
X					errorflag = TRUE;
X				}
X			}
X
X			else        /* sector number is wrong OR Ymodem filename */
X			{ 
X				if (sectcurr == 0 && recvsectcnt == 0)  /* Ymodem file-name packet */
X				{
X					logit("YMODEM Batch Protocol\n");
X
X					/* Read and process a file-name packet */
X
X					if (readbuf(bufsize, 1, FALSE, FALSE, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
X					{
X
X						/* verify checksum or CRC */
X
X						if (CRCMODE) 
X						{
X							checksum &= 0xffff;
X							inchecksum = readbyte(3);  /* get 16-bit CRC */
X							inchecksum = (inchecksum<<8) | readbyte(3);
X						}
X
X						else
X							inchecksum = readbyte(3);  /* get simple 8-bit checksum */
X
X						if (inchecksum == checksum) /* good checksum, hence good filename */
X						{
X							xmdebug("checksum ok");
X							strcpy(name, (char *)buff);
X							expsect = ((buff[bufsize-1]<<8) | buff[bufsize-2]);
X							BATCH = TRUE;
X							YMDMBAT = TRUE;
X							if (strlen(name) == 0)  /* check for no more files */
X							{
X								flushin();          /* flush input */
X								sendbyte(ACK);      /* ACK the packet */
X								logit("YMODEM Batch Receive Complete\n");
X								return (FALSE);
X							}
X							unixify(name);       /* make filename canonical */
X
X							/* read rest of YMODEM header */
X							p = (char *)buff + strlen((char *)buff) + 1;
X							sscanf(p, "%ld%lo%o", &filelength, &modtime, &filemode);
X							logitarg("YMODEM file name: %s\n", name);
X							fileread = 0l;
X							if (filelength)
X							{
X								CHECKLENGTH = TRUE;
X								logitarg("YMODEM file size: %ld\n", filelength);
X							}
X							else if (expsect)
X								logitarg("YMODEM estimated file length %d sectors\n", expsect);
X							if (modtime)
X							{
X								logitarg("YMODEM file date: %s", ctime(&modtime));
X							}
X							if (filemode)
X								logitarg("YMODEM file mode: %o", filemode);
X
X							sendbyte(ACK);      /* ACK the packet */
X							firstwait = WAITFIRST;  /* reset to negotiate */
X						}
X
X						else                /* bad filename checksum */
X						{
X							logit("checksum error on filename sector\n");
X							errorflag = TRUE;
X						}
X					}
X					else
X					{
X						logit("Timeout while reading filename packet\n");
X						errorflag = TRUE;
X					}
X				}
X
X				else if (sectcurr == sectnum)   /* duplicate sector? */
X				{  
X					logitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
X					flushin();                  /* REALLY flush input */
X					while(readbyte(1) != TIMEOUT)
X						;
X					sendbyte(ACK);
X				}
X				else                /* no, real phase error */
X				{
X					logitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
X					errorflag = TRUE;
X					fatalerror = TRUE;
X				}
X			}
X		}
X
X		else        /* bad packet number checksum */
X		{  
X			logitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
X			errorflag = TRUE;
X		}
X
X	}           /* END reading packet loop */
X
X	if (errorflag && !fatalerror && recvsectcnt != 0)   /* Handle errors */
X	{  
X		errors++;
X
X		if (errors >= ERRORMAX)     /* over error limit? */
X			fatalerror = TRUE;
X		else                        /* flush input and NAK the packet */
X		{
X			flushin();
X			while (readbyte(1) != TIMEOUT)  /* wait for line to settle */
X				;
X			sendbyte(NAK);
X		}
X	}
X
X	if (recvsectcnt == 0 && errorflag && firstchar != EOT) 	/* handle startup handshake */
X	{
X		sterrors++;
X
X		if (sterrors >= STERRORMAX)
X			fatalerror = TRUE;
X
X		else if (CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
X		{
X			CRCMODE = FALSE;
X			logit("Sender not accepting CRC request, changing to checksum\n");
X			sendbyte(NAK);
X		}
X
X		else if (!CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
X		{
X			CRCMODE = TRUE;
X			logit("Sender not accepting checksum request, changing to CRC\n");
X			sendbyte(CRCCHR);
X			if (LONGPACK && !MDM7BAT)
X				sendbyte(KCHR);
X		}
X
X		else if (CRCMODE)
X			{
X			sendbyte(CRCCHR);
X			if (LONGPACK && !MDM7BAT)
X				sendbyte(KCHR);
X			}
X
X		else
X			sendbyte(NAK);
X	}
X}
Xwhile ((firstchar != EOT) && !fatalerror);   /* end of MAIN Do-While */
X
Xif ((firstchar == EOT) && !fatalerror)  /* normal exit? */
X{
X	if (openflag)       /* close the file */
X		close(fd);
X	sendbyte(ACK);      /* ACK the EOT */
X	logit("Receive Complete\n");
X	prtime (recvsectcnt, time((time_t *) 0) - start);
X
X	if (openflag && modtime)   /* set file modification time */
X	{
X		timep[0] = time((time_t *) 0);
X		timep[1] = modtime;
X		utime(name, timep);
X	}
X
X	if (BATCH)          /* send appropriate return code */
X		return(TRUE);
X	else
X		return(FALSE);
X}
Xelse                /* no, error exit */
X{ 
X	if (openflag)
X	{
X		sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
X		close(fd);
X		unlink(name);
X		error("ABORTED -- Too Many Errors--deleting file", TRUE);
X	}
X	else if (recvsectcnt != 0)
X		error("ABORTED -- Too Many Errors", TRUE);
X	else
X		error("ABORTED -- Remote system is not responding", TRUE);
X}
Xreturn(FALSE);
X
X}
!Funky!Stuff!
echo x - misc.c
sed -e 's/^X//' > misc.c << '!Funky!Stuff!'
X#include "xmodem.h"
X
X/*  Print Help Message  */
Xhelp()
X	{
X	fprintf(stderr, "\nUsage:  \n\txmodem ");
X	fprintf(stderr, "-[rb!rt!ra!sb!st!sa][options] filename\n");
X	fprintf(stderr, "\nMajor Commands --");
X	fprintf(stderr, "\n\trb <-- Receive Binary");
X	fprintf(stderr, "\n\trt <-- Receive Text");
X	fprintf(stderr, "\n\tra <-- Receive Apple macintosh text");
X	fprintf(stderr, "\n\tsb <-- Send Binary");
X	fprintf(stderr, "\n\tst <-- Send Text");
X	fprintf(stderr, "\n\tsa <-- Send Apple macintosh text");
X	fprintf(stderr, "\nOptions --");
X	fprintf(stderr, "\n\ty  <-- Use YMODEM Batch Mode on transmit");
X	fprintf(stderr, "\n\tm  <-- Use MODEM7 Batch Mode on transmit");
X	fprintf(stderr, "\n\tk  <-- Use 1K packets on transmit");
X	fprintf(stderr, "\n\tc  <-- Select CRC mode on receive");
X	fprintf(stderr, "\n\tt  <-- Indicate a TOO BUSY Unix system");
X	fprintf(stderr, "\n\td  <-- Delete xmodem.log file before starting");
X	fprintf(stderr, "\n\tl  <-- (ell) Turn OFF Log File Entries");
X	fprintf(stderr, "\n\tx  <-- Include copious debugging information in log file");
X	fprintf(stderr, "\n");
X	}
X
X/* get type of transmission requested (text or binary) */
Xgettype(ichar)
Xchar ichar;
X	{
X	if (ichar == 't' || ichar == 'T')
X		return('t');
X	else if (ichar == 'b' || ichar == 'B')
X		return('b');
X	else if (ichar == 'a' || ichar == 'A')
X		return('a');
X	else
X		error("Invalid Send/Receive Parameter - not t or b", FALSE);
X	return('\0');
X	}
X
X/* return a string containing transmission type */
Xchar *
Xprtype(ichar)
Xchar ichar;
X	{
X	if (ichar == 't' || ichar == 'T')
X		return("text");
X	else if (ichar == 'b' || ichar == 'B')
X		return("binary");
X	else if (ichar == 'a' || ichar == 'A')
X		return("apple");
X	else
X		return("");
X	}
X
X/* print error message and exit; if mode == TRUE, restore normal tty modes */
Xerror(msg, mode)
Xchar *msg;
Xint mode;
X	{
X	if (mode)
X		restoremodes(TRUE);  /* put back normal tty modes */
X	fprintf(stderr, "\r\n%s\n", msg);
X	if ((LOGFLAG || DEBUG) && (LOGFP != NULL))
X		{   
X		fprintf(LOGFP, "XMODEM Fatal Error:  %s\n", msg);
X	    	fclose(LOGFP);
X		}
X	exit(-1);
X	}
X
X
X/* Construct a proper (i.e. pretty) sector count for messages */
X
Xchar
X*sectdisp(recvsectcnt, bufsize, plus1)
Xlong recvsectcnt;
Xint bufsize, plus1;
X	{
X	static char string[20];
X	if (plus1)
X		recvsectcnt += (bufsize == 128) ? 1 : 8;
X	if (bufsize == 128 || recvsectcnt == 0)
X		sprintf (string, "%d", recvsectcnt);
X	else
X		sprintf (string, "%d-%d", recvsectcnt-7, recvsectcnt);
X	return(string);
X	}
X
X/* type out debugging info */
Xxmdebug(str)
Xchar *str;
X	{
X	if (DEBUG && (LOGFP != NULL))
X		fprintf(LOGFP,"DEBUG: '%s'\n",str);
X	}
X
X/* print elapsed time and rate of transfer in logfile */
X
Xint quant[] = { 60, 60, 24};	
Xchar sep[3][10] = { "second", "minute", "hour" };
X
Xprtime (numsect, seconds)
Xlong numsect;
Xtime_t seconds;
X
X{
X	register int i;
X	register int Seconds;
X	int nums[3];
X	int rate;
X
X	if (!LOGFLAG || numsect == 0)
X		return(0);
X
X	Seconds = (int)seconds;
X	Seconds = (Seconds > 0) ? Seconds : 0;
X
X	rate = (Seconds != 0) ? 128 * numsect/Seconds : 0;
X
X	for (i=0; i<3; i++) {
X		nums[i] = (Seconds % quant[i]);
X		Seconds /= quant[i];
X	}
X
X	fprintf (LOGFP, "%ld Sectors Transfered in ", numsect);
X
X	if (rate == 0)
X		fprintf (LOGFP, "0 seconds");
X	else
X		while (--i >= 0)
X			if (nums[i])
X				fprintf (LOGFP, "%d %s%c ", nums[i], &sep[i][0],
X					nums[i] == 1 ? ' ' : 's');
X	fprintf (LOGFP, "\n");
X
X	if (rate != 0)
X		fprintf (LOGFP, "Transfer Rate = %d Characters per Second\n", rate);
X
X	return(0);
X}
X
X/* Print elapsed time estimate */
X
Xprojtime (numsect, fd)
Xlong numsect;
XFILE *fd;
X	{
X	register int i;
X	register int seconds;
X	int nums[3];
X
X	if (numsect == 0)
X		return (0);
X
X/* constant below should really be 1280; reduced to 90% to account for time lost in overhead */
X
X	seconds = 1422 * numsect / ttyspeed + 1;
X
X	for (i=0; i<3; i++) {
X		nums[i] = (seconds % quant[i]);
X		seconds /= quant[i];
X	}
X
X	fprintf (fd, "Estimated transmission time ");
X
X	while (--i >= 0)
X		if (nums[i])
X			fprintf (fd, "%d %s%c ", nums[i], &sep[i][0],
X				nums[i] == 1 ? ' ' : 's');
X	fprintf (fd, "\n");
X	return (0);
X	}
!Funky!Stuff!
exit

-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.



More information about the Comp.sources.unix mailing list