home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / xmodem3.6 / part05 < prev    next >
Encoding:
Internet Message Format  |  1988-06-13  |  14.9 KB

  1. Subject:  v15i074:  Xmodem release 3.6, Part05/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 74
  8. Archive-name: xmodem3.6/part05
  9.  
  10. : This is a shar archive.  Extract with sh, not csh.
  11. echo x - tip.diffs
  12. sed -e 's/^X//' > tip.diffs << '!Funky!Stuff!'
  13. X
  14. X*** cmdtab.c.ORIG    Mon May  5 11:01:59 1986
  15. X--- cmdtab.c    Thu Aug 21 10:08:50 1986
  16. X***************
  17. X*** 15,16 ****
  18. X--- 15,17 ----
  19. X  extern    int cu_take(), cu_put(), dollar(), genbrk(), suspend();
  20. X+ extern    int rtfile(), stfile(), rbfile(), sbfile();
  21. X  
  22. X***************
  23. X*** 35,36 ****
  24. X--- 36,41 ----
  25. X      { '#',    NORM,    "send break",             genbrk },
  26. X+     { '{',    NORM,    "receive xmodem text file",      rtfile },
  27. X+     { '}',    NORM,    "send xmodem text file",      stfile },
  28. X+     { '(',    NORM,    "receive xmodem binary file",     rbfile },
  29. X+     { ')',    NORM,    "send xmodem binary file",      sbfile },
  30. X      { 0, 0, 0 }
  31. X
  32. X
  33. X
  34. X*** cmds.c.ORIG    Mon May  5 11:01:56 1986
  35. X--- cmds.c    Tue Sep 30 10:17:11 1986
  36. X***************
  37. X*** 855,856 ****
  38. X--- 865,1412 ----
  39. X      return(0);
  40. X+ }
  41. X+ 
  42. X+ 
  43. X+ /*  XMODEM stuff; sag sept 1984    - Feb 1985
  44. X+  *    Taken from Brian Kantor's (sdccsu3!brian) xmodem version 1.0
  45. X+  *    Note that this code will work on version 4.2 ONLY (uses select)
  46. X+  */
  47. X+ 
  48. X+ #include <sys/stat.h>
  49. X+ #include <sys/time.h>
  50. X+ 
  51. X+ /*  ASCII Constants  */
  52. X+ #define      SOH      001 
  53. X+ #define         STX    002
  54. X+ #define         ETX    003
  55. X+ #define      EOT    004
  56. X+ #define         ENQ    005
  57. X+ #define      ACK      006
  58. X+ #define         LF        012   /* Unix LF/NL */
  59. X+ #define         CR        015  
  60. X+ #define      NAK      025
  61. X+ #define         SYN    026
  62. X+ #define         CAN    030
  63. X+ #define         ESC    033
  64. X+ #define         CTRLZ    032   /* CP/M EOF for text (usually!) */
  65. X+ 
  66. X+ /*  XMODEM Constants  */
  67. X+ #define      TIMEOUT      -1
  68. X+ #define      ERRORMAX      10    /* maximum errors tolerated */
  69. X+ #define      RETRYMAX      10    /* maximum retries to be made */
  70. X+ #define         BBUFSIZ    128   /* buffer size -- do not change! */
  71. X+ #define      DEBUG    0     /* 1 for debugging output */
  72. X+ #define      GETERR    -10   /* error code for getbyte routine */
  73. X+ 
  74. X+ char buff[BBUFSIZ];
  75. X+ 
  76. X+ int nbchr;    /* number of chars read so far for buffered read */
  77. X+ 
  78. X+ /* Receive a text file */
  79. X+ rtfile(c)
  80. X+ char c;
  81. X+ {
  82. X+     putchar (c);
  83. X+     rfile ('t');
  84. X+ }
  85. X+ 
  86. X+ /* Receive a binary file */
  87. X+ rbfile(c)
  88. X+ char c;
  89. X+ {
  90. X+     putchar (c);
  91. X+     rfile ('b');
  92. X+ }
  93. X+ 
  94. X+ /* Send a text file */
  95. X+ stfile(c)
  96. X+ char c;
  97. X+ {
  98. X+     putchar (c);
  99. X+     sfile ('t');
  100. X+ }
  101. X+ 
  102. X+ /* Send a binary file */
  103. X+ sbfile(c)
  104. X+ char c;
  105. X+ {
  106. X+     putchar (c);
  107. X+     sfile ('b');
  108. X+ }
  109. X+ 
  110. X+ /* print error message and cleanup for exit */
  111. X+ error(msg)
  112. X+ char *msg;
  113. X+     {
  114. X+     printf("\r\nXMODEM:  %s\n", msg);
  115. X+     ioctl (0, TIOCSETC, &tchars);
  116. X+     write (fildes[1], (char *)&ccc, 1);
  117. X+     signal (SIGINT, SIG_DFL);
  118. X+     }
  119. X+ 
  120. X+ /*
  121. X+  *
  122. X+  *    Get a byte from the specified file.  Buffer the read so we don't
  123. X+  *    have to use a system call for each character.
  124. X+  *
  125. X+  */
  126. X+ getbyte(fildes, ch)                /* Buffered disk read */
  127. X+ int fildes;
  128. X+ char *ch;
  129. X+ 
  130. X+     {
  131. X+     static char buf[BUFSIZ];    /* Remember buffer */
  132. X+     static char *bufp = buf;    /* Remember where we are in buffer */
  133. X+     
  134. X+     if (nbchr == 0)            /* Buffer exausted; read some more */
  135. X+         {
  136. X+         if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
  137. X+             {
  138. X+             error("File Read Error");
  139. X+             return (GETERR);
  140. X+              }
  141. X+         bufp = buf;        /* Set pointer to start of array */
  142. X+         }
  143. X+     if (--nbchr >= 0)
  144. X+         {
  145. X+         *ch = *bufp++;
  146. X+         return(0);
  147. X+         }
  148. X+     else
  149. X+         return(EOF);
  150. X+     }
  151. X+ 
  152. X+ /**  receive a file  **/
  153. X+ rfile(mode)
  154. X+ char mode;
  155. X+     {
  156. X+     register int bufctr, checksum;
  157. X+     register int c;
  158. X+     int j, firstchar, sectnum, sectcurr, tmode;
  159. X+     int sectcomp, errors, errorflag, recfin;
  160. X+     int fatalerror, inchecksum;
  161. X+     long recvsectcnt;
  162. X+ 
  163. X+     int (*f) ();
  164. X+     char *cp, *expand();
  165. X+     time_t start;
  166. X+ 
  167. X+     if (prompt (" Receive local file name? ", copyname))
  168. X+         return;
  169. X+     cp = expand (copyname);
  170. X+     if ((sfd = creat (cp, 0666)) < 0)
  171. X+         {
  172. X+         printf ("\r\n%s: Cannot creat\r\n", copyname);
  173. X+         return;
  174. X+         }
  175. X+ 
  176. X+     kill (pid, SIGIOT);
  177. X+     read (repdes[0], (char *)&ccc, 1); /* wait until read process stops */
  178. X+     ioctl (0, TIOCSETC, &defchars);       /* set tty modes */
  179. X+     f = signal (SIGINT, intcopy);       /* intercept control-c */
  180. X+ 
  181. X+     start = time(0);
  182. X+     quit = 0;
  183. X+     (void) setjmp(intbuf);           /* set control-c catcher */
  184. X+ 
  185. X+     if (quit)
  186. X+         {
  187. X+         error("Control-C; Reception canceled");
  188. X+         close (sfd);
  189. X+         return;
  190. X+         }
  191. X+ 
  192. X+     printf("XMODEM:  Ready to RECEIVE File %s", cp);
  193. X+     puts("\r\nControl-C to cancel.\n");
  194. X+ 
  195. X+     recfin = FALSE;
  196. X+     sectnum = errors = 0;
  197. X+     fatalerror = FALSE;  /* NO fatal errors */
  198. X+     recvsectcnt = 0;  /* number of received sectors */
  199. X+ 
  200. X+     if (mode == 't')
  201. X+         tmode = TRUE;
  202. X+     else
  203. X+         tmode = FALSE;
  204. X+ 
  205. X+     sendbyte(NAK);  /* Start up the sender's first block */
  206. X+ 
  207. X+         do
  208. X+             {   
  209. X+         errorflag = FALSE;
  210. X+                 do 
  211. X+             {
  212. X+                       firstchar = readbyte(6);
  213. X+                     } 
  214. X+             while ((firstchar != SOH) 
  215. X+                 && (firstchar != EOT) 
  216. X+                 && (firstchar != TIMEOUT) 
  217. X+                 && ((firstchar & 0x7f) != CAN));
  218. X+ 
  219. X+                 if (firstchar == TIMEOUT)
  220. X+                 {  
  221. X+             printf("\r\nTimeout on Sector %d\n", sectnum+1);
  222. X+                        errorflag = TRUE;
  223. X+                 }
  224. X+ 
  225. X+                 if ((firstchar & 0x7f) == CAN)
  226. X+                 {  
  227. X+             error("Reception canceled at user's request");
  228. X+             close (sfd);
  229. X+             return;
  230. X+                 }
  231. X+ 
  232. X+                 if (firstchar == SOH)
  233. X+                {
  234. X+                        sectcurr = readbyte(3);       /* get sector numbers */
  235. X+                        sectcomp = readbyte(3);
  236. X+                        if ((sectcurr + sectcomp) == 0xff)
  237. X+                            {  
  238. X+                 if (sectcurr == ((sectnum+1) & 0xff))
  239. X+                      {  
  240. X+                     checksum = 0;
  241. X+                          for (j = bufctr = 0; j < BBUFSIZ; j++)
  242. X+                                    {  
  243. X+                         buff[bufctr] = c = readbyte(3);
  244. X+                             checksum = ((checksum+c) & 0xff);
  245. X+                         if (!tmode)  /* binary mode */
  246. X+                             {  
  247. X+                             bufctr++;
  248. X+                                    continue;
  249. X+                                 }
  250. X+                         if (c == CR)
  251. X+                                continue;  /* skip CR's */
  252. X+                         if (c == CTRLZ)  /* CP/M EOF char */
  253. X+                             {  
  254. X+                             recfin = TRUE;  /* flag EOF */
  255. X+                                    continue;
  256. X+                                 }
  257. X+                             if (!recfin)
  258. X+                                bufctr++;
  259. X+                              }
  260. X+                          inchecksum = readbyte(3);  /* get checksum */
  261. X+                         if (checksum == inchecksum)  /* good checksum */
  262. X+                              {  
  263. X+                         errors = 0;
  264. X+                         recvsectcnt++;
  265. X+                             sectnum = sectcurr; 
  266. X+                         if (DEBUG) printf ("\n");
  267. X+                         printf ("\rreceived sector %-4d", recvsectcnt);
  268. X+                         if (write(sfd, buff, bufctr) < 0) 
  269. X+                             {
  270. X+                             sendbyte(CAN);
  271. X+                                error("File Write Error");
  272. X+                             close (sfd);
  273. X+                             return;
  274. X+                             }
  275. X+                             else 
  276. X+                                sendbyte(ACK);
  277. X+ 
  278. X+                              }
  279. X+                          else
  280. X+                              {  
  281. X+                         printf("\r\nChecksum Error on Sector %d\n", sectnum+1);
  282. X+                             errorflag = TRUE;
  283. X+                              }
  284. X+                               }
  285. X+                           else
  286. X+                               { 
  287. X+                     if (sectcurr == sectnum)
  288. X+                                     {  
  289. X+                         while(readbyte(3) != TIMEOUT)
  290. X+                             ;
  291. X+                                        sendbyte(ACK);
  292. X+                                     }
  293. X+                                 else
  294. X+                             {  
  295. X+                         printf("\r\nPhase Error - Received Sector is ");
  296. X+                           printf("%d while Expected Sector is %d\n",
  297. X+                                sectcurr, ((sectnum+1) & 0xff));
  298. X+                         errorflag = TRUE;
  299. X+                         fatalerror = TRUE;
  300. X+                         sendbyte(CAN);
  301. X+                             }
  302. X+                           }
  303. X+                        }
  304. X+             else
  305. X+                    {  
  306. X+                 printf("\r\nHeader Sector Number Error on Sector %d\n",
  307. X+                        sectnum+1);
  308. X+                            errorflag = TRUE;
  309. X+                    }
  310. X+                 }
  311. X+     
  312. X+             if (errorflag)
  313. X+                 {  
  314. X+             errors++;
  315. X+                while (readbyte(3) != TIMEOUT)
  316. X+                 ;
  317. X+             sendbyte(NAK);
  318. X+                 }
  319. X+           }
  320. X+           while ((firstchar != EOT) && (errors < ERRORMAX) && !fatalerror);
  321. X+ 
  322. X+       if ((firstchar == EOT) && (errors < ERRORMAX) && !fatalerror)
  323. X+           {
  324. X+              close(sfd);
  325. X+         sendbyte(ACK);
  326. X+         printf("\n\rReceive Complete");
  327. X+         printf("\n\r%ld CP/M Records ", recvsectcnt);
  328. X+         prtime(" transferred in ", time(0)-start);
  329. X+ 
  330. X+         ioctl (0, TIOCSETC, &tchars);        /* reset ttys */
  331. X+         write (fildes[1], (char *)&ccc, 1);    /* wakeup tip */
  332. X+         signal (SIGINT, SIG_DFL);        /* reset control-c catcher */
  333. X+           }
  334. X+       else
  335. X+           { 
  336. X+         sendbyte(CAN);
  337. X+              error("\r\nABORTED -- Too Many Errors");
  338. X+         close (sfd);
  339. X+         return;
  340. X+           }
  341. X+     }
  342. X+ 
  343. X+ /**  send a file  **/
  344. X+ sfile(mode)
  345. X+ char mode;
  346. X+     {
  347. X+     register int bufctr, checksum, sectnum;
  348. X+     char blockbuf[134];
  349. X+     int fd, attempts;
  350. X+     int nlflag, sendfin, tmode;
  351. X+     int bbufcnt;
  352. X+     int firstchar;
  353. X+     int getretrn;
  354. X+     char c;
  355. X+     int sendresp;  /* response char to sent block */
  356. X+ 
  357. X+     int (*f) ();
  358. X+     char *cp, *expand();
  359. X+     time_t start;
  360. X+ 
  361. X+     if (prompt (" Send local file name? ", copyname))
  362. X+         return;
  363. X+     cp = expand (copyname);
  364. X+     if ((fd = open(cp, 0)) < 0)
  365. X+         {  
  366. X+                 printf("Can't open file for send\n");
  367. X+         return;
  368. X+         }
  369. X+ 
  370. X+     kill (pid, SIGIOT);
  371. X+     read (repdes[0], (char *)&ccc, 1); /* wait until read process stops */
  372. X+     ioctl (0, TIOCSETC, &defchars);    /* setup tty */
  373. X+     f = signal (SIGINT, intcopy);       /* prepare to catch control-c */
  374. X+     start = time(0);
  375. X+     quit = 0;
  376. X+     (void) setjmp(intbuf);           /* setup control-c catcher */
  377. X+ 
  378. X+     nbchr = 0;  /* clear buffered read char count */
  379. X+         
  380. X+     if (quit)
  381. X+         {
  382. X+         sendbyte(CAN);
  383. X+         error("Control-C; Send canceled");
  384. X+         close (fd);
  385. X+         return;
  386. X+         }
  387. X+ 
  388. X+     printf("XMODEM:  File %s Ready to SEND", cp);
  389. X+     prfilestat(cp);  /* print file size statistics */
  390. X+     puts("\r\nControl-C to cancel.\n");
  391. X+ 
  392. X+     if (mode == 't')
  393. X+        tmode = TRUE;
  394. X+     else
  395. X+        tmode = FALSE;
  396. X+ 
  397. X+         sendfin = nlflag = FALSE;
  398. X+       attempts = 0;
  399. X+ 
  400. X+     while (((firstchar=readbyte(30)) != NAK) && (firstchar != CAN))
  401. X+         {
  402. X+         if (++attempts > RETRYMAX) {
  403. X+             error("Remote System Not Responding");
  404. X+             close (fd);
  405. X+             return;
  406. X+         }
  407. X+         }
  408. X+ 
  409. X+     if ((firstchar & 0x7f) == CAN)
  410. X+         {
  411. X+         error("Send cancelled at user's request.");
  412. X+         close (fd);
  413. X+         return;
  414. X+         }
  415. X+ 
  416. X+     sectnum = 1;  /* first sector number */
  417. X+     attempts = 0;
  418. X+ 
  419. X+         do 
  420. X+         {   
  421. X+         for (bufctr=0; bufctr < BBUFSIZ;)
  422. X+                 {
  423. X+             if (nlflag)
  424. X+                     {  
  425. X+                 buff[bufctr++] = LF;  /* leftover newline */
  426. X+                        nlflag = FALSE;
  427. X+                     }
  428. X+             getretrn = getbyte(fd, &c);
  429. X+             if (getretrn == GETERR)
  430. X+                 {
  431. X+                 sendbyte(CAN);
  432. X+                 error ("Read error on local file");
  433. X+                 close (fd);
  434. X+                 return;
  435. X+                 }
  436. X+             if (getretrn == EOF)
  437. X+                 { 
  438. X+                 sendfin = TRUE;  /* this is the last sector */
  439. X+                    if (!bufctr)  /* if EOF on sector boundary */
  440. X+                           break;  /* avoid sending extra sector */
  441. X+                    if (tmode)
  442. X+                           buff[bufctr++] = CTRLZ;  /* Control-Z for CP/M EOF */
  443. X+                        else
  444. X+                           bufctr++;
  445. X+                    continue;
  446. X+                       }
  447. X+ 
  448. X+             if (tmode && c == LF)  /* text mode & Unix newline? */
  449. X+                     {
  450. X+                 buff[bufctr++] = CR;  /* insert carriage return */
  451. X+                      if (bufctr < BBUFSIZ)
  452. X+                             buff[bufctr++] = LF;  /* insert LF */
  453. X+                        else
  454. X+                         nlflag = TRUE;  /* insert on next sector */
  455. X+                    }    
  456. X+             else
  457. X+                 buff[bufctr++] = c;  /* copy the char without change */
  458. X+                 }
  459. X+ 
  460. X+                 attempts = 0;
  461. X+     
  462. X+             if (!bufctr)  /* if EOF on sector boundary */
  463. X+                       break;  /* avoid sending empty sector */
  464. X+ 
  465. X+                 do
  466. X+                     {
  467. X+             bbufcnt = 0;        /* start building block to be sent */
  468. X+             blockbuf[bbufcnt++] = SOH;        /* start of packet char */
  469. X+             blockbuf[bbufcnt++] = sectnum;        /* current sector # */
  470. X+             blockbuf[bbufcnt++] = -sectnum-1;   /* and its complement */
  471. X+ 
  472. X+                     checksum = 0;  /* init checksum */
  473. X+                     for (bufctr=0; bufctr < BBUFSIZ; bufctr++)
  474. X+                            {
  475. X+                 blockbuf[bbufcnt++] = buff[bufctr];
  476. X+                          checksum = ((checksum+buff[bufctr]) & 0xff);
  477. X+                      }
  478. X+ 
  479. X+             blockbuf[bbufcnt++] = checksum;
  480. X+             write(FD, blockbuf, 132);  /* write the block */
  481. X+             ioctl(FD,TIOCFLUSH,0);
  482. X+ 
  483. X+                     attempts++;
  484. X+             sendresp = readbyte(10);  /* get response */
  485. X+             if (sendresp != ACK)
  486. X+                    {
  487. X+                    printf("\r\nNon-ACK Received on Sector %d\n",sectnum);
  488. X+                    if (sendresp == TIMEOUT)
  489. X+                     printf("\r\nThis Non-ACK was a TIMEOUT\n");
  490. X+                    }
  491. X+                     }
  492. X+             while((sendresp != ACK) && (attempts < RETRYMAX));
  493. X+ 
  494. X+                sectnum++;  /* increment to next sector number */
  495. X+         if (DEBUG) printf ("\n");
  496. X+         printf ("\rsent sector %-4d", sectnum-1);
  497. X+             }
  498. X+         while (!sendfin && (attempts < RETRYMAX));
  499. X+ 
  500. X+         if (attempts >= RETRYMAX) 
  501. X+         {
  502. X+         error("Remote System Not Responding");
  503. X+         close (fd);
  504. X+         return;
  505. X+         }
  506. X+ 
  507. X+         attempts = 0;
  508. X+         sendbyte(EOT);  /* send 1st EOT */
  509. X+     
  510. X+         while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX))
  511. X+            sendbyte(EOT);
  512. X+ 
  513. X+         if (attempts >= RETRYMAX)
  514. X+            error("Remote System Not Responding on Completion");
  515. X+ 
  516. X+         close(fd);
  517. X+         printf("\r\nSend Complete\r\n");
  518. X+     prtime("Data transferred in ", time(0)-start);
  519. X+ 
  520. X+     ioctl (0, TIOCSETC, &tchars);        /* restore tty */
  521. X+     write (fildes[1], (char *)&ccc, 1);    /* wakeup tip */
  522. X+     signal (SIGINT, SIG_DFL);        /* reset control-c catcher */
  523. X+         sleep(5);  /* give other side time to return to terminal mode */
  524. X+ 
  525. X+     }
  526. X+ 
  527. X+ /*  print file size status information  */
  528. X+ prfilestat(name)
  529. X+ char *name;
  530. X+     {
  531. X+     struct stat filestatbuf; /* file status info */
  532. X+ 
  533. X+     stat(name, &filestatbuf);  /* get file status bytes */
  534. X+     printf("\r\nEstimated File Size %ldK, %ld Records, %ld Bytes",
  535. X+           (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
  536. X+           filestatbuf.st_size);
  537. X+         return;
  538. X+     }
  539. X+ 
  540. X+ /* get a byte from data stream -- timeout if "seconds" elapses */
  541. X+ int readbyte(seconds)
  542. X+ int seconds;
  543. X+     {
  544. X+     int i, readfd;
  545. X+     char c;
  546. X+     struct timeval tmout;
  547. X+ 
  548. X+     tmout.tv_sec = seconds;
  549. X+     tmout.tv_usec = 0;
  550. X+ 
  551. X+     readfd = 1 << FD;
  552. X+ 
  553. X+     if ((i=select(FD+1, &readfd, 0, 0, &tmout)) == 0)
  554. X+         {
  555. X+         return(TIMEOUT);
  556. X+         }
  557. X+ 
  558. X+     read(FD, &c, 1);
  559. X+ 
  560. X+     return(c & 0xff);  /* return the char */
  561. X+     }
  562. X+ 
  563. X+ /* send a byte to data stream */
  564. X+ sendbyte(data)
  565. X+ char data;
  566. X+     {
  567. X+     write(FD, &data, 1);      /* write the byte */
  568. X+     ioctl(FD,TIOCFLUSH,0);    /* flush so it really happens now! */
  569. X+     return;
  570. X+     }
  571. X+ 
  572. X+ /*
  573. X+  * "nap" for specified time
  574. X+  */
  575. X+ nap (milliseconds)
  576. X+ int    milliseconds;
  577. X+ {
  578. X+     struct    timeval    timeout;
  579. X+ 
  580. X+     if (milliseconds == 0)
  581. X+         return;
  582. X+     timeout.tv_sec = 0;
  583. X+     timeout.tv_usec = milliseconds * 1000;
  584. X+ 
  585. X+     (void) select(1, 0, 0, 0, &timeout);
  586. X  }
  587. !Funky!Stuff!
  588. exit
  589.  
  590.