home *** CD-ROM | disk | FTP | other *** search
- /*
- * (originally macput) -- send file to Macintosh using MacBinary XMODEM protocol
- * Dave Johnson, Brown University Computer Science
- *
- * (c) 1984 Brown University
- * may be used but not sold without permission
- *
- */
-
- /* To compile:
- cc -O -o macbput macbput.c
- (Sun 4.2 BSD) cc -O -DSUNBSD42 -o macbput macbput.c
- (System V) cc -O -DSYSV -o macbput macbput.c
-
- Latest modifications 10/20/88 by Trissel -
-
- 1. General cleanup by removal of unused definitions and headers.
- 2. Added #ifdefs to support System V and BSD 4.2 Sun compilation.
- 3. Removed ancient Macterminal Beta 0.5X code.
- 4. Fixed bad bug where XMODEM block count was not bumped up
- after the first fork transfer.
-
- Dave Trissel
- Motorola Inc.
- ut-sally!oakhill!davet
-
- This code is fundamentally from two earlier programmers:
-
- Jon Hueras
- Symantec/THINK Technologies
- singer@endor.harvard.edu
-
- who added 2-Byte CRC capability to code from:
-
- Dave Johnson
- ddj%brown@csnet-relay.arpa
- Brown University Computer Science
-
- who did the initial MacTerminal 1.1 transfer protocol.
- */
-
- /* If you have System V define the following: */
- /* #define SYSV */
-
- /* Sun BSD 4.2 systems should define the following: */
- /* #define SUNBSD42 */
-
- #include <stdio.h>
- #include <signal.h>
- #include <setjmp.h>
- #ifdef SYSV
- #include <termio.h>
- #else
- #include <sgtty.h>
- #endif
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #ifdef SUNBSD42
- /* RAW is no longer being found on latest Sun system (??) (Trissel) */
- #define RAW 0x20
- #endif
-
- #define RECORDBYTES 132
- #define DATABYTES 128
- #define NAMEBYTES 63
-
- #define RETRIES 10
- #define ACKTIMO 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
- /* 65 <-> 80 is the FInfo structure */
- #define H_TYPEOFF 65
- #define H_AUTHOFF 69
-
- #define H_LOCKOFF 81
- #define H_DLENOFF 83
- #define H_RLENOFF 87
- #define H_CTIMOFF 91
- #define H_MTIMOFF 95
-
- #define H_OLD_DLENOFF 81
- #define H_OLD_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];
- long m_datalen;
- long m_rsrclen;
- long m_createtime;
- long m_modifytime;
- } mh;
-
- struct filenames {
- char f_info[256];
- char f_data[256];
- char f_rsrc[256];
- } files;
-
- int recno, crc;
- char buf[DATABYTES];
-
- char usage[] =
- "usage: \"macbput [-rdu] [-t type] [-c creator] [-n name] filename\"\n";
-
- main(ac, av)
- char **av;
- {
- int n;
- char *filename;
-
- if (ac == 1) {
- fprintf(stderr, usage);
- exit(1);
- }
-
- mode = FULL;
- ac--; av++;
- while (ac) {
- if (av[0][0] == '-') {
- switch (av[0][1]) {
- case 'r':
- mode = RSRC;
- strncpy(mh.m_type, "????", 4);
- strncpy(mh.m_author, "????", 4);
- break;
- case 'u':
- mode = TEXT;
- strncpy(mh.m_type, "TEXT", 4);
- strncpy(mh.m_author, "MACA", 4);
- break;
- case 'd':
- mode = DATA;
- strncpy(mh.m_type, "????", 4);
- strncpy(mh.m_author, "????", 4);
- break;
- case 'n':
- if (ac > 1) {
- ac--; av++;
- n = strlen(av[0]);
- if (n > NAMEBYTES) n = NAMEBYTES;
- strncpy(mh.m_name, av[0], n);
- mh.m_name[n] = '\0';
- break;
- }
- else goto bad_usage;
- case 't':
- if (ac > 1) {
- ac--; av++;
- strncpy(mh.m_type, av[0], 4);
- break;
- }
- else goto bad_usage;
- case 'c':
- if (ac > 1) {
- ac--; av++;
- strncpy(mh.m_author, av[0], 4);
- break;
- }
- else goto bad_usage;
- default:
- bad_usage:
- fprintf(stderr, usage);
- exit(1);
- }
- }
- else {
- filename = av[0];
- }
- ac--; av++;
- }
-
- setup_tty();
- find_files(filename, mode);
- if (mode != FULL)
- forge_info();
-
- if (send_sync()) {
- recno = 1;
- txtmode = 0;
- send_file(files.f_info, 1);
-
- if (mode != FULL)
- unlink(files.f_info);
-
- if (mode == TEXT) txtmode++;
- send_file(files.f_data, 1);
-
- txtmode = 0;
- send_file(files.f_rsrc, 0);
- }
- reset_tty();
- }
-
- find_files(filename, mode)
- char *filename;
- {
- int n, tdiff;
- struct stat stbuf;
-
- sprintf(files.f_data, "%s.data", filename);
- sprintf(files.f_rsrc, "%s.rsrc", filename);
-
- if (mode == FULL) {
- sprintf(files.f_info, "%s.info", filename);
- if (stat(files.f_info, &stbuf) != 0) {
- perror(files.f_info);
- cleanup(-1);
- }
- return;
- }
- else {
- strcpy(files.f_info, "#machdrXXXXXX");
- mktemp(files.f_info);
- }
-
- if (mode == RSRC) {
- strcpy(files.f_data, "/dev/null");
- if (stat(files.f_rsrc, &stbuf) != 0) {
- strcpy(files.f_rsrc, filename);
- if (stat(files.f_rsrc, &stbuf) != 0) {
- perror(files.f_rsrc);
- cleanup(-1);
- }
- }
- mh.m_datalen = 0;
- mh.m_rsrclen = stbuf.st_size;
- }
- else {
- strcpy(files.f_rsrc, "/dev/null");
- if (stat(files.f_data, &stbuf) != 0) {
- sprintf(files.f_data, "%s.text", filename);
- if (stat(files.f_data, &stbuf) != 0) {
- strcpy(files.f_data, filename);
- if (stat(files.f_data, &stbuf) != 0) {
- perror(files.f_data);
- cleanup(-1);
- }
- }
- }
- mh.m_datalen = stbuf.st_size;
- mh.m_rsrclen = 0;
- }
-
- if (mh.m_name[0] == '\0') {
- n = strlen(filename);
- if (n > NAMEBYTES) n = NAMEBYTES;
- strncpy(mh.m_name, filename, n);
- mh.m_name[n] = '\0';
- }
- }
-
- forge_info()
- {
- int n;
- char *np;
- FILE *fp;
-
- for (np = mh.m_name; *np; np++)
- if (*np == '_') *np = ' ';
-
- buf[H_NLENOFF] = n = np - mh.m_name;
- strncpy(buf + H_NAMEOFF, mh.m_name, n);
- strncpy(buf + H_TYPEOFF, mh.m_type, 4);
- strncpy(buf + H_AUTHOFF, mh.m_author, 4);
- put4(buf + H_DLENOFF, mh.m_datalen);
- put4(buf + H_RLENOFF, mh.m_rsrclen);
- put4(buf + H_CTIMOFF, mh.m_createtime);
- put4(buf + H_MTIMOFF, mh.m_modifytime);
- fp = fopen(files.f_info, "w");
- if (fp == NULL) {
- perror("temp file");
- cleanup(-1);
- }
- fwrite(buf, 1, DATABYTES, fp);
- fclose(fp);
- }
-
- send_sync()
- {
- int c;
-
- tputc(ESC);
- tputc('b');
-
- for (;;) {
-
- if ((c = tgetc(ACKTIMO)) == TMO)
- {
- return(0);
- }
-
- if (c == NAK)
- {
- return(1);
- }
-
- if (c == 'C') {
- crc++;
- return(1);
- }
- }
- }
-
- send_file(fname, more)
- char *fname;
- int more;
- {
- register int status, i, n;
- FILE *inf;
-
- inf = fopen(fname, "r");
- if (inf == NULL) {
- perror(fname);
- cleanup(-1);
- }
- for (;;) {
- n = fread(buf, 1, DATABYTES, inf);
- if (n > 0) {
- for (i = 0; i < RETRIES; i++) {
- send_rec(buf, DATABYTES);
- while ((status = tgetc(ACKTIMO)) != ACK && status != NAK && status != CAN);
- if (status != NAK)
- break;
- }
- if (status != ACK) {
- if (status != CAN)
- while ((status = tgetc(ACKTIMO)) != CAN);
- fclose(inf);
- cleanup(-1);
- /* NOTREACHED */
- }
- }
- if (n < DATABYTES) {
- if (!more) {
- tputc(EOT);
- tgetc(ACKTIMO);
- }
- return;
- }
- recno++;
- recno &= MAXRECNO;
- }
- }
-
- send_rec(buf, recsize)
- char buf[];
- int recsize;
- {
- int i, cksum;
- char *bp;
-
- if (txtmode || !crc) {
- cksum = 0;
- bp = buf;
- for (i = 0; i < recsize; i++, bp++) {
- if (txtmode && *bp == '\n')
- *bp = '\r';
- cksum += *bp;
- }
- }
-
- if (crc)
- cksum = calcrc(buf, recsize);
-
- tputc(SOH);
- tputc((char) recno);
- tputc((char) (MAXRECNO - recno));
- tputrec(buf, recsize);
-
- if (crc) {
- tputc((char) (cksum >> 8));
- tputc((char) cksum);
- } else
- tputc((char) cksum);
- }
-
- static int ttyfd;
- static FILE *ttyf;
- static jmp_buf timobuf;
-
- tgetc(timeout)
- int timeout;
- {
- int c;
-
- if (setjmp(timobuf))
- return TMO;
-
- alarm(timeout);
- c = getc(ttyf);
- alarm(0);
-
- if (c == -1) /* probably hung up or logged off */
- return EOT;
- else
- return c & BYTEMASK;
- }
-
- tputrec(buf, count)
- char *buf;
- int count;
- {
- write(ttyfd, buf, count);
- }
-
- tputc(c)
- char c;
- {
- write(ttyfd, &c, 1);
- }
-
- timedout()
- {
- signal(SIGALRM, timedout); /* for pre-4.2 systems */
- longjmp(timobuf, 1);
- }
-
- #ifdef SYSV
- static struct termio otty, ntty;
- #else
- static struct sgttyb otty, ntty;
- #endif
-
- /* should turn messages off */
-
- setup_tty()
- {
- int cleanup();
- int timedout();
-
- ttyf = stdin;
- ttyfd = fileno(stdout);
- #ifdef SYSV
- ioctl(ttyfd, TCGETA, &otty); /* get termio info */
- #else
- ioctl(ttyfd, TIOCGETP, &otty);
- #endif
- signal(SIGHUP, cleanup);
- signal(SIGINT, cleanup);
- signal(SIGQUIT, cleanup);
- signal(SIGTERM, cleanup);
- signal(SIGALRM, timedout);
- ntty = otty;
- #ifdef SYSV
- ntty.c_iflag = BRKINT; /* only interrupt on break */
- ntty.c_oflag = 0; /* no output processing */
- ntty.c_cflag |= CS8; /* 8 bit characters */
- ntty.c_lflag = 0; /* no echoing */
- ntty.c_cc[VEOF] = 1; /* "MIN" minimum chars before input */
- ntty.c_cc[VEOL] = 1; /* "TIME" maximum .1 secs before feed */
- ioctl(ttyfd, TCSETAF, &ntty); /* set mode and flush input */
- #else
- ntty.sg_flags = RAW;
- ioctl(ttyfd, TIOCSETP, &ntty);
- #endif
- }
-
- reset_tty()
- {
- if (ttyf != NULL) {
- #ifdef SYSV
- ioctl(ttyfd, TCSETAF, &otty); /* reset after output drains */
- #else
- sleep (5); /* wait for output to drain */
- ioctl(ttyfd, TIOCSETP, &otty);
- #endif
- }
- }
-
- cleanup(sig)
- int sig;
- {
- reset_tty();
- exit(sig);
- }
-
- put4(bp, value)
- char *bp;
- long value;
- {
- register int i, c;
-
- for (i = 0; i < 4; i++) {
- c = (value >> 24) & BYTEMASK;
- value <<= 8;
- *bp++ = c;
- }
- }
-
- int calcrc(ptr, count)
- char *ptr;
- int count;
- {
- int crc, i;
-
- crc = 0;
- while (--count >= 0) {
- crc ^= ((int) *ptr++) << 8;
- for (i = 0; i < 8; ++i)
- if (crc & 0x8000)
- crc = crc << 1 ^ 0x1021;
- else
- crc <<= 1;
- }
- return (crc & 0xFFFF);
- }
-