[fa.info-mac] MACPUT/GET for Tops20

info-mac@uw-beaver (info-mac) (12/01/84)

From: Ed Pattermann <PATTERMANN@SUMEX-AIM.ARPA>
I had thought someone at Utah was doing a MACPUT/MACGET for Tops20. Is
that true? Wasn't there also someone considering modifying the Tops20
MODEM program (by Bill Westfield) to download resource and data forks?

-- Ed
                ---------------

Date: Tue 27 Nov 84 19:12:49-EST
From: S.BOY-BOYCE-GEORGE%CRNL20A.BITNET@Berkeley
Subject: macget/put
To: patterman@sumex-aim.ARPA

Has anyone ported macget/put to TOPS-20. I made one attempt (using the Utah C
package) but it didn't seem to fly. Any ideas?

Address: Cornell Computer Services, Cornell University, Ithaca NY, 14851
         s.boy@crnl20a.bitnet,george@cornell.arpa,gboydecy@cornella.bitnet
-------

-------

info-mac@uw-beaver (info-mac) (12/01/84)

From: Dan Tappan <Tappan@BBNG.ARPA>
I have a hacked up MACGET for TOPS20, compiles with the MIT C compiler.
It is below if anyone can use it. I have not done MACPUT.

	-----
#include <stdio.h>


#define RECORDBYTES 132
#define DATABYTES 128
#define NAMEBYTES 63

#define RETRIES 15
#define SOHTIMO 60
#define LINTIMO 60
#define CHRTIMO 10

#define MAXRECNO 0xff
#define BYTEMASK 0xff

#define TMO -1
#define DUP '\000'
#define SOH '\001'
#define EOT '\004'
#define ACK '\006'
#define NAK '\025'
#define CAN '\030'
#define EEF '\032'
#define ESC '\033'

#define H_NLENOFF 1
#define H_NAMEOFF 2
#define H_TYPEOFF 65
#define H_AUTHOFF 69
#define H_DLENOFF 81
#define H_RLENOFF 85

#define TEXT 0
#define DATA 1
#define RSRC 2
#define FULL 3

int mode, txtmode;

struct macheader {
	char m_name[NAMEBYTES+1];
	char m_type[4];
	char m_author[4];
	int m_datalen;
	int m_rsrclen;
} mh;

struct filenames {
	char f_info[256];
	char f_data[256];
	char f_rsrc[256];
} files;

int lastack;
char buf[DATABYTES];

/*
 * macget -- receive file from macintosh using xmodem protocol
 *
 * (c) 1984 Brown University Computer Science 
 * may be used but not sold without permission
 * written by Dave Johnson 5/22/84
 * revised ddj 6/29/84
 *
 * Converted tops20 (mit c) 7/31/84, took out all timeout
 * stuff (signal not supported), only binary mode transfers
 * supported.
 */
char usage[] = "usage: \"macget [-rdu] [filename]\"\n";

static recv_file(), recv_hdr();

main(ac, av)
char **av;
{
	char *name;

	mode = FULL;
	name = "";
	ac--; av++;
	while (ac) {
		if (av[0][0] == '-') {
			switch (av[0][1]) {
                        case 'R':                   
			case 'r':
				mode = RSRC;
				break;
                        case 'D':        
			case 'd':
				mode = DATA;
				break;
                        case 'U':        
			case 'u':
				mode = TEXT;
				break;
			default:
				fprintf(stderr, usage);
				exit(1);
			}
		}
		else {
			name = av[0];
		}
		ac--; av++;
	}

	setup_tty();
	if (send_sync() == ACK) {
		txtmode = 0;
		recv_hdr(name);
		if (mode == TEXT) txtmode++;
		recv_file(files.f_data, mh.m_datalen, 1);
		txtmode = 0;
		recv_file(files.f_rsrc, mh.m_rsrclen, 0);
	}
	reset_tty();
}

static recv_hdr(name)
char *name;
{
	int n;
	FILE *fp;
	char *tmpnam();
        char tmpname[50];
	char *np;

        tmpnam(tmpname);
	recv_file(tmpname, DATABYTES, 1);

	fp = fopen(tmpname, "r8b");
	if (fp == NULL) {
		perror("temp file");
		cleanup(-1);
	}
	fread(buf, 1, DATABYTES, fp);
	fclose(fp);

	if (name && *name) {
		n = strlen(name);
		if (n > NAMEBYTES) n = NAMEBYTES;
		strncpy(mh.m_name, name, n);
		mh.m_name[n] = '\0';
	}
	else {
		n = buf[H_NLENOFF] & BYTEMASK;
		if (n > NAMEBYTES) n = NAMEBYTES;
		strncpy(mh.m_name, buf + H_NAMEOFF, n);
		mh.m_name[n] = '\0';
	}
	for (np = mh.m_name; *np; np++)
		if (*np == ' ') *np = '_';

	if (mode == FULL) {
		sprintf(files.f_info, "%s.info", mh.m_name);
                rename(tmpname, files.f_info);
		sprintf(files.f_data, "%s.data", mh.m_name);
		sprintf(files.f_rsrc, "%s.rsrc", mh.m_name);
	}
	else {
		unlink(tmpname);
		switch (mode) {
		case RSRC:
			sprintf(files.f_data, "/dev/null");
			sprintf(files.f_rsrc, "%s.rsrc", mh.m_name);
			break;

		case DATA:
			sprintf(files.f_data, "%s.data", mh.m_name);
			sprintf(files.f_rsrc, "/dev/null");
			break;

		case TEXT:
			sprintf(files.f_data, "%s.text", mh.m_name);
			sprintf(files.f_rsrc, "/dev/null");
			break;
		}
	}

	strncpy(mh.m_type, buf + H_TYPEOFF, 4);
	strncpy(mh.m_author, buf + H_AUTHOFF, 4);
	mh.m_datalen = get4(buf + H_DLENOFF);
	mh.m_rsrclen = get4(buf + H_RLENOFF);
}

