[net.sources.mac] macget: here it is

vishniac@wanginst.UUCP (Ephraim Vishniac) (07/23/85)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	macget.c
#	macget.1w
#	Makefile
# This archive created: Tue Jul 23 08:25:58 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'macget.c'" '(7828 characters)'
if test -f 'macget.c'
then
	echo shar: will not over-write existing file "'macget.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'macget.c'
	X#include <stdio.h>
	X#include <signal.h>
	X#include <setjmp.h>
	X#include <sgtty.h>
	X
	X#ifdef NO_RENAME
	X#define rename(old, new)	link(old, new); unlink(old)
	X#endif
	X
	X/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
	X#define TIMEDIFF 0x7c25b080
	X
	X#define RECORDBYTES 132
	X#define DATABYTES 128
	X#define NAMEBYTES 63
	X
	X#define RETRIES 10
	X#define SOHTIMO 10
	X#define LINTIMO 20
	X#define CHRTIMO 2
	X
	X#define MAXRECNO 0xff
	X#define BYTEMASK 0xff
	X
	X#define TMO -1
	X#define DUP '\000'
	X#define SOH '\001'
	X#define EOT '\004'
	X#define ACK '\006'
	X#define NAK '\025'
	X#define CAN '\030'
	X#define EEF '\032'
	X#define ESC '\033'
	X
	X#define H_NLENOFF 1
	X#define H_NAMEOFF 2
	X/* 65 <-> 80 is the FInfo structure */
	X#define H_TYPEOFF 65
	X#define H_AUTHOFF 69
	X
	X#define H_LOCKOFF 81
	X#define H_DLENOFF 83
	X#define H_RLENOFF 87
	X#define H_CTIMOFF 91
	X#define H_MTIMOFF 95
	X
	X#define H_OLD_DLENOFF 81
	X#define H_OLD_RLENOFF 85
	X
	X#define TEXT 0
	X#define DATA 1
	X#define RSRC 2
	X#define FULL 3
	X
	Xchar *textension;
	Xint mode, txtmode;
	Xint pre_beta;	/* -o flag; for compatibility with MacTerminal Version -0.15X */
	X
	Xstruct macheader {
	X	char m_name[NAMEBYTES+1];
	X	char m_type[4];
	X	char m_author[4];
	X	long m_datalen;
	X	long m_rsrclen;
	X	long m_createtime;
	X	long m_modifytime;
	X} mh;
	X
	Xstruct filenames {
	X	char f_info[256];
	X	char f_data[256];
	X	char f_rsrc[256];
	X} files;
	X
	Xchar tmpname[16];
	X
	Xint lastack;
	Xchar buf[DATABYTES];
	X
	X/*
	X * macget -- receive file from macintosh using xmodem protocol
	X * Dave Johnson, Brown University Computer Science
	X *
	X * (c) 1984 Brown University 
	X * may be used but not sold without permission
	X *
	X * created ddj 5/22/84 
	X * revised ddj 6/29/84 -- added [-rdu] options
	X * revised ddj 7/16/84 -- protocol changes for MacTerminal Beta Version 0.5X
	X * revised ddj 7/31/84 -- pre-4.2 signal bugs fixed in timedout()
	X * revised ddj 11/7/84 -- renamed send_sync() -> get_sync()
	X * revised wi/ss 12/6/84 -- take off .text extension option "-U"
	X */
	Xchar usage[] = "usage: \"macget [-o] [-rduU] [filename]\"\n";
	X
	Xmain(ac, av)
	Xchar **av;
	X{
	X	char *name;
	X
	X	mode = FULL;
	X	name = "";
	X	ac--; av++;
	X	while (ac) {
	X		if (av[0][0] == '-') {
	X			switch (av[0][1]) {
	X			case 'r':
	X				mode = RSRC;
	X				break;
	X			case 'd':
	X				mode = DATA;
	X				break;
	X			case 'u':
	X				mode = TEXT;
	X				textension = ".text";
	X				break;
	X			case 'U':
	X				mode = TEXT;
	X				textension = "";
	X				break;
	X			case 'o':
	X				pre_beta++;
	X				break;
	X			default:
	X				fprintf(stderr, usage);
	X				exit(1);
	X			}
	X		}
	X		else {
	X			name = av[0];
	X		}
	X		ac--; av++;
	X	}
	X
	X	setup_tty();
	X	if (get_sync() == ACK) {
	X		txtmode = 0;
	X		recv_hdr(name);
	X		if (mode == TEXT) txtmode++;
	X		recv_file(files.f_data, mh.m_datalen, 1);
	X		txtmode = 0;
	X		recv_file(files.f_rsrc, mh.m_rsrclen, 0);
	X	}
	X	reset_tty();
	X}
	X
	Xrecv_hdr(name)
	Xchar *name;
	X{
	X	long get4();
	X	int n;
	X	FILE *fp;
	X	char *np;
	X
	X	strcpy(tmpname, "#machdrXXXXXX");
	X	mktemp(tmpname);
	X	recv_file(tmpname, (long)DATABYTES, 1);
	X
	X	fp = fopen(tmpname, "r");
	X	if (fp == NULL) {
	X		perror("temp file");
	X		cleanup(-1);
	X	}
	X	fread(buf, 1, DATABYTES, fp);
	X	fclose(fp);
	X
	X	if (name && *name) {
	X		n = strlen(name);
	X		if (n > NAMEBYTES) n = NAMEBYTES;
	X		strncpy(mh.m_name, name, n);
	X		mh.m_name[n] = '\0';
	X	}
	X	else {
	X		n = buf[H_NLENOFF] & BYTEMASK;
	X		if (n > NAMEBYTES) n = NAMEBYTES;
	X		strncpy(mh.m_name, buf + H_NAMEOFF, n);
	X		mh.m_name[n] = '\0';
	X	}
	X	for (np = mh.m_name; *np; np++)
	X		if (*np == ' ') *np = '_';
	X
	X	if (mode == FULL) {
	X		sprintf(files.f_info, "%s.info", mh.m_name);
	X		rename(tmpname, files.f_info);
	X		tmpname[0] = '\0';
	X		sprintf(files.f_data, "%s.data", mh.m_name);
	X		sprintf(files.f_rsrc, "%s.rsrc", mh.m_name);
	X	}
	X	else {
	X		unlink(tmpname);
	X		tmpname[0] = '\0';
	X		switch (mode) {
	X		case RSRC:
	X			sprintf(files.f_data, "/dev/null");
	X			sprintf(files.f_rsrc, "%s.rsrc", mh.m_name);
	X			break;
	X
	X		case DATA:
	X			sprintf(files.f_data, "%s.data", mh.m_name);
	X			sprintf(files.f_rsrc, "/dev/null");
	X			break;
	X
	X		case TEXT:
	X			sprintf(files.f_data, "%s%s", mh.m_name, textension);
	X			sprintf(files.f_rsrc, "/dev/null");
	X			break;
	X		}
	X	}
	X
	X	strncpy(mh.m_type, buf + H_TYPEOFF, 4);
	X	strncpy(mh.m_author, buf + H_AUTHOFF, 4);
	X	if (pre_beta) {
	X		mh.m_datalen = get4(buf + H_OLD_DLENOFF);
	X		mh.m_rsrclen = get4(buf + H_OLD_RLENOFF);
	X	}
	X	else {
	X		mh.m_datalen = get4(buf + H_DLENOFF);
	X		mh.m_rsrclen = get4(buf + H_RLENOFF);
	X		mh.m_createtime = get4(buf + H_CTIMOFF);
	X		mh.m_modifytime = get4(buf + H_MTIMOFF);
	X	}
	X}
	X
	Xrecv_file(fname, bytes, more)
	Xchar *fname;
	Xlong bytes;
	Xint more;
	X{
	X	register int status, n;
	X	FILE *outf;
	X	int naks = 0;
	X
	X	lastack = 0;
	X	outf = fopen(fname, "w");
	X	if (outf == NULL) {
	X		perror(fname);
	X		cleanup(-1);
	X	}
	X	for (;;) {
	X		status = rec_read(buf, DATABYTES);
	X		switch (status) {
	X		case EOT:
	X			if (!pre_beta)
	X				tputc(ACK);
	X			if (more)
	X				tputc(NAK);
	X			fclose(outf);
	X			return;
	X		case ACK:
	X			tputc(ACK);
	X			naks = 0;
	X			n = (bytes > DATABYTES) ? DATABYTES : bytes;
	X			bytes -= n;
	X			fwrite(buf, n, 1, outf);
	X			break;
	X		case DUP:
	X			tputc(ACK);
	X			naks = 0;
	X			break;
	X		case NAK:
	X			purge(CHRTIMO);
	X			if (naks++ < RETRIES) {
	X				tputc(NAK);
	X				break;
	X			}
	X			/* fall through */
	X		case CAN:
	X			tputc(CAN);
	X			fclose(outf);
	X			/* unlink fname? */
	X			cleanup(-1);
	X			/* NOTREACHED */
	X		}
	X	}
	X}
	X
	Xget_sync()
	X{
	X	int c;
	X
	X	for (;;) {
	X		c = tgetc(60);
	X		switch (c) {
	X		case ESC:
	X			break;
	X		case CAN:
	X		case EOT:
	X		case TMO:
	X			return c;
	X		default:
	X			continue;
	X		}
	X		c = tgetc(1);
	X		if (c != 'a')
	X			continue;
	X		tputc(ACK);
	X		return ACK;
	X	}
	X}
	X
	Xrec_read(buf, recsize)
	Xchar buf[];
	Xint recsize;
	X{
	X	int c, rec, rec_bar, cksum;
	X
	X	c = tgetc(SOHTIMO);
	X	switch (c) {
	X	case TMO:
	X	default:
	X		return NAK;
	X	case EOT:
	X		return EOT;
	X	case CAN:
	X		return CAN;
	X	case SOH:
	X		/* read header */
	X		rec = tgetc(CHRTIMO);
	X		if (rec == TMO)
	X			return NAK;
	X		rec_bar = tgetc(CHRTIMO);
	X		if (rec_bar == TMO)
	X			return NAK;
	X
	X		/* check header */
	X		if (rec != MAXRECNO - rec_bar) return NAK;
	X
	X		/* fill buffer */
	X		cksum = tgetrec(buf, recsize, LINTIMO);
	X		if (cksum == TMO)
	X			return NAK;
	X
	X		/* get checksum */
	X		c = tgetc(CHRTIMO);
	X		if (c == TMO)
	X			return NAK;
	X		if (c != (cksum & BYTEMASK))
	X			return NAK;
	X
	X		/* check record number */
	X		if (rec == lastack)
	X			return DUP;
	X		if (rec != ((lastack + 1) & MAXRECNO))
	X			return CAN;
	X		else {
	X			lastack = rec;
	X			return ACK;
	X		}
	X	}
	X	/* NOTREACHED */
	X}
	X
	Xpurge(timeout)
	Xint timeout;
	X{
	X	int c;
	X
	X	do {
	X		c = tgetc(timeout);
	X	} while (c != TMO);
	X}
	X
	Xstatic int ttyfd;
	Xstatic FILE *ttyf;
	Xjmp_buf timobuf;
	X
	Xtgetrec(buf, count, timeout)
	Xchar *buf;
	Xint count, timeout;
	X{
	X	char *bp;
	X	int i, cksum;
	X
	X	if (setjmp(timobuf))
	X		return TMO;
	X	
	X	alarm(timeout);
	X	i = fread(buf, 1, count, ttyf);
	X	alarm(0);
	X	if (i != count)
	X		return TMO;
	X	
	X	cksum = 0;
	X	bp = buf;
	X	for (i = 0; i < count; bp++, i++) {
	X		cksum += *bp;
	X		if (txtmode && *bp == '\r')
	X			*bp = '\n';
	X	}
	X	return cksum;
	X}
	X
	Xtgetc(timeout)
	Xint timeout;
	X{
	X	int c;
	X
	X	if (setjmp(timobuf))
	X		return TMO;
	X
	X	alarm(timeout);
	X	c = getc(ttyf);
	X	alarm(0);
	X
	X	if (c == -1)	/* probably hung up or logged off */
	X		return EOT;
	X	else
	X		return c & BYTEMASK;
	X}
	X
	Xtputc(c)
	Xchar c;
	X{
	X	write(ttyfd, &c, 1);
	X}
	X
	Xtimedout()
	X{
	X	signal(SIGALRM, timedout);	/* for pre-4.2 systems */
	X	longjmp(timobuf, 1);
	X}
	X
	Xstatic struct sgttyb otty, ntty;
	X/* should turn messages off */
	X
	Xsetup_tty()
	X{
	X	int cleanup();
	X	int timedout();
	X
	X	ttyf = stdin;
	X	ttyfd = fileno(stdout);
	X	ioctl(ttyfd, TIOCGETP, &otty);
	X	signal(SIGHUP, cleanup);
	X	signal(SIGINT, cleanup);
	X	signal(SIGQUIT, cleanup);
	X	signal(SIGTERM, cleanup);
	X	signal(SIGALRM, timedout);
	X	ntty = otty;
	X	ntty.sg_flags = RAW|ANYP;
	X	ioctl(ttyfd, TIOCSETP, &ntty);
	X}
	X
	Xreset_tty()
	X{
	X	sleep(2);	/* should wait for output to drain */
	X	ioctl(ttyfd, TIOCSETP, &otty);
	X}
	X
	Xcleanup(sig)
	Xint sig;
	X{
	X	if (tmpname[0] != '\0')
	X		unlink(tmpname);
	X	reset_tty();
	X	exit(sig);
	X}
	X
	Xlong
	Xget4(bp)
	Xchar *bp;
	X{
	X	register int i;
	X	long value = 0;
	X
	X	for (i = 0; i < 4; i++) {
	X		value <<= 8;
	X		value |= (*bp & BYTEMASK);
	X		bp++;
	X	}
	X	return value;
	X}
	X
