home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume15 / xmodem3.6 / part02 < prev    next >
Text File  |  1988-06-13  |  25KB  |  932 lines

  1. Subject:  v15i071:  Xmodem release 3.6, Part02/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Steve Grandi <grandi@noao.arizona.edu>
  7. Posting-number: Volume 15, Issue 71
  8. Archive-name: xmodem3.6/part02
  9.  
  10. : This is a shar archive.  Extract with sh, not csh.
  11. echo x - xmodem.c
  12. sed -e 's/^X//' > xmodem.c << '!Funky!Stuff!'
  13. X/*
  14. X *  XMODEM -- Implements the Christensen XMODEM protocol, 
  15. X *            for packetized file up/downloading.    
  16. X *
  17. X *    See the README file for some notes on SYS V adaptations.
  18. X *    The program has been successfully run on VAXes (4.3BSD) and SUN-3/4s
  19. X *    (SunOS 3.x) against MEX-PC and ZCOMM/DSZ.
  20. X *
  21. X *  See the README and update.doc files for history and change notes.
  22. X *
  23. X *  Please send bug fixes, additions and comments to:
  24. X *    {ihnp4,ncar}!noao!grandi   grandi@noao.arizona.edu
  25. X */
  26. X
  27. X#include "xmodem.h"
  28. X
  29. Xmain(argc, argv)
  30. Xint argc;
  31. Xchar **argv;
  32. X{
  33. X    char *getenv();
  34. X    FILE *fopen();
  35. X    char *unix_cpm();
  36. X    char *strcpy();
  37. X    char *strcat();
  38. X    char *prtype();
  39. X    
  40. X    char *fname = filename;        /* convenient place to stash file names */
  41. X    char *logfile = "xmodem.log";    /* Name of LOG File */
  42. X    
  43. X    char *stamptime();        /* for timestamp */
  44. X
  45. X    char *defname = "xmodem.in";    /* default file name if none given */
  46. X
  47. X    struct stat filestatbuf;    /* file status info */
  48. X
  49. X    int index;
  50. X    char flag;
  51. X    long expsect;
  52. X
  53. X    /* initialize option flags */
  54. X
  55. X    XMITTYPE = 't';        /* assume text transfer */
  56. X    DEBUG = FALSE;        /* keep debugging info in log */
  57. X    RECVFLAG = FALSE;    /* not receive */
  58. X    SENDFLAG = FALSE;    /* not send either */
  59. X    BATCH = FALSE;        /* nor batch */
  60. X    CRCMODE = FALSE;    /* use checksums for now */
  61. X    DELFLAG = FALSE;    /* don't delete old log file */
  62. X    LOGFLAG = TRUE;        /* keep log */
  63. X    LONGPACK = FALSE;     /* do not use long packets on transmit */
  64. X    MDM7BAT = FALSE;    /* no MODEM7 batch mode */
  65. X    YMDMBAT = FALSE;    /* no YMODEM batch mode */
  66. X    TOOBUSY = FALSE;    /* not too busy for sleeping in packet read */
  67. X
  68. X    fprintf(stderr, "XMODEM Version %d.%d", VERSION/10, VERSION%10);
  69. X    fprintf(stderr, " -- UNIX-Microcomputer Remote File Transfer Facility\n");
  70. X
  71. X    if (argc == 1)
  72. X        {
  73. X        help();
  74. X        exit(-1);
  75. X        }
  76. X
  77. X    index = 0;        /* set index for flag loop */
  78. X
  79. X    while ((flag = argv[1][index++]) != '\0')
  80. X        switch (flag) {
  81. X        case '-' : break;
  82. X        case 'X' :
  83. X        case 'x' : DEBUG = TRUE;  /* turn on debugging log */
  84. X               break;
  85. X        case 'C' :
  86. X        case 'c' : CRCMODE = TRUE; /* enable CRC on receive */
  87. X               break;
  88. X        case 'D' :
  89. X        case 'd' : DELFLAG = TRUE;  /* delete log file */
  90. X               break;
  91. X        case 'L' :
  92. X        case 'l' : LOGFLAG = FALSE;  /* turn off log  */
  93. X               break;
  94. X        case 'm' :
  95. X        case 'M' : MDM7BAT = TRUE;  /* turn on MODEM7 batch protocol */
  96. X               BATCH   = TRUE;
  97. X               break;
  98. X        case 'y' :
  99. X        case 'Y' : YMDMBAT = TRUE;  /* turn on YMODEM batch protocol */
  100. X               BATCH   = TRUE;
  101. X               break;
  102. X        case 'k' :
  103. X        case 'K' : LONGPACK = TRUE;  /* use 1K packets on transmit */
  104. X               break;
  105. X        case 't' :
  106. X        case 'T' : TOOBUSY = TRUE;  /* turn off sleeping */
  107. X               break;
  108. X        case 'R' :
  109. X        case 'r' : RECVFLAG = TRUE;  /* receive file */
  110. X               XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
  111. X               break;
  112. X        case 'S' :
  113. X        case 's' : SENDFLAG = TRUE;  /* send file */
  114. X               XMITTYPE = gettype(argv[1][index++]);
  115. X               break;
  116. X        default  : fprintf(stderr, "Invalid Flag %c ignored\n", flag);
  117. X               break;
  118. X       }
  119. X
  120. X    if (DEBUG)
  121. X        LOGFLAG = TRUE;
  122. X
  123. X    if (LOGFLAG)
  124. X       { 
  125. X         if ((fname = getenv("HOME")) == 0)    /* Get HOME variable */
  126. X        error("Fatal - Can't get Environment!", FALSE);
  127. X         fname = strcat(fname, "/");
  128. X         fname = strcat(fname, logfile);
  129. X         if (!DELFLAG)
  130. X        LOGFP = fopen(fname, "a");  /* append to LOG file */
  131. X         else
  132. X        LOGFP = fopen(fname, "w");  /* new LOG file */
  133. X         if (!LOGFP)
  134. X        error("Fatal - Can't Open Log File", FALSE);
  135. X
  136. X         fprintf(LOGFP,"\n++++++++  %s", stamptime());
  137. X         fprintf(LOGFP,"XMODEM Version %d.%d\n", VERSION/10, VERSION%10);
  138. X         fprintf(LOGFP,"Command line: %s %s", argv[0], argv[1]);
  139. X         for (index=2; index<argc; ++index)
  140. X        fprintf(LOGFP, " %s", argv[index]);
  141. X         fprintf(LOGFP, "\n");
  142. X       }
  143. X
  144. X    getspeed();        /* get tty-speed for time estimates */
  145. X
  146. X    if (RECVFLAG && SENDFLAG)
  147. X        error("Fatal - Both Send and Receive Functions Specified", FALSE);
  148. X
  149. X    if (MDM7BAT && YMDMBAT)
  150. X        error("Fatal - Both YMODEM and MODEM7 Batch Protocols Specified", FALSE);
  151. X
  152. X    if (!RECVFLAG && !SENDFLAG)
  153. X        error("Fatal - Either Send or Receive Function must be chosen!",FALSE);
  154. X    
  155. X    if (SENDFLAG && argc==2)
  156. X        error("Fatal - No file specified to send",FALSE);
  157. X
  158. X    if (RECVFLAG && argc==2)
  159. X        {
  160. X        /* assume we really want CRC-16 in batch, unless we specify MODEM7 mode */ 
  161. X        CRCMODE = MDM7BAT ? FALSE : TRUE;
  162. X        fprintf(stderr, "Ready for BATCH RECEIVE");
  163. X        fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  164. X        fprintf(stderr, "Send several Control-X characters to cancel\n");
  165. X        logit("Batch Receive Started");
  166. X        logitarg(" in %s mode\n", prtype(XMITTYPE));
  167. X        strcpy(fname, defname);
  168. X        }
  169. X
  170. X    if (RECVFLAG && argc>2)
  171. X        {
  172. X        if(open(argv[2], 0) != -1)  /* check for overwriting */
  173. X            {
  174. X            logit("Warning -- Target File Exists and is Being Overwritten\n");
  175. X            fprintf(stderr, "Warning -- Target File Exists and is Being Overwritten\n");
  176. X            }
  177. X        fprintf(stderr, "Ready to RECEIVE File %s", argv[2]);
  178. X        fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  179. X        fprintf(stderr, "Send several Control-X characters to cancel\n");
  180. X        logitarg("Receiving in %s mode\n", prtype(XMITTYPE));
  181. X        strcpy(fname,argv[2]);
  182. X        }
  183. X
  184. X    if (RECVFLAG)
  185. X        {  
  186. X        setmodes();        /* set tty modes for transfer */
  187. X
  188. X        while(rfile(fname) != FALSE);  /* receive files */
  189. X
  190. X        flushin();
  191. X        restoremodes(FALSE);    /* restore normal tty modes */
  192. X
  193. X        sleep(2);        /* give other side time to return to terminal mode */
  194. X        exit(0);
  195. X        }
  196. X
  197. X    if (SENDFLAG && BATCH) 
  198. X        {
  199. X        if (YMDMBAT)
  200. X            {
  201. X            fprintf(stderr, "Ready to YMODEM BATCH SEND");
  202. X            fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  203. X            logit("YMODEM Batch Send Started");
  204. X            logitarg(" in %s mode\n", prtype(XMITTYPE));
  205. X            }
  206. X        else if (MDM7BAT)
  207. X            {
  208. X            fprintf(stderr, "Ready to MODEM7 BATCH SEND");
  209. X            fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  210. X            logit("MODEM7 Batch Send Started");
  211. X            logitarg(" in %s mode\n", prtype(XMITTYPE));
  212. X            }
  213. X        fprintf(stderr, "Send several Control-X characters to cancel\n");
  214. X
  215. X        setmodes();
  216. X        for (index=2; index<argc; index++) {
  217. X            if (stat(argv[index], &filestatbuf) < 0) {
  218. X                logitarg("\nFile %s not found\n", argv[index]);
  219. X                continue;
  220. X            }
  221. X            sfile(argv[index]);
  222. X        }
  223. X        sfile("");
  224. X        flushin();
  225. X        restoremodes(FALSE);
  226. X
  227. X        logit("Batch Send Complete\n");
  228. X        sleep(2);
  229. X        exit (0);
  230. X        }
  231. X
  232. X    if (SENDFLAG && !BATCH) 
  233. X        {
  234. X        if (stat(argv[2], &filestatbuf) < 0)
  235. X            error("Can't find requested file", FALSE);
  236. X        expsect = (filestatbuf.st_size/128)+1;
  237. X            
  238. X        fprintf(stderr, "File %s Ready to SEND", argv[2]);
  239. X        fprintf(stderr, " in %s mode\n", prtype(XMITTYPE));
  240. X        fprintf(stderr, "Estimated File Size %ldK, %ld Sectors, %ld Bytes\n",
  241. X              (filestatbuf.st_size/1024)+1, expsect,
  242. X            filestatbuf.st_size);
  243. X        projtime(expsect, stdout);
  244. X        fprintf(stderr, "Send several Control-X characters to cancel\n");
  245. X        logitarg("Sending in %s mode\n", prtype(XMITTYPE));
  246. X
  247. X        setmodes();
  248. X        sfile(argv[2]);
  249. X        flushin();
  250. X        restoremodes(FALSE);
  251. X
  252. X        sleep(2);
  253. X        exit(0);
  254. X        }
  255. X}
  256. !Funky!Stuff!
  257. echo x - receive.c
  258. sed -e 's/^X//' > receive.c << '!Funky!Stuff!'
  259. X#include "xmodem.h"
  260. X
  261. X/**  receive a file  **/
  262. X
  263. X/* returns TRUE if in the midst of a batch transfer */
  264. X/* returns FALSE if no more files are coming */
  265. X
  266. X/* This routine is one HUGE do-while loop with far to many indented levels.
  267. X * I chose this route to facilitate error processing and to avoid GOTOs.
  268. X * Given the troubles I've had keeping the nested IF statements straight,
  269. X * I was probably mistaken...
  270. X */
  271. X
  272. Xrfile(name)
  273. Xchar *name;
  274. X{
  275. X
  276. Xchar *sectdisp();
  277. Xchar *cpm_unix();
  278. Xchar *strcpy();
  279. Xchar *ctime();
  280. Xtime_t time();
  281. X
  282. Xint fd,     /* file descriptor for created file */
  283. Xchecksum,   /* packet checksum */
  284. Xfirstchar,  /* first character of a packet */
  285. Xsectnum,    /* number of last received packet (modulo 128) */
  286. Xsectcurr,   /* second byte of packet--should be packet number (mod 128) */
  287. Xsectcomp,   /* third byte of packet--should be complement of sectcurr */
  288. Xtmode,      /* text mode if true */
  289. Xamode,      /* apple mode if true */
  290. Xerrors,     /* count of errors for each packet */
  291. Xsterrors,   /* count of errors during startup handshake */
  292. Xerrorflag,  /* set true when packet (or first char of putative packet) is invalid */
  293. Xfatalerror, /* set within main "read-packet" Do-While when bad error found */
  294. Xinchecksum, /* incoming checksum or CRC */
  295. Xexpsect,    /* expected number of sectors (YMODEM batch) */
  296. Xfirstwait,  /* seconds to wait for first character in a packet */
  297. Xbufsize;    /* packet size (128 or 1024) */
  298. Xlong recvsectcnt;   /* running sector count (128 byte sectors) */
  299. Xlong modtime;       /* Unix style file mod time from YMODEM header */
  300. Xint filemode;       /* Unix style file mode from YMODEM header */
  301. Xlong readbackup;    /* "backup" value for characters read in file */
  302. Xtime_t timep[2];    /* used in setting mod time of received file */
  303. Xchar *p;    /* generic pointer */
  304. Xint bufctr; /* number of real chars in read packet */
  305. Xunsigned char *nameptr; /* ptr in filename for MODEM7 protocol */
  306. Xtime_t start;       /* starting time of transfer */
  307. Xint openflag = FALSE;   /* is file open for writing? */
  308. X
  309. Xlogit("----\nXMODEM File Receive Function\n");
  310. Xif (CRCMODE)
  311. Xlogit("CRC mode requested\n");
  312. X
  313. XBATCH = FALSE;          /* don't know if really are in batch mode ! */
  314. Xfatalerror = FALSE;
  315. Xfirstwait = WAITFIRST;  /* For first packet, wait short time */
  316. Xsectnum = errors = recvsectcnt = 0;
  317. Xbufsize = 128;
  318. Xmodtime = 0l; filemode = 0;
  319. Xfilelength = 0l; fileread =0l; CHECKLENGTH = FALSE;
  320. X
  321. Xtmode = (XMITTYPE == 't') ? TRUE : FALSE;
  322. Xamode = (XMITTYPE == 'a') ? TRUE : FALSE;
  323. X
  324. X/* start up transfer */
  325. X
  326. Xsterrors = 0;
  327. Xflushin();         /* flush input queue */
  328. X
  329. Xif (CRCMODE)        
  330. X{
  331. X    sendbyte(CRCCHR);
  332. X    if (LONGPACK && !MDM7BAT)
  333. X        sendbyte(KCHR);
  334. X}
  335. Xelse
  336. X    sendbyte(NAK);
  337. X
  338. X
  339. Xdo                  /* start of MAIN Do-While loop to read packets */
  340. X{   
  341. X    errorflag = FALSE;
  342. X    do              /* start by reading first byte in packet */
  343. X    {
  344. X        firstchar = readbyte(firstwait);
  345. X    } 
  346. X    while ((firstchar != SOH) 
  347. X        && (firstchar != STX) 
  348. X        && (firstchar != EOT) 
  349. X        && (firstchar != ACK || recvsectcnt > 0) 
  350. X        && (firstchar != TIMEOUT) 
  351. X        && (firstchar != CAN || recvsectcnt > 0));
  352. X
  353. X    if (firstchar == EOT)           /* check for REAL EOT */
  354. X    {
  355. X        flushin();
  356. X        sendbyte(NAK);              /* NAK the EOT */
  357. X        if ((firstchar = readbyte(3)) != EOT)   /* check next character */
  358. X        {
  359. X            logit("Spurious EOT detected; ignored\n");
  360. X            if ((firstchar == SOH) || (firstchar == STX) ||
  361. X                (firstchar == ACK && recvsectcnt == 0) ||
  362. X                (firstchar == CAN && recvsectcnt == 0) ||
  363. X                (firstchar == TIMEOUT))
  364. X                break;
  365. X            else
  366. X            {
  367. X                firstchar = 0;
  368. X                errorflag = TRUE;
  369. X            }
  370. X        }
  371. X    }
  372. X
  373. X    if (firstchar == TIMEOUT)       /* timeout? */
  374. X    {  
  375. X        if (recvsectcnt > 0)
  376. X            logitarg("Timeout on Sector %s\n", sectdisp(recvsectcnt,bufsize,1));
  377. X        errorflag = TRUE;
  378. X    }
  379. X
  380. X    if (firstchar == CAN)           /* bailing out? (only at beginning) */
  381. X    {
  382. X        if ((readbyte(3) & 0x7f) == CAN)
  383. X            error("Reception canceled at user's request",TRUE);
  384. X        else
  385. X        {
  386. X            errorflag = TRUE;
  387. X            logit("Received single CAN character\n");
  388. X        }
  389. X    }
  390. X
  391. X    if (firstchar == ACK)           /* MODEM7 batch? (only at beginning) */
  392. X    {
  393. X        int i,c; 
  394. X
  395. X        logit("MODEM7 Batch Protocol\n");
  396. X        nameptr = buff;
  397. X        checksum = 0;
  398. X
  399. X        for (i=0; i<NAMSIZ; i++)
  400. X        {
  401. X            c = readbyte(3);
  402. X
  403. X            if (c == CAN)
  404. X            {
  405. X                if (readbyte(3) == CAN)
  406. X                    error("Program Canceled by User", TRUE);
  407. X                else
  408. X                {
  409. X                    logit("Received single CAN character in MODEM7 filename\n");
  410. X                    errorflag = TRUE;
  411. X                    break;
  412. X                }
  413. X            }
  414. X
  415. X            if (c == EOT && i == 0)
  416. X            {
  417. X                sendbyte(ACK);          /* acknowledge EOT */
  418. X                logit("MODEM7 Batch Receive Complete\n");
  419. X                return (FALSE);
  420. X            }
  421. X
  422. X            if (c == TIMEOUT)
  423. X            {
  424. X                logit("Timeout waiting for MODEM7 filename character\n");
  425. X                errorflag = TRUE;
  426. X                break;
  427. X            }
  428. X
  429. X            if (c == BAD_NAME)
  430. X            {
  431. X                logit("Error during MODEM7 filename transfer\n");
  432. X                errorflag = TRUE;
  433. X                break;
  434. X            }
  435. X
  436. X            *nameptr++ = c;
  437. X            checksum += c;
  438. X            sendbyte(ACK);
  439. X        }
  440. X
  441. X        if (!errorflag)
  442. X        {
  443. X            c = readbyte(3);
  444. X            if (c == CTRLZ)     /* OK; end of string found */
  445. X            {
  446. X                sendbyte(checksum + CTRLZ);
  447. X                if (readbyte(15) == ACK)     /* file name found! */
  448. X                {
  449. X                    xmdebug("MODEM7 file name OK");
  450. X                    *nameptr = '\000';  /* unixify the file name */
  451. X                    name = cpm_unix(buff);
  452. X                    BATCH = TRUE;
  453. X                    logitarg("MODEM7 file name: %s\n", name);
  454. X                    errors = 0;     /* restart crc handshake */
  455. X                    sleep(2);       /* give other side a chance */
  456. X                }
  457. X                else
  458. X                {
  459. X                    logit("Checksum error in MODEM7 filename\n");
  460. X                    errorflag = TRUE;
  461. X                }
  462. X            }
  463. X            else
  464. X            {
  465. X                logit("Length error in MODEM7 filename\n");
  466. X                errorflag = TRUE;
  467. X            }
  468. X        }
  469. X    }
  470. X
  471. X
  472. X    if (firstchar == SOH || firstchar == STX)  /* start reading packet */
  473. X    {
  474. X        bufsize = (firstchar == SOH) ? 128 : 1024;
  475. X
  476. X        if (recvsectcnt == 0)           /* 1st data packet, initialize */
  477. X        {
  478. X            if (bufsize == 1024)
  479. X                logit("1K packet mode chosen\n");
  480. X            start = time((time_t *) 0);
  481. X            errors = 0;
  482. X            firstwait = 5;
  483. X        }
  484. X
  485. X        sectcurr = readbyte(3);
  486. X        sectcomp = readbyte(3);
  487. X        if ((sectcurr + sectcomp) == 0xff)  /* is packet number checksum correct? */
  488. X        {  
  489. X            if (sectcurr == ((sectnum+1) & 0xff))   /* is packet number correct? */
  490. X            {  
  491. X                if (DEBUG)
  492. X                    fprintf(LOGFP,"DEBUG: packet %d started\n", sectnum);
  493. X
  494. X                /* Read, process and calculate checksum for a buffer of data */
  495. X
  496. X                readbackup = fileread;
  497. X                if (readbuf(bufsize, 1, tmode, amode, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
  498. X                {
  499. X
  500. X                    /* verify checksum or CRC */
  501. X
  502. X                    if (CRCMODE) 
  503. X                    {
  504. X                        checksum &= 0xffff;
  505. X                        inchecksum = readbyte(3);  /* get 16-bit CRC */
  506. X                        inchecksum = (inchecksum<<8) | readbyte(3);
  507. X                    }
  508. X
  509. X                    else
  510. X                        inchecksum = readbyte(3);  /* get simple 8-bit checksum */
  511. X
  512. X                    if (inchecksum == checksum) /* good checksum, hence good packet */
  513. X                    {  
  514. X                        xmdebug("checksum ok");
  515. X                        errors = 0;
  516. X                        recvsectcnt += (bufsize == 128) ? 1 : 8;
  517. X                        sectnum = sectcurr; 
  518. X
  519. X                        if (!openflag)      /* open output file if necessary */
  520. X                        {
  521. X                            openflag = TRUE;
  522. X                            if ((fd = creat(name, CREATMODE)) < 0)
  523. X                            {
  524. X                                sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  525. X                                error("Can't create file for receive", TRUE);
  526. X                            }
  527. X                            if (!BATCH)
  528. X                                logitarg("File Name: %s\n", name);
  529. X                        }
  530. X
  531. X                        if (write(fd, (char *) buff, bufctr) != bufctr)
  532. X                        {
  533. X                            close(fd);
  534. X                            unlink(name);
  535. X                            error("File Write Error", TRUE);
  536. X                        }
  537. X                        else
  538. X                        {
  539. X                            flushin();          /* flush input */
  540. X                            sendbyte(ACK);      /* ACK the received packet */
  541. X                        }
  542. X                    }
  543. X
  544. X                    /* Start handling various errors and special conditions */
  545. X
  546. X                    else        /* bad checksum */
  547. X                    {  
  548. X                        logitarg("Checksum Error on Sector %s:  ", sectdisp(recvsectcnt,bufsize,1));
  549. X                        logitarg("sent=%x  ", inchecksum);
  550. X                        logitarg("recvd=%x\n", checksum);
  551. X                        fileread = readbackup;
  552. X                        errorflag = TRUE;
  553. X                    }
  554. X                }
  555. X
  556. X                else    /* read timeout */
  557. X                {
  558. X                    logitarg("Timeout while reading sector %s\n",sectdisp(recvsectcnt,bufsize,1));
  559. X                    fileread = readbackup;
  560. X                    errorflag = TRUE;
  561. X                }
  562. X            }
  563. X
  564. X            else        /* sector number is wrong OR Ymodem filename */
  565. X            { 
  566. X                if (sectcurr == 0 && recvsectcnt == 0)  /* Ymodem file-name packet */
  567. X                {
  568. X                    logit("YMODEM Batch Protocol\n");
  569. X
  570. X                    /* Read and process a file-name packet */
  571. X
  572. X                    if (readbuf(bufsize, 1, FALSE, FALSE, recvsectcnt, &checksum, &bufctr) != TIMEOUT) 
  573. X                    {
  574. X
  575. X                        /* verify checksum or CRC */
  576. X
  577. X                        if (CRCMODE) 
  578. X                        {
  579. X                            checksum &= 0xffff;
  580. X                            inchecksum = readbyte(3);  /* get 16-bit CRC */
  581. X                            inchecksum = (inchecksum<<8) | readbyte(3);
  582. X                        }
  583. X
  584. X                        else
  585. X                            inchecksum = readbyte(3);  /* get simple 8-bit checksum */
  586. X
  587. X                        if (inchecksum == checksum) /* good checksum, hence good filename */
  588. X                        {
  589. X                            xmdebug("checksum ok");
  590. X                            strcpy(name, (char *)buff);
  591. X                            expsect = ((buff[bufsize-1]<<8) | buff[bufsize-2]);
  592. X                            BATCH = TRUE;
  593. X                            YMDMBAT = TRUE;
  594. X                            if (strlen(name) == 0)  /* check for no more files */
  595. X                            {
  596. X                                flushin();          /* flush input */
  597. X                                sendbyte(ACK);      /* ACK the packet */
  598. X                                logit("YMODEM Batch Receive Complete\n");
  599. X                                return (FALSE);
  600. X                            }
  601. X                            unixify(name);       /* make filename canonical */
  602. X
  603. X                            /* read rest of YMODEM header */
  604. X                            p = (char *)buff + strlen((char *)buff) + 1;
  605. X                            sscanf(p, "%ld%lo%o", &filelength, &modtime, &filemode);
  606. X                            logitarg("YMODEM file name: %s\n", name);
  607. X                            fileread = 0l;
  608. X                            if (filelength)
  609. X                            {
  610. X                                CHECKLENGTH = TRUE;
  611. X                                logitarg("YMODEM file size: %ld\n", filelength);
  612. X                            }
  613. X                            else if (expsect)
  614. X                                logitarg("YMODEM estimated file length %d sectors\n", expsect);
  615. X                            if (modtime)
  616. X                            {
  617. X                                logitarg("YMODEM file date: %s", ctime(&modtime));
  618. X                            }
  619. X                            if (filemode)
  620. X                                logitarg("YMODEM file mode: %o", filemode);
  621. X
  622. X                            sendbyte(ACK);      /* ACK the packet */
  623. X                            firstwait = WAITFIRST;  /* reset to negotiate */
  624. X                        }
  625. X
  626. X                        else                /* bad filename checksum */
  627. X                        {
  628. X                            logit("checksum error on filename sector\n");
  629. X                            errorflag = TRUE;
  630. X                        }
  631. X                    }
  632. X                    else
  633. X                    {
  634. X                        logit("Timeout while reading filename packet\n");
  635. X                        errorflag = TRUE;
  636. X                    }
  637. X                }
  638. X
  639. X                else if (sectcurr == sectnum)   /* duplicate sector? */
  640. X                {  
  641. X                    logitarg("Duplicate sector %s flushed\n", sectdisp(recvsectcnt,bufsize,0));
  642. X                    flushin();                  /* REALLY flush input */
  643. X                    while(readbyte(1) != TIMEOUT)
  644. X                        ;
  645. X                    sendbyte(ACK);
  646. X                }
  647. X                else                /* no, real phase error */
  648. X                {
  649. X                    logitarg("Phase Error - Expected packet is %s\n", sectdisp(recvsectcnt,bufsize,1));
  650. X                    errorflag = TRUE;
  651. X                    fatalerror = TRUE;
  652. X                }
  653. X            }
  654. X        }
  655. X
  656. X        else        /* bad packet number checksum */
  657. X        {  
  658. X            logitarg("Header Sector Number Error on Sector %s\n", sectdisp(recvsectcnt, bufsize,1));
  659. X            errorflag = TRUE;
  660. X        }
  661. X
  662. X    }           /* END reading packet loop */
  663. X
  664. X    if (errorflag && !fatalerror && recvsectcnt != 0)   /* Handle errors */
  665. X    {  
  666. X        errors++;
  667. X
  668. X        if (errors >= ERRORMAX)     /* over error limit? */
  669. X            fatalerror = TRUE;
  670. X        else                        /* flush input and NAK the packet */
  671. X        {
  672. X            flushin();
  673. X            while (readbyte(1) != TIMEOUT)  /* wait for line to settle */
  674. X                ;
  675. X            sendbyte(NAK);
  676. X        }
  677. X    }
  678. X
  679. X    if (recvsectcnt == 0 && errorflag && firstchar != EOT)     /* handle startup handshake */
  680. X    {
  681. X        sterrors++;
  682. X
  683. X        if (sterrors >= STERRORMAX)
  684. X            fatalerror = TRUE;
  685. X
  686. X        else if (CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
  687. X        {
  688. X            CRCMODE = FALSE;
  689. X            logit("Sender not accepting CRC request, changing to checksum\n");
  690. X            sendbyte(NAK);
  691. X        }
  692. X
  693. X        else if (!CRCMODE && sterrors == CRCSWMAX && !YMDMBAT)
  694. X        {
  695. X            CRCMODE = TRUE;
  696. X            logit("Sender not accepting checksum request, changing to CRC\n");
  697. X            sendbyte(CRCCHR);
  698. X            if (LONGPACK && !MDM7BAT)
  699. X                sendbyte(KCHR);
  700. X        }
  701. X
  702. X        else if (CRCMODE)
  703. X            {
  704. X            sendbyte(CRCCHR);
  705. X            if (LONGPACK && !MDM7BAT)
  706. X                sendbyte(KCHR);
  707. X            }
  708. X
  709. X        else
  710. X            sendbyte(NAK);
  711. X    }
  712. X}
  713. Xwhile ((firstchar != EOT) && !fatalerror);   /* end of MAIN Do-While */
  714. X
  715. Xif ((firstchar == EOT) && !fatalerror)  /* normal exit? */
  716. X{
  717. X    if (openflag)       /* close the file */
  718. X        close(fd);
  719. X    sendbyte(ACK);      /* ACK the EOT */
  720. X    logit("Receive Complete\n");
  721. X    prtime (recvsectcnt, time((time_t *) 0) - start);
  722. X
  723. X    if (openflag && modtime)   /* set file modification time */
  724. X    {
  725. X        timep[0] = time((time_t *) 0);
  726. X        timep[1] = modtime;
  727. X        utime(name, timep);
  728. X    }
  729. X
  730. X    if (BATCH)          /* send appropriate return code */
  731. X        return(TRUE);
  732. X    else
  733. X        return(FALSE);
  734. X}
  735. Xelse                /* no, error exit */
  736. X{ 
  737. X    if (openflag)
  738. X    {
  739. X        sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  740. X        close(fd);
  741. X        unlink(name);
  742. X        error("ABORTED -- Too Many Errors--deleting file", TRUE);
  743. X    }
  744. X    else if (recvsectcnt != 0)
  745. X        error("ABORTED -- Too Many Errors", TRUE);
  746. X    else
  747. X        error("ABORTED -- Remote system is not responding", TRUE);
  748. X}
  749. Xreturn(FALSE);
  750. X
  751. X}
  752. !Funky!Stuff!
  753. echo x - misc.c
  754. sed -e 's/^X//' > misc.c << '!Funky!Stuff!'
  755. X#include "xmodem.h"
  756. X
  757. X/*  Print Help Message  */
  758. Xhelp()
  759. X    {
  760. X    fprintf(stderr, "\nUsage:  \n\txmodem ");
  761. X    fprintf(stderr, "-[rb!rt!ra!sb!st!sa][options] filename\n");
  762. X    fprintf(stderr, "\nMajor Commands --");
  763. X    fprintf(stderr, "\n\trb <-- Receive Binary");
  764. X    fprintf(stderr, "\n\trt <-- Receive Text");
  765. X    fprintf(stderr, "\n\tra <-- Receive Apple macintosh text");
  766. X    fprintf(stderr, "\n\tsb <-- Send Binary");
  767. X    fprintf(stderr, "\n\tst <-- Send Text");
  768. X    fprintf(stderr, "\n\tsa <-- Send Apple macintosh text");
  769. X    fprintf(stderr, "\nOptions --");
  770. X    fprintf(stderr, "\n\ty  <-- Use YMODEM Batch Mode on transmit");
  771. X    fprintf(stderr, "\n\tm  <-- Use MODEM7 Batch Mode on transmit");
  772. X    fprintf(stderr, "\n\tk  <-- Use 1K packets on transmit");
  773. X    fprintf(stderr, "\n\tc  <-- Select CRC mode on receive");
  774. X    fprintf(stderr, "\n\tt  <-- Indicate a TOO BUSY Unix system");
  775. X    fprintf(stderr, "\n\td  <-- Delete xmodem.log file before starting");
  776. X    fprintf(stderr, "\n\tl  <-- (ell) Turn OFF Log File Entries");
  777. X    fprintf(stderr, "\n\tx  <-- Include copious debugging information in log file");
  778. X    fprintf(stderr, "\n");
  779. X    }
  780. X
  781. X/* get type of transmission requested (text or binary) */
  782. Xgettype(ichar)
  783. Xchar ichar;
  784. X    {
  785. X    if (ichar == 't' || ichar == 'T')
  786. X        return('t');
  787. X    else if (ichar == 'b' || ichar == 'B')
  788. X        return('b');
  789. X    else if (ichar == 'a' || ichar == 'A')
  790. X        return('a');
  791. X    else
  792. X        error("Invalid Send/Receive Parameter - not t or b", FALSE);
  793. X    return('\0');
  794. X    }
  795. X
  796. X/* return a string containing transmission type */
  797. Xchar *
  798. Xprtype(ichar)
  799. Xchar ichar;
  800. X    {
  801. X    if (ichar == 't' || ichar == 'T')
  802. X        return("text");
  803. X    else if (ichar == 'b' || ichar == 'B')
  804. X        return("binary");
  805. X    else if (ichar == 'a' || ichar == 'A')
  806. X        return("apple");
  807. X    else
  808. X        return("");
  809. X    }
  810. X
  811. X/* print error message and exit; if mode == TRUE, restore normal tty modes */
  812. Xerror(msg, mode)
  813. Xchar *msg;
  814. Xint mode;
  815. X    {
  816. X    if (mode)
  817. X        restoremodes(TRUE);  /* put back normal tty modes */
  818. X    fprintf(stderr, "\r\n%s\n", msg);
  819. X    if ((LOGFLAG || DEBUG) && (LOGFP != NULL))
  820. X        {   
  821. X        fprintf(LOGFP, "XMODEM Fatal Error:  %s\n", msg);
  822. X            fclose(LOGFP);
  823. X        }
  824. X    exit(-1);
  825. X    }
  826. X
  827. X
  828. X/* Construct a proper (i.e. pretty) sector count for messages */
  829. X
  830. Xchar
  831. X*sectdisp(recvsectcnt, bufsize, plus1)
  832. Xlong recvsectcnt;
  833. Xint bufsize, plus1;
  834. X    {
  835. X    static char string[20];
  836. X    if (plus1)
  837. X        recvsectcnt += (bufsize == 128) ? 1 : 8;
  838. X    if (bufsize == 128 || recvsectcnt == 0)
  839. X        sprintf (string, "%d", recvsectcnt);
  840. X    else
  841. X        sprintf (string, "%d-%d", recvsectcnt-7, recvsectcnt);
  842. X    return(string);
  843. X    }
  844. X
  845. X/* type out debugging info */
  846. Xxmdebug(str)
  847. Xchar *str;
  848. X    {
  849. X    if (DEBUG && (LOGFP != NULL))
  850. X        fprintf(LOGFP,"DEBUG: '%s'\n",str);
  851. X    }
  852. X
  853. X/* print elapsed time and rate of transfer in logfile */
  854. X
  855. Xint quant[] = { 60, 60, 24};    
  856. Xchar sep[3][10] = { "second", "minute", "hour" };
  857. X
  858. Xprtime (numsect, seconds)
  859. Xlong numsect;
  860. Xtime_t seconds;
  861. X
  862. X{
  863. X    register int i;
  864. X    register int Seconds;
  865. X    int nums[3];
  866. X    int rate;
  867. X
  868. X    if (!LOGFLAG || numsect == 0)
  869. X        return(0);
  870. X
  871. X    Seconds = (int)seconds;
  872. X    Seconds = (Seconds > 0) ? Seconds : 0;
  873. X
  874. X    rate = (Seconds != 0) ? 128 * numsect/Seconds : 0;
  875. X
  876. X    for (i=0; i<3; i++) {
  877. X        nums[i] = (Seconds % quant[i]);
  878. X        Seconds /= quant[i];
  879. X    }
  880. X
  881. X    fprintf (LOGFP, "%ld Sectors Transfered in ", numsect);
  882. X
  883. X    if (rate == 0)
  884. X        fprintf (LOGFP, "0 seconds");
  885. X    else
  886. X        while (--i >= 0)
  887. X            if (nums[i])
  888. X                fprintf (LOGFP, "%d %s%c ", nums[i], &sep[i][0],
  889. X                    nums[i] == 1 ? ' ' : 's');
  890. X    fprintf (LOGFP, "\n");
  891. X
  892. X    if (rate != 0)
  893. X        fprintf (LOGFP, "Transfer Rate = %d Characters per Second\n", rate);
  894. X
  895. X    return(0);
  896. X}
  897. X
  898. X/* Print elapsed time estimate */
  899. X
  900. Xprojtime (numsect, fd)
  901. Xlong numsect;
  902. XFILE *fd;
  903. X    {
  904. X    register int i;
  905. X    register int seconds;
  906. X    int nums[3];
  907. X
  908. X    if (numsect == 0)
  909. X        return (0);
  910. X
  911. X/* constant below should really be 1280; reduced to 90% to account for time lost in overhead */
  912. X
  913. X    seconds = 1422 * numsect / ttyspeed + 1;
  914. X
  915. X    for (i=0; i<3; i++) {
  916. X        nums[i] = (seconds % quant[i]);
  917. X        seconds /= quant[i];
  918. X    }
  919. X
  920. X    fprintf (fd, "Estimated transmission time ");
  921. X
  922. X    while (--i >= 0)
  923. X        if (nums[i])
  924. X            fprintf (fd, "%d %s%c ", nums[i], &sep[i][0],
  925. X                nums[i] == 1 ? ' ' : 's');
  926. X    fprintf (fd, "\n");
  927. X    return (0);
  928. X    }
  929. !Funky!Stuff!
  930. exit
  931.  
  932.