static recv_file(fname, bytes, more)
char *fname;
int bytes, more;
{
	register int status, n;
	FILE *outf;
	int naks = 0;

	lastack = 0;
	outf = fopen(fname, txtmode ? "w" : "w8b");
	if (outf == NULL) {
		perror(fname);
		cleanup(-1);
	}
	for (;;) {
		status = rec_read(buf, DATABYTES);
		switch (status) {
		case EOT:
                        tputc(ACK);

			if (more)
				tputc(NAK);
			fclose(outf);
			return;
		case ACK:
			tputc(ACK);
			naks = 0;
			n = (bytes > DATABYTES) ? DATABYTES : bytes;
			bytes -= n;
			fwrite(buf, n, 1, outf);
			break;
		case DUP:
			tputc(ACK);
			naks = 0;
			break;
		case NAK:
			if (naks++ < RETRIES) {
				tputc(NAK);
				break;
			}
			/* fall through */
		case CAN:
			tputc(CAN);
			fclose(outf);
			/* unlink fname? */
			cleanup(-1);
			/* NOTREACHED */
		}
	}
}

send_sync()
{
	int c;

	for (;;) {
		c = tgetc(60);
		switch (c) {
		case ESC:
			break;
		case CAN:
		case EOT:
		case TMO:
			return c;
		default:
			continue;
		}
		c = tgetc(1);
		if (c != 'a')
			continue;
		tputc(ACK);
		return ACK;
	}
}

rec_read(buf, recsize)
char buf[];
int recsize;
{
	int c, rec, rec_bar, cksum;

	c = tgetc(SOHTIMO);
	switch (c) {
	case TMO:
		return NAK;
	case EOT:
		return EOT;
	case CAN:
		return CAN;
	case SOH:
		/* read header */
		rec = tgetc(CHRTIMO);
		if (rec == TMO)
			return NAK;
		rec_bar = tgetc(CHRTIMO);
		if (rec_bar == TMO)
			return NAK;

		/* check header */
		if (rec != MAXRECNO - rec_bar) return NAK;

		/* fill buffer */
		cksum = tgetrec(buf, recsize, LINTIMO);
		if (cksum == TMO)
			return NAK;

		/* get checksum */
		c = tgetc(CHRTIMO);
		if (c == TMO)
			return NAK;
		if (c != (cksum & BYTEMASK))
			return NAK;

		/* check record number */
		if (rec == lastack)
			return DUP;
		if (rec != ((lastack + 1) & MAXRECNO))
			return CAN;
		else {
			lastack = rec;
			return ACK;
		}
	}
	/* NOTREACHED */
}

static int ttyfd;
static FILE *ttyf;

tgetrec(buf, count, timeout)
char *buf;
int count, timeout;
{
	char *bp;
	int i, cksum;

        bp = buf; i = count;

        while(i-- > 0) *bp++ = tgetc(100);
	
	cksum = 0;
	bp = buf;
 	for (i = 0; i < count; bp++, i++) {
 		cksum += *bp;
	}
	return cksum;
}

tgetc(timeout)
int timeout;
{
	int c;

        c = _BIN(ttyfd);

	if (c == -1)	/* probably hung up or logged off */
		return EOT;
	else
		return c & BYTEMASK;
}

tputc(c)
char c;
{
        _BOUT(ttyfd, c);   
}

static int otty;
/* should turn messages off */

setup_tty()
{
	int cleanup();
	int timedout();

	ttyf = stdin;
	ttyfd = fileno(stdin);
        otty = _RFMOD(ttyfd);
        _SFMOD(ttyfd, otty&0777777773477);
        _STPAR(ttyfd, otty%0777777777775);
        _STIW(0777773, 0);
}

reset_tty()
{
	sleep(2);	/* should wait for output to drain */
        _SFMOD(ttyfd, otty);
        _STPAR(ttyfd, otty);
}

cleanup(sig)
int sig;
{
	reset_tty();
	exit(sig);
}

get4(bp)
char *bp;
{
	register int i;
	int value = 0;

	for (i = 0; i < 4; i++) {
		value <<= 8;
		value |= (*bp & BYTEMASK);
		bp++;
	}
	return value;
}
-------

info-mac@uw-beaver (info-mac) (12/01/84)

From: Dan Tappan <Tappan@BBNG.ARPA>
I have a hacked up MACGET for TOPS20, compiles with the MIT C compiler.
It is below if anyone can use it. I have not done MACPUT.

[Ed. File is on {SUMEX-AIM}<INFO-MAC>MACGET.T20C]

	-----