Path: utzoo!utgpu!water!watmath!uunet!lll-winken!pacbell!att!mtune!ethos!pcid!gizzmo!fthood!egray From: egray@fthood.UUCP Newsgroups: unix-pc.sources Subject: xmodem v3.6 (2 of 3) Message-ID: <6800078@fthood> Date: 14 Jul 88 19:05:00 GMT Lines: 1760 Nf-ID: #N:fthood:6800078:000:51200 Nf-From: fthood.UUCP!egray Jul 14 14:05:00 1988 This is part 2 of 3 to Steve Grandi's xmodem v3.6 package Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------- #! /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: # misc.c # receive.c # send.c # xmodem.c # xmodem.h # xmodem.1 # This archive created: Thu Jul 14 13:12:46 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'misc.c'" '(4381 characters)' if test -f 'misc.c' then echo shar: "will not over-write existing file 'misc.c'" else sed 's/^X//' << \SHAR_EOF > 'misc.c' 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#ifdef LOCAL X fprintf(stderr, "\n\tr <-- Receive Binary"); X#else /* LOCAL */ X fprintf(stderr, "\n\trb <-- Receive Binary"); X#endif /* LOCAL */ X fprintf(stderr, "\n\trt <-- Receive Text"); X fprintf(stderr, "\n\tra <-- Receive Apple macintosh text"); X#ifdef LOCAL X fprintf(stderr, "\n\ts <-- Send Binary"); X#else /* LOCAL */ X fprintf(stderr, "\n\tsb <-- Send Binary"); X#endif /* LOCAL */ 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#ifdef LOCAL X fprintf(stderr, "\n\tc <-- Select checksum mode on receive"); X#else /* LOCAL */ X fprintf(stderr, "\n\tc <-- Select CRC mode on receive"); X#endif /* LOCAL */ 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 } SHAR_EOF if test 4381 -ne "`wc -c < 'misc.c'`" then echo shar: "error transmitting 'misc.c'" '(should have been 4381 characters)' fi fi echo shar: "extracting 'receive.c'" '(12880 characters)' if test -f 'receive.c' then echo shar: "will not over-write existing file 'receive.c'" else sed 's/^X//' << \SHAR_EOF > 'receive.c' 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= 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} SHAR_EOF if test 12880 -ne "`wc -c < 'receive.c'`" then echo shar: "error transmitting 'receive.c'" '(should have been 12880 characters)' fi fi echo shar: "extracting 'send.c'" '(9886 characters)' if test -f 'send.c' then echo shar: "will not over-write existing file 'send.c'" else sed 's/^X//' << \SHAR_EOF > 'send.c' X/** send a file **/ X X/* X * Operation of this routine depends on on MDM7BAT and YMDMBAT flags. X * X * If "name" is NULL; close out the BATCH send. X */ X X#include "xmodem.h" X Xsfile(name) Xchar *name; X { X X char *sectdisp(); X time_t time(); X char *strcpy(); X char *unix_cpm(); X char *cpmify(); X long countnl(); X X extern unsigned short crctab[1< NAKMAX) X { X if (MDM7BAT && startup) X { X sendbyte(ACK); sendbyte(EOT); X } X error("Remote System Not Responding", TRUE); X } X X if ((firstchar & 0x7f) == CAN) X if (readbyte(3) == CAN) X error("Send cancelled at user's request",TRUE); X X if (firstchar == CRCCHR) X { X CRCMODE = TRUE; X if (!closeout) X logit("CRC mode requested\n"); X if (readbyte(1) == KCHR) X { X buf1024 = TRUE; X logit("Receiver invoked 1K packet mode\n"); X } X } X } X while (firstchar != NAK && firstchar != CRCCHR); X X if (MDM7BAT && closeout) /* close out MODEM7 batch */ X { X sendbyte(ACK); sendbyte (EOT); X flushin(); readbyte(2); /* flush junk */ X return; X } X X if (MDM7BAT && startup) /* send MODEM7 file name */ X { X if (send_name(unix_cpm(name)) == -1) X { X attempts = 0; X goto restart; X } X startup = FALSE; X attempts = 0; X goto restart; X } X X sectnum = 1; X X if (YMDMBAT) /* Fudge for YMODEM transfer (to send name packet) */ X { X sectnum = 0; X bufsize = 128; X filepack = TRUE; X } X X attempts = sentsect = 0; X start = time((time_t *) 0); X X do /* outer packet building/sending loop; loop till whole file is sent */ X { X X if (closeout && YMDMBAT && sectnum == 1) /* close out YMODEM */ X return; X X if (YMDMBAT && sectnum == 1) /* get set to send YMODEM data packets */ X { X bufsize = buf1024 ? 1024 : 128; X X do /* establish handshaking again */ X { X while (((firstchar=readbyte(2)) != CRCCHR) && (firstchar != NAK) && (firstchar != CAN)) X if (++attempts > ERRORMAX) X error("YMODEM protocol botch, C expected", TRUE); X if ((firstchar&0x7f) == CAN) X if (readbyte(3) == CAN) X error("Send cancelled at User's request", TRUE); X } X while ((firstchar != CRCCHR) && (firstchar != NAK)); X X attempts = 0; X } X X if ((bufsize == 1024) && (attempts > KSWMAX)) X { X logit("Reducing packet size to 128 due to excessive errors\n"); X bufsize = 128; X } X X if ((bufsize == 1024) && ((expsect - sentsect) < 8)) X { X logit("Reducing packet size to 128 for tail end of file\n"); X bufsize = 128; X } X X if (sectnum > 0) /* data packet */ X { X for (bufctr=0; bufctr < bufsize;) X { X if (nlflag) X { X buff[bufctr++] = LF; /* leftover newline */ X nlflag = FALSE; X } X if (getbyte(fd, &c) == EOF) X { X sendfin = TRUE; /* this is the last sector */ X if (!bufctr) /* if EOF on sector boundary */ X break; /* avoid sending extra sector */ X buff[bufctr++] = CTRLZ; /* pad with Ctrl-Z for CP/M EOF (even do for binary files) */ X continue; X } X X if (tmode && c == LF) /* text mode & Unix newline? */ X { X buff[bufctr++] = CR; /* insert carriage return */ X if (bufctr < bufsize) X buff[bufctr++] = LF; /* insert LF */ X else X nlflag = TRUE; /* insert on next sector */ X } X else if (amode && c == LF) /* Apple mode & Unix newline? */ X buff[bufctr++] = CR; /* substitute CR */ X else X buff[bufctr++] = c; /* copy the char without change */ X } X X if (!bufctr) /* if EOF on sector boundary */ X break; /* avoid sending empty sector */ X } X X else /* YMODEM filename packet */ X { X for (bufctr=0; bufctr> 8) & 0xff); X } X } X X bbufcnt = 0; /* start building block to be sent */ X blockbuf[bbufcnt++] = (bufsize == 1024) ? STX : SOH; /* start of packet char */ X blockbuf[bbufcnt++] = sectnum; /* current sector # */ X blockbuf[bbufcnt++] = ~sectnum; /* and its complement */ X X checksum = 0; /* initialize checksum */ X for (bufctr=0; bufctr < bufsize; bufctr++) X { X blockbuf[bbufcnt++] = buff[bufctr]; X X if (CRCMODE) X checksum = (checksum<>(W-B)) ^ buff[bufctr]]; X X else X checksum = ((checksum+buff[bufctr]) & 0xff); X } X X if (CRCMODE) /* put in CRC */ X { X checksum &= 0xffff; X blockbuf[bbufcnt++] = ((checksum >> 8) & 0xff); X blockbuf[bbufcnt++] = (checksum & 0xff); X } X else /* put in checksum */ X blockbuf[bbufcnt++] = checksum; X X attempts = 0; X X do /* inner packet loop */ X { X X writebuf(blockbuf, bbufcnt); /* write the block */ X flushin(); /* purge anything in input queue */ X X if (DEBUG) X fprintf (LOGFP, "DEBUG: %d byte Packet %02xh (%02xh) sent, checksum %02xh %02xh\n", X bbufcnt, blockbuf[1]&0xff, blockbuf[2]&0xff, blockbuf[bufsize+3]&0xff, blockbuf[bufsize+4]&0xff); X X attempts++; X sendresp = readbyte(10); /* get response from remote */ X X if (sendresp != ACK) X { X if (sendresp == TIMEOUT) X { X logitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1)); X } X else if (sendresp == NAK) X { X logitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1)); X } X else X { X logitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1)); X } X } X } X while((sendresp != ACK) && (attempts < ERRORMAX)); /* close of inner loop */ X X sectnum++; /* increment to next sector number */ X if (!filepack) X sentsect += (bufsize == 128) ? 1 : 8; X filepack = FALSE; X } X while (!sendfin && ( attempts < ERRORMAX)); /* end of outer loop */ X X if (attempts >= ERRORMAX) X { X sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); X error ("Too many errors in transmission", TRUE); X } X X attempts = 0; X sendbyte(EOT); /* send 1st EOT to close down transfer */ X X while ((readbyte(15) != ACK) && (attempts++ < EOTMAX)) /* wait for ACK of EOT */ X { X if (attempts > 1) X logitarg("EOT not ACKed, try %d\n", attempts); X sendbyte(EOT); X } X X if (attempts >= RETRYMAX) X error("Remote System Not Responding on Completion", TRUE); X X close(fd); X X logit("Send Complete\n"); X prtime(sentsect, time((time_t *) 0) - start); X } SHAR_EOF if test 9886 -ne "`wc -c < 'send.c'`" then echo shar: "error transmitting 'send.c'" '(should have been 9886 characters)' fi fi echo shar: "extracting 'xmodem.c'" '(8408 characters)' if test -f 'xmodem.c' then echo shar: "will not over-write existing file 'xmodem.c'" else sed 's/^X//' << \SHAR_EOF > 'xmodem.c' 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@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#ifdef NOCLOBBER X char ans[10]; X#endif /* NOCLOBBER */ X#ifdef LOCAL X XMITTYPE = 'b'; /* assume binary transfer */ X#else /* LOCAL */ X XMITTYPE = 't'; /* assume text transfer */ X#endif /* LOCAL */ 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#ifdef LOCAL X CRCMODE = TRUE; /* use crc-16 for now */ X#else /* LOCAL */ X CRCMODE = FALSE; /* use checksums for now */ X#endif /* LOCAL */ X DELFLAG = FALSE; /* don't delete old log file */ X#ifdef LOCAL X LOGFLAG = FALSE; /* keep log */ X#else /* LOCAL */ X LOGFLAG = TRUE; /* keep log */ X#endif /* LOCAL */ 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#ifdef LOCAL X case 'c' : CRCMODE = FALSE; /* enable checksum on receive */ X#else /* LOCAL */ X case 'c' : CRCMODE = TRUE; /* enable CRC on receive */ X#endif /* LOCAL */ X break; X case 'D' : X case 'd' : DELFLAG = TRUE; /* delete log file */ X break; X case 'L' : X#ifdef LOCAL X case 'l' : LOGFLAG = TRUE; /* turn on log */ X#else /* LOCAL */ X case 'l' : LOGFLAG = FALSE; /* turn off log */ X#endif /* LOCAL */ 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#ifdef LOCAL X if (argv[1][index] == 'b' || argv[1][index] == 'B') { X index++; X XMITTYPE = 'b'; X break; X } X if (argv[1][index] == 't' || argv[1][index] == 'T') { X index++; X XMITTYPE = 't'; X break; X } X if (argv[1][index] == 'a' || argv[1][index] == 'A') { X index++; X XMITTYPE = 'a'; X break; X } X#else /* LOCAL */ X XMITTYPE = gettype(argv[1][index++]); /* get t/b */ X#endif /* LOCAL */ X break; X case 'S' : X case 's' : SENDFLAG = TRUE; /* send file */ X#ifdef LOCAL X if (argv[1][index] == 'b' || argv[1][index] == 'B') { X index++; X XMITTYPE = 'b'; X break; X } X if (argv[1][index] == 't' || argv[1][index] == 'T') { X index++; X XMITTYPE = 't'; X break; X } X if (argv[1][index] == 'a' || argv[1][index] == 'A') { X index++; X XMITTYPE = 'a'; X break; X } X#else /* LOCAL */ X XMITTYPE = gettype(argv[1][index++]); X#endif /* LOCAL */ 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; index2) X { X if(open(argv[2], 0) != -1) /* check for overwriting */ X#ifdef NOCLOBBER X while(1) { X printf("File exists - overwrite (y/n)? "); X gets(ans); X if (ans[0] == 'n' || ans[0] == 'N') X exit(0); X if (ans[0] == 'y' || ans[0] == 'Y') X break; X } X#endif /* NOCLOBBER */ X { X logit("Warning -- Target File Exists and is Being Overwritten\n"); X#ifndef NOCLOBBER X fprintf(stderr, "Warning -- Target File Exists and is Being Overwritten\n"); X#endif /* NOCLOBBER */ 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 'xmodem.h' X#include X#include X#include X#include X#ifdef SYSV X#include X#include X#define rindex strrchr X#define index strchr X#else /* SYSV */ X#include X#include X#endif /* SYSV */ X#include X X/* define macros to print messages in log file */ X#define logit(string) if(LOGFLAG)fprintf(LOGFP,string) X#define logitarg(string,argument) if(LOGFLAG)fprintf(LOGFP,string,argument) X X#define VERSION 36 /* Version Number */ X#define FALSE 0 X#define TRUE 1 X X X/* ASCII Constants */ X#define SOH 001 X#define STX 002 X#define ETX 003 X#define EOT 004 X#define ENQ 005 X#define ACK 006 X#define LF 012 /* Unix LF/NL */ X#define CR 015 X#define NAK 025 X#define SYN 026 X#define CAN 030 X#define ESC 033 X X/* XMODEM Constants */ X#define TIMEOUT -1 X#define ERRORMAX 10 /* maximum errors tolerated while transferring a packet */ X#define WAITFIRST 1 /* seconds between startup characters in read */ X#define STERRORMAX 60 /* maximum "errors" tolerated in read startup */ X#define CRCSWMAX 30 /* maximum time to try CRC mode before switching */ X#define NAKMAX 120 /* maximum times to wait for initial NAK when sending */ X#define RETRYMAX 5 /* maximum retries to be made certain handshaking routines */ X#define KSWMAX 5 /* maximum errors before switching to 128 byte packets */ X#define EOTMAX 10 /* maximum times sender will send an EOT to end transfer */ X#define SLEEPNUM 100 /* target number of characters to collect during sleepy time */ X#define BBUFSIZ 1024 /* buffer size */ X#define NAMSIZ 11 /* length of a CP/M file name string */ X#define CTRLZ 032 /* CP/M EOF for text (usually!) */ X#define CRCCHR 'C' /* CRC request character */ X#define KCHR 'K' /* 1K block request character */ X#define BAD_NAME 'u' /* Bad filename indicator */ X X#define CREATMODE 0644 /* mode for created files */ X X/* GLOBAL VARIABLES */ X Xint ttyspeed; /* tty speed (bits per second) */ Xunsigned char buff[BBUFSIZ]; /* buffer for data */ Xint nbchr; /* number of chars read so far for buffered read */ Xlong filelength; /* length specified in YMODEM header */ Xlong fileread; /* characters actually read so far in file */ Xchar filename[256]; /* place to construct filenames */ XFILE *LOGFP; /* descriptor for LOG file */ X X/* option flags and state variables */ Xchar XMITTYPE; /* text or binary? */ Xint DEBUG; /* keep debugging info in log? */ Xint RECVFLAG; /* receive? */ Xint SENDFLAG; /* send? */ Xint BATCH; /* batch? (Now used as a state variable) */ Xint CRCMODE; /* CRC or checksums? */ Xint DELFLAG; /* don't delete old log file? */ Xint LOGFLAG; /* keep log? */ Xint LONGPACK; /* do not use long packets on transmit? */ Xint MDM7BAT; /* MODEM7 batch protocol */ Xint YMDMBAT; /* YMODEM batch protocol */ Xint TOOBUSY; /* turn off sleeping in packet read routine */ Xint CHECKLENGTH; /* Are we truncating a file to a YMODEM length? */ X X X/* CRC-16 constants. From Usenet contribution by Mark G. Mendel, X Network Systems Corp. (ihnp4!umn-cs!hyper!mark) X*/ X X /* the CRC polynomial. */ X#define P 0x1021 X X /* number of bits in CRC */ X#define W 16 X X /* the number of bits per char */ X#define B 8 SHAR_EOF if test 3369 -ne "`wc -c < 'xmodem.h'`" then echo shar: "error transmitting 'xmodem.h'" '(should have been 3369 characters)' fi fi echo shar: "extracting 'xmodem.1'" '(7948 characters)' if test -f 'xmodem.1' then echo shar: "will not over-write existing file 'xmodem.1'" else sed 's/^X//' << \SHAR_EOF > 'xmodem.1' X.TH XMODEM LOCAL "April 14, 1988" X.UC 4.2 X.SH NAME Xxmodem \- Christensen protocol file transfer utility X.SH SYNOPSIS X.B xmodem X[\fBst|sb|sa|rt|rb|ra\fR][\fBymkctdlx\fR] X[file...] X.br X.SH DESCRIPTION XThe X.I xmodem Xprogram implements the Christensen (XMODEM) file transfer Xprotocol for moving files between 4.2/4.3BSD Unix systems and microcomputers. XThe XMODEM/CRC protocol, the MODEM7 batch protocol, the XMODEM-1K Xblock protocol and the YMODEM batch protocol are all supported by X.IR xmodem . XFor details of the protocols, Xsee the document edited by Chuck Forsberg titled X.I XXMODEM/YMODEM Protocol Reference. X.sp XOption Flags are case insensitive; the cluster of flags Xmay be preceded by an optional "-" Xcharacter. X.PP X.SH PARAMETERS XExactly one of the following must be selected: X.TP X.B rb XReceive Binary - files are placed on the Unix disk without conversion. X.I Xmodem Xwill silently destroy existing files of the same name. X.TP X.B rt XReceive Text - files are converted from the CP/M and MS-DOS Xformat of CR-LF pairs to the Unix convention of newline Xcharacters only between lines. XNull bytes are ignored and bit 8 of each character is stripped (which makes XWordstar files much more readable). XA CTRL-Z character is deemed to indicate the EOF location in the incoming Xfile. XThe resulting file Xis acceptable to the Unix editors and compilers, and is usually slightly Xsmaller than the original file. X.I Xmodem Xwill silently destroy existing files of the same name. X.TP X.B ra XReceive Apple - same as rt save CR characters in the incoming file are Xtranslated into Unix newline characters. X.TP X.B sb XSend Binary - files are sent without conversion as they exist on the Unix disk. X.TP X.B st XSend Text - newline characters in the file are converted to CR-LF pairs Xin accord with the CP/M and MS-DOS conventions for text files. The file X"grows" in this process. X.TP X.B sa XSend Apple - same as st save newline characters are converted into CR Xcharacters in accord with Apple Macintosh conventions for text files. X.PP X.SH OPTIONS X.TP X.B y XSelect the YMODEM batch protocol for sending files; a list of files specified Xon the command line will be sent in sequence. The YMODEM batch protocol is Xused automatically for file reception if the sending program requests it. XIf this flag is specified for a batch receive, (\fIxmodem rty\fR, for example), Xthe transfer will never attempt to switch from CRC to checksum mode. X.TP X.B m XSelect the MODEM7 batch protocol for sending files; a list of files specified Xon the command line will be sent in sequence. The MODEM7 batch protocol is Xused automatically for file reception if the sending program requests it. XIf this flag is specified for a batch receive, (\fIxmodem rbm\fR, for example), Xthe transfer starts in checksum mode rather than CRC mode. X.TP X.B k XSelect the XMODEM-1K file transfer mode for sending files. Use of 1K packets on Xlow-error lines increases throughput. XHowever, over direct connections at 9600 bps to a busy host, 1K packets may Xcause data overflows generating excessive retries. X1K packets are automatically Xused for file reception if the sending program requests it. XIf this flag is specified with the YMODEM flag in a batch receive (\fIxmodem Xrbyk\fR, for example), the program will attempt to use the "KMD/IMP" convention Xto invoke 1K file transfers. X.TP X.B c XSelect the CRC-16 error-checking protocol on receive. CRC mode is better at catching Xtransmission errors that occur than the alternative checksum protocol. XCRC mode is automatically selected for file Xtransmission if the receiving modem program requests it. X.TP X.B t XIndicates the Unix system is Too Busy and X.I xmodem Xshould fall back to a simpler I/O strategy than normal. X.TP X.B d XDelete the X.I xmodem.log Xfile before file transfer is begun. X.TP X.B l XDo NOT write to the log file. If logging is selected, a file X.I xmodem.log Xwill be created (or appended to), with entries for significant events, errors Xand retries. This can be useful to see why things went wrong Xwhen they do. X.TP X.B x XToggle on debug mode. If debug mode is selected, copious and possibly Xuseful debugging information will be placed in X.IR xmodem.log . X.SH "FILE NAMES" XFiles transmitted using one of the batch modes Xwill be stored on the remote machine under a CP/M-ified name (path names Xstripped, limited Xto eight characters plus a three character extension; ":" characters will Xbe turned into "/" characters; all characters will be in monocase). XFiles received using one of the batch modes Xwill be stored under their transmitted names (except that any "/" characters Xin the file name will be converted into ":" characters, all upper-case Xcharacters will be translated into lower case and trailing dots will be Xexpunged). X.PP XWhen a batch receive is requested, X.I xmodem Xtakes a wait and see attitude and can adapt to either batch protocol or even Xa classic XMODEM transfer (note that CRC-16 mode is automatically set under Xthese circumstances unless the b flag is specified). XIf a classic, "non-batch" XMODEM file reception takes place, Xthe received file is stored as X.IR xmodem.in . XFile names present on the command line for a batch receive are ignored. X.SH NOTES XWhile waiting for the beginning of a file transfer, X.I xmodem Xtreats two CAN (CTRL-X) characters that are received within 3 seconds Xas a request to abort. CAN characters will not cause an abort if received Xduring a file transfer. X.PP XIf 10 or more errors are detected during the transmission or reception of any Xone packet, the transfer is aborted. X.PP XSqueezed, compressed or ARCed files must be transferred in binary mode, even if they Xcontain text. X.PP XIf you use X.I xmodem Xover a X.I rlogin Xlink, you may have to use the form X.IR "rlogin machine -8" . X.PP XIf an unexpected error occurs before a file is completely received, the Xincomplete file is deleted. X.PP XFiles received using both binary and text mode in a YMODEM batch transfer Xwill be truncated Xto the file size specified in the YMODEM header (extra CR characters in the Xincoming file are correctly handled). File sizes are included in Xthe YMODEM header when sending both binary and text files. Thus files Xtransferred via YMODEM should preserve their exact length. XFile modification times are set for received files if present in the YMODEM Xheader; they are included in the headers for transmitted files. X.PP XThe "KMD/IMP" record count field in the YMODEM header is both set and read. X.SH EXAMPLES XTo receive a text file transmitted from a micro (using CRC-16 Xerror-checking) and store it under the Xname X.IR file.name , Xuse the command line X.RS X.B "xmodem rtc file.name" X.RE XNote that if the transmitting program on the micro uses the 1K packet Xprotocol or either batch protocol, X.I xmodem Xdetects this automatically and takes appropriate action. Further Xnote that if one of the batch protocols is used, the received file(s) Xwill be stored under their own names and the name on the command line X(if any) will be ignored. X.PP XTo send a set of text files to a microcomputer using 1K packets and the XYMODEM batch protocol, use the command line X.RS X.B "xmodem styk *.txt" X.RE X.SH FILES Xxmodem.log (if logging is enabled) X.SH BUGS XBatch mode could be smarter about bad file-names in the midst of a Xbatch transmit/receive. X.PP XBatch mode could allow a mixture of binary and text files. X.PP XBare Carriage Return characters (i.e., those not immediately followed by a XLine Feed character) are mishandled in a received file when using text mode. XA file with ``overstruck'' lines will thus come out looking funny. X.PP XYMODEM header packets are only sent as 128 byte packets. Thus VERY long file Xnames will not be handled properly. X.SH SEE ALSO Xkermit(1) X.SH AUTHOR XSteve Grandi, National Optical Astronomy Observatories. Based on X.I xmodem Xby Brian Kantor, University of California at San Diego. XThis, in turn, was based on X.I umodem Xby Lauren Weinstein, Richard Conn and others. SHAR_EOF if test 7948 -ne "`wc -c < 'xmodem.1'`" then echo shar: "error transmitting 'xmodem.1'" '(should have been 7948 characters)' fi fi exit 0 # End of shell archive