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:
# macput.c
# macput.1w
# Makefile
# This archive created: Tue Jul 23 08:25:38 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'macput.c'" '(8781 characters)'
if test -f 'macput.c'
then
echo shar: will not over-write existing file "'macput.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'macput.c'
X/*
X
XHere is the source for the current incarnation of macput . . . .
XIt is compatible with the 1.1 Release version of MacTerminal,
Xthough in case you still need to use the -0.15X version, there's
Xthe "-o" option to provide compatibility. Versions 0.5 and 0.9
Xhave a bug in the record checksum calculation which will break
Xfile transfers, so 1.1 is recommended.
X
XPlease pass any improvements/bug fixes on to me, and
Xif you know of any good protocols for use on a flow-controlled
Xline, let me know.
X
X Dave Johnson
X ddj%brown@csnet-relay.arpa
X Brown University Computer Science
X
X*/
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <sgtty.h>
X#include <time.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/timeb.h>
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 ACKTIMO 10
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
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
Xint recno;
Xchar buf[DATABYTES];
X
X/*
X * macput -- send file to 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 6/17/84
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 7/31/84 -- moved forge_info() call ahead of send_sync()
X * revised ddj 11/6/84 -- added sleep(5) after send_sync to give mac time to
X * turn off xon mode, set up sio chip, and put up progress indicator
X */
Xchar usage[] =
X "usage: \"macput [-o] [-rdu] [-t type] [-a author] [-n name] filename\"\n";
X
Xmain(ac, av)
Xchar **av;
X{
X int n;
X char *filename;
X
X if (ac == 1) {
X fprintf(stderr, usage);
X exit(1);
X }
X
X mode = FULL;
X ac--; av++;
X while (ac) {
X if (av[0][0] == '-') {
X switch (av[0][1]) {
X case 'r':
X mode = RSRC;
X strncpy(mh.m_type, "APPL", 4);
X strncpy(mh.m_author, "CCOM", 4);
X break;
X case 'u':
X mode = TEXT;
X strncpy(mh.m_type, "TEXT", 4);
X strncpy(mh.m_author, "MACA", 4);
X break;
X case 'd':
X mode = DATA;
X strncpy(mh.m_type, "TEXT", 4);
X strncpy(mh.m_author, "????", 4);
X break;
X case 'n':
X if (ac > 1) {
X ac--; av++;
X n = strlen(av[0]);
X if (n > NAMEBYTES) n = NAMEBYTES;
X strncpy(mh.m_name, av[0], n);
X mh.m_name[n] = '\0';
X break;
X }
X else goto bad_usage;
X case 't':
X if (ac > 1) {
X ac--; av++;
X strncpy(mh.m_type, av[0], 4);
X break;
X }
X else goto bad_usage;
X case 'a':
X if (ac > 1) {
X ac--; av++;
X strncpy(mh.m_author, av[0], 4);
X break;
X }
X else goto bad_usage;
X case 'o':
X pre_beta++;
X break;
X default:
Xbad_usage:
X fprintf(stderr, usage);
X exit(1);
X }
X }
X else {
X filename = av[0];
X }
X ac--; av++;
X }
X
X setup_tty();
X find_files(filename, mode);
X if (mode != FULL)
X forge_info();
X
X if (send_sync() == ACK) {
X txtmode = 0;
X sleep(5);
X send_file(files.f_info, 1);
X
X if (mode != FULL)
X unlink(files.f_info);
X
X if (mode == TEXT) txtmode++;
X send_file(files.f_data, 1);
X
X txtmode = 0;
X send_file(files.f_rsrc, 0);
X }
X reset_tty();
X}
X
Xfind_files(filename, mode)
Xchar *filename;
X{
X int n, tdiff;
X struct tm *tp;
X struct timeb tbuf;
X struct stat stbuf;
X
X sprintf(files.f_data, "%s.data", filename);
X sprintf(files.f_rsrc, "%s.rsrc", filename);
X
X if (mode == FULL) {
X sprintf(files.f_info, "%s.info", filename);
X if (stat(files.f_info, &stbuf) != 0) {
X perror(files.f_info);
X cleanup(-1);
X }
X return;
X }
X else {
X strcpy(files.f_info, "#machdrXXXXXX");
X mktemp(files.f_info);
X }
X
X if (mode == RSRC) {
X strcpy(files.f_data, "/dev/null");
X if (stat(files.f_rsrc, &stbuf) != 0) {
X strcpy(files.f_rsrc, filename);
X if (stat(files.f_rsrc, &stbuf) != 0) {
X perror(files.f_rsrc);
X cleanup(-1);
X }
X }
X mh.m_datalen = 0;
X mh.m_rsrclen = stbuf.st_size;
X }
X else {
X strcpy(files.f_rsrc, "/dev/null");
X if (stat(files.f_data, &stbuf) != 0) {
X sprintf(files.f_data, "%s.text", filename);
X if (stat(files.f_data, &stbuf) != 0) {
X strcpy(files.f_data, filename);
X if (stat(files.f_data, &stbuf) != 0) {
X perror(files.f_data);
X cleanup(-1);
X }
X }
X }
X mh.m_datalen = stbuf.st_size;
X mh.m_rsrclen = 0;
X }
X
X if (!pre_beta) {
X ftime(&tbuf);
X tp = localtime(&tbuf.time);
X tdiff = TIMEDIFF - tbuf.timezone * 60;
X if (tp->tm_isdst)
X tdiff += 60 * 60;
X mh.m_createtime = stbuf.st_mtime + tdiff;
X mh.m_modifytime = stbuf.st_mtime + tdiff;
X }
X
X if (mh.m_name[0] == '\0') {
X n = strlen(filename);
X if (n > NAMEBYTES) n = NAMEBYTES;
X strncpy(mh.m_name, filename, n);
X mh.m_name[n] = '\0';
X }
X}
X
Xforge_info()
X{
X int n;
X char *np;
X FILE *fp;
X
X for (np = mh.m_name; *np; np++)
X if (*np == '_') *np = ' ';
X
X buf[H_NLENOFF] = n = np - mh.m_name;
X strncpy(buf + H_NAMEOFF, mh.m_name, n);
X strncpy(buf + H_TYPEOFF, mh.m_type, 4);
X strncpy(buf + H_AUTHOFF, mh.m_author, 4);
X if (pre_beta) {
X put4(buf + H_OLD_DLENOFF, mh.m_datalen);
X put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
X }
X else {
X put4(buf + H_DLENOFF, mh.m_datalen);
X put4(buf + H_RLENOFF, mh.m_rsrclen);
X put4(buf + H_CTIMOFF, mh.m_createtime);
X put4(buf + H_MTIMOFF, mh.m_modifytime);
X }
X fp = fopen(files.f_info, "w");
X if (fp == NULL) {
X perror("temp file");
X cleanup(-1);
X }
X fwrite(buf, 1, DATABYTES, fp);
X fclose(fp);
X}
X
Xsend_sync()
X{
X int c, i;
X
X for (i = 0; i < 3; i++) {
X tputc(ESC);
X tputc('a');
X while ((c = tgetc(ACKTIMO)) != TMO) {
X switch (c) {
X case CAN:
X case EOT:
X case ACK:
X return c;
X default:
X continue;
X }
X }
X fprintf(stderr, "starting handshake timeout\r\n");
X }
X fprintf(stderr, "giving up\r\n");
X return CAN;
X}
X
Xsend_file(fname, more)
Xchar *fname;
Xint more;
X{
X register int status, i, n;
X FILE *inf;
X
X inf = fopen(fname, "r");
X if (inf == NULL) {
X perror(fname);
X cleanup(-1);
X }
X recno = 1;
X for (;;) {
X n = fread(buf, 1, DATABYTES, inf);
X if (n > 0) {
X for (i = 0; i < RETRIES; i++) {
X send_rec(buf, DATABYTES);
X status = tgetc(ACKTIMO);
X if (status != NAK)
X break;
X }
X if (status == NAK || status == CAN) {
X fclose(inf);
X cleanup(-1);
X /* NOTREACHED */
X }
X }
X if (n < DATABYTES) {
X tputc(EOT);
X if (!pre_beta) {
X status = tgetc(ACKTIMO);
X }
X if (more) {
X status = tgetc(ACKTIMO);
X }
X return;
X }
X recno++;
X recno &= MAXRECNO;
X }
X}
X
Xsend_rec(buf, recsize)
Xchar buf[];
Xint recsize;
X{
X int i, cksum;
X char *bp;
X
X cksum = 0;
X bp = buf;
X for (i = 0; i < recsize; i++, bp++) {
X if (txtmode && *bp == '\n')
X *bp = '\r';
X cksum += *bp;
X }
X
X tputc(SOH);
X tputc((char)recno);
X tputc((char)(MAXRECNO - recno));
X tputrec(buf, recsize);
X tputc((char)cksum);
X}
X
Xstatic int ttyfd;
Xstatic FILE *ttyf;
Xstatic jmp_buf timobuf;
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
Xtputrec(buf, count)
Xchar *buf;
Xint count;
X{
X write(ttyfd, buf, count);
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 if (ttyf != NULL) {
X sleep(2); /* should wait for output to drain */
X ioctl(ttyfd, TIOCSETP, &otty);
X }
X}
X
Xcleanup(sig)
Xint sig;
X{
X reset_tty();
X exit(sig);
X}
X
Xput4(bp, value)
Xchar *bp;
Xlong value;
X{
X register int i, c;
X
X for (i = 0; i < 4; i++) {
X c = (value >> 24) & BYTEMASK;
X value <<= 8;
X *bp++ = c;
X }
X}
X
SHAR_EOF
if test 8781 -ne "`wc -c < 'macput.c'`"
then
echo shar: error transmitting "'macput.c'" '(should have been 8781 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'macput.1w'" '(3396 characters)'
if test -f 'macput.1w'
then
echo shar: will not over-write existing file "'macput.1w'"
else
sed 's/^ X//' << \SHAR_EOF > 'macput.1w'
X.TH MACPUT.WI "8 Nov 1984"
X.UC 4
X.SH NAME
Xmacput \- send file to macintosh via modem7/macterminal
X.SH SYNOPSIS
X.B macput
Xfile
X.br
X.B macput
X[
X.B \-rdu
X] file
X[
X.B \-t
Xtype
X]
X[
X.B \-a
Xauthor
X]
X[
X.B \-n
Xname
X]
X.SH DESCRIPTION
X.I Macput
Xsends a file to 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,
Xand run macput specifying the desired options and one file to be sent.
XIf MacTerminal is properly configured, it will recognize that a file
Xis arriving on the serial line and put up an indicator showing how
Xmuch of the file has been sent.
XSeveral Control-X's may be used to force macput
Xto give up if the transfer fails.
X.PP
XIf none of the
X.B \-rdu
Xflags are specified,
X.I macput
Xsends three unix files to the Mac:
X.IB file .info ,
X.IB file .data ,
Xand
X.IB file .rsrc .
XThese specify the three parts of one Mac file: the .data file
Xbecomes the data fork, the .rsrc file becomes the resource fork,
Xand the .info file specifies the sizes of the two forks, as well
Xas the file name, file type, creation date, and other information.
XThis is useful for returning files to the Mac which were stored
Xusing macget.
X.PP
XThe
X.B \-r
Xflag specifies
X.I resource
Xmode.
XEither
X.IB file .rsrc
Xor
X.I file
Xwill be sent to the Mac, along with a forged
X.B .info
Xfile and an empty
X.B .data
Xfile.
XThe file sent becomes the resource fork of the Mac file.
X.PP
XThe
X.B \-d
Xflag specifies
X.I data
Xmode.
XEither
X.IB file .data
X,
X.IB file .text
Xor
X.I file
Xwill be sent to the Mac, along with a forged
X.B .info
Xfile and an empty
X.B .rsrc
Xfile.
XThe file sent becomes the data fork of the Mac file.
X.PP
XThe
X.B \-u
Xflag requests
X.I unix
Xmode, which is the same as
X.I data
Xmode except unix newline characters are converted
Xinto carriage returns.
XHuman-readable unix text files sent to the Mac using this option
Xwill be compatible with applications which expect "text only" files.
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.PP
XThe remaining options serve to override the default
Xfile type, author, and file name to be used on the Mac.
XThe default type and author for
X.I resource
Xmode are "APPL" and "CCOM".
X.I data
Xmode defaults are "TEXT", "????", and
X.I unix
Xmode defaults are "TEXT" and "MACA".
X.SH SEE ALSO
Xmacget(local)
X.SH BUGS
XThe modem7 protocol will not work over flow controlled communication lines,
Xsome terminal concentrators, or when using rlogin.
X.PP
XDoesn't set the bundle bit on resource files,
Xto incorporate any icons into the Desk Top.
XUse setfile to set the bundle bit.
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 FEATURES
XProperly initializes the Creation Date.
X.SH AUTHOR
XDave Johnson, Brown 7/31/84
X
SHAR_EOF
if test 3396 -ne "`wc -c < 'macput.1w'`"
then
echo shar: error transmitting "'macput.1w'" '(should have been 3396 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(191 characters)'
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^ X//' << \SHAR_EOF > 'Makefile'
Xmacput: macput.o
X cc macput.o -o macput
X
Xmacput-install: macput
X mv macput /usr/local/bin/macput
X
Xmacput-man-install: macput.1w
X cp macput.1w /usr/man/man1/macput.1w
X man macput >/dev/null&
SHAR_EOF
if test 191 -ne "`wc -c < 'Makefile'`"
then
echo shar: error transmitting "'Makefile'" '(should have been 191 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0