SHAR_EOF
if test 7828 -ne "`wc -c < 'macget.c'`"
then
	echo shar: error transmitting "'macget.c'" '(should have been 7828 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'macget.1w'" '(2699 characters)'
if test -f 'macget.1w'
then
	echo shar: will not over-write existing file "'macget.1w'"
else
sed 's/^	X//' << \SHAR_EOF > 'macget.1w'
	X.TH MACGET 1.WI 
	X.UC 4
	X.SH NAME
	Xmacget \- receive file from macintosh via modem7/macterminal
	X.SH SYNOPSIS
	X.B macget
	X[
	X.B \-rduU
	X] [file]
	X.SH DESCRIPTION
	X.I Macget
	Xreceives a file from a Macintosh running MacTerminal.
	XThe File Transfer settings should specify the "Modem7"
	Xtransfer method and a "MacTerminal" remote system.
	XThis program is designed for use with the 1.1 Release
	Xversion of MacTerminal, but includes a compatibility option for the
	Xold -0.15X Almost-Alpha version.
	X.PP
	XTo use this program, log into the unix system using MacTerminal,
	Xstart macget with the desired options, select "Send File..." from
	Xthe "File" menu, and open the file you wish to send.
	XIf MacTerminal is properly configured, it will put up an indicator
	Xshowing how much of the file has been transfered.
	XSeveral Control-X's may be used to force macget
	Xto give up if the transfer fails.
	X.PP
	XThe optional 
	X.I file
	Xparameter specifies the name to use when creating the unix files,
	Xotherwise the Mac file name is used
	X(with spaces converted to underscores).
	X.PP
	XIf none of the
	X.B \-rdu
	Xflags are specified, 
	X.I macget 
	Xcreates three unix files from the received Mac file:
	X.IB file .info ,
	X.IB file .data ,
	Xand
	X.IB file .rsrc .
	XThis mode is useful for storing Mac files so they can
	Xbe restored later using
	X.IR macput .
	X.PP
	XThe
	X.B \-r
	Xflag specifies 
	X.I resource
	Xmode.
	XOnly 
	X.IB file .rsrc
	Xwill be created, from the Mac file's resource fork.
	X.PP
	XThe
	X.B \-d
	Xflag specifies 
	X.I data
	Xmode.
	XOnly
	X.IB file .data
	Xwill be created, containing the data fork of the Mac file.
	X.PP
	XThe 
	X.B \-u
	Xflag requests 
	X.I unix
	Xmode, in which carriage returns are converted into
	Xunix newline characters, and the unix file
	X.IB file .text
	Xis created.
	XA file saved from Mac applications as "text only" can be transfered
	Xusing this option to convert it to a normal unix text file.
	X.PP
	XThe 
	X.B \-U
	Xflag is the same as the 
	X.B \-u
	Xflag except that the result filename has no .text part.
	X.PP
	XThe 
	X.B \-o
	Xflag specifies "old" (version -0.15X) MacTerminal compatibility mode.
	XYou must manually disable XON/XOFF flow control in this version to
	Xperform file transfer; this is done automatically in the newer versions.
	X.SH SEE ALSO
	Xmacput(local)
	X.SH BUGS
	XThe modem7 protocol will not work over flow controlled communication lines,
	Xsome terminal concentrators, or when using rlogin.
	X.PP
	XMacTerminal Beta versions 0.5 and 0.9 incorrectly calculate record checksums
	Xunder certain circumstances, preventing some files from being successfully
	Xtransfered; this bug has been fixed in the released version 1.1.
	XThis program is otherwise compatible with all versions of MacTerminal 
	Xsince 0.5 (and -0.15X by using the -o option).
	X.SH AUTHOR
	XDave Johnson, Brown 7/31/84
	X
SHAR_EOF
if test 2699 -ne "`wc -c < 'macget.1w'`"
then
	echo shar: error transmitting "'macget.1w'" '(should have been 2699 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(211 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'Makefile'
	XCFLAGS=-DNO_RENAME
	X
	Xmacget:	macget.o
	X	cc  macget.o -o macget
	X
	Xmacget-install:	macget
	X	mv macget /usr/local/bin/macget
	X
	Xmacget-man-install:	macget.1w
	X	cp macget.1w /usr/man/man1/macget.1w
	X	man macget >/dev/null&
SHAR_EOF
if test 211 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 211 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0