home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / pcomm / part06 / xmodem.c < prev   
Encoding:
C/C++ Source or Header  |  1988-05-18  |  4.5 KB  |  263 lines

  1. /*
  2.  * Miscellaneous routines to support the xmodem file transfer protocols.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <signal.h>
  7. #include <termio.h>
  8. #include <setjmp.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include "param.h"
  12. #include "status.h"
  13. #include "xmodem.h"
  14.  
  15. /*
  16.  * Calculate the CRC for the given buffer
  17.  */
  18.  
  19. int
  20. calc_crc(buf, len)
  21. unsigned char *buf;
  22. int len;
  23. {
  24.     int crc, i;
  25.     
  26.     crc = 0;
  27.     while (--len >= 0) {
  28.         /*
  29.          * Some fancy foot work here... The algorithm looks good
  30.          * in assembly, but in C it looks horrible!
  31.          */
  32.         crc = crc ^ (int) *buf++ << 8;
  33.         for (i=0; i<8; i++) {
  34.             if (crc & 0x8000)
  35.                 crc = crc << 1 ^ 0x1021;
  36.             else
  37.                 crc = crc << 1;
  38.         }
  39.     }
  40.     return(crc & 0xffff);
  41. }
  42.  
  43. /*
  44.  * Calculate the checksum for the given buffer.
  45.  */
  46.  
  47. unsigned char
  48. calc_sum(buf, len)
  49. unsigned char *buf;
  50. int len;
  51. {
  52.     unsigned char sum;
  53.  
  54.     sum = 0;
  55.     while (--len >= 0)
  56.         sum += *buf++;
  57.  
  58.     return(sum);
  59. }
  60.  
  61. /*
  62.  * Get a character from the line with a specified time-out period in
  63.  * seconds.  If the function times-out, it returns a -1.
  64.  */
  65.  
  66. jmp_buf gl_jmp;
  67.  
  68. int
  69. getc_line(sec)
  70. unsigned int sec;
  71. {
  72.     int force_gl();
  73.     unsigned char c;
  74.     unsigned int alarm();
  75.  
  76.     signal(SIGALRM, force_gl);
  77.     if (setjmp(gl_jmp))
  78.         return(-1);
  79.  
  80.     alarm(sec);
  81.     if (read(status->fd, (char *) &c, 1) <= 0) {
  82.         alarm(0);
  83.         return(-1);
  84.     }
  85.     alarm(0);
  86.     return(c);
  87. }
  88. int
  89. force_gl(dummy)
  90. int dummy;
  91. {
  92.     void longjmp();
  93.  
  94.     longjmp(gl_jmp, 1);
  95. }
  96.  
  97. /*
  98.  * Same as above, but reads a bunch of characters.  The return code is
  99.  * now just a success/fail indicator.
  100.  */
  101.  
  102. jmp_buf rl_jmp;
  103.  
  104. int
  105. fread_line(buf, len, sec)
  106. unsigned char *buf;
  107. unsigned int len, sec;
  108. {
  109.     int i, force_rl();
  110.     unsigned int alarm();
  111.  
  112.     signal(SIGALRM, force_rl);
  113.     if (setjmp(rl_jmp))
  114.         return(-1);
  115.  
  116.     alarm(sec);
  117.     /*
  118.      * Later, this will have some fine tuning to use more than
  119.      * single character I/O.
  120.      */
  121.     for (i=0; i<len; i++) {
  122.         if (read(status->fd, (char *) buf++, 1) <= 0) {
  123.             alarm(0);
  124.             return(-1);
  125.         }
  126.     }
  127.     alarm(0);
  128.     return(0);
  129. }
  130. int
  131. force_rl(dummy)
  132. int dummy;
  133. {
  134.     void longjmp();
  135.  
  136.     longjmp(rl_jmp, 1);
  137. }
  138.  
  139. /*
  140.  * Put a character on the tty line.  This serves no useful purpose other
  141.  * than making the code look pretty.
  142.  */
  143.  
  144. int
  145. putc_line(c)
  146. unsigned char c;
  147. {
  148.     return(write(status->fd, (char *) &c, 1));
  149. }
  150.  
  151. /*
  152.  * Put the tty driver in the mode suitable for xmodem transfers.
  153.  */
  154.  
  155. void
  156. xmodem_mode(fd)
  157. int fd;
  158. {
  159.     struct termio tbuf;
  160.  
  161.     ioctl(fd, TCGETA, &tbuf);
  162.     /*
  163.      * Turn off the XON/XOFF flow control, turn off echoing, and
  164.      * switch to 8 bit no parity.  Later, the VTIME and VMIN variables
  165.      * will be fine tuned, to allow for more efficient I/O.
  166.      */
  167.     tbuf.c_cc[4] = 1;        /* VMIN */
  168.     tbuf.c_cc[5] = 0;        /* VTIME */
  169.     tbuf.c_iflag = 0;        /* no flow control or mapping */
  170.     tbuf.c_oflag = 0;        /* no char mapping or delays */
  171.     tbuf.c_lflag = 0;        /* no echo or signals */
  172.     tbuf.c_cflag &= ~PARENB;    /* no parity */
  173.     tbuf.c_cflag &= ~CSIZE;
  174.     tbuf.c_cflag |= CS8;        /* 8 bit */
  175.  
  176.     ioctl(fd, TCSETA, &tbuf);
  177.     ioctl(fd, TCFLSH, 2);
  178.     return;
  179. }
  180.  
  181. /*
  182.  * Cancel the file transfer.  Send several ^X's to the remote, followed
  183.  * by an equal number of backspace (in case they have already aborted and
  184.  * we're really at the command line).
  185.  */
  186.  
  187. void
  188. cancel_xfer()
  189. {
  190.     extern char file_name[15];
  191.  
  192.     if (!strcmp(param->abort, "DELETE"))
  193.         unlink(file_name);
  194.  
  195.     putc_line(CAN);
  196.     putc_line(CAN);
  197.     putc_line(CAN);
  198.     putc_line(8);
  199.     putc_line(8);
  200.     putc_line(8);
  201.     return;
  202. }
  203.  
  204. /*
  205.  * Shorten a file to a predetermined length.  Used to remove the ^Z
  206.  * padding from the end of files.  (Heaven help us, if one day a binary
  207.  * file actually has ^Z's as part of the end of the file).
  208.  */
  209.  
  210. int
  211. fix_length(file, len)
  212. char *file;
  213. int len;
  214. {
  215.     FILE *fp, *tempfp;
  216.     int num;
  217.     char *tempfile, *mktemp();
  218.     unsigned char buf[BUFSIZ];
  219.     struct stat stbuf;
  220.  
  221.     if (stat(file, &stbuf) < 0)
  222.         return(1);
  223.                     /* see if we have any work to do */
  224.     if (len >= stbuf.st_size)
  225.         return(0);
  226.  
  227.     if (!(fp = fopen(file, "r")))
  228.         return(1);
  229.  
  230.     /*
  231.      * The temporary file should be in the same directory as the
  232.      * file being received because otherwise we'd have no way of
  233.      * guaranteeing they would be in the same file system.  (Hard
  234.      * links across different file systems aren't allowed).
  235.      */
  236.     tempfile = mktemp("trunXXXXXX");
  237.     if (!(tempfp = fopen(tempfile, "w"))) {
  238.         fclose(fp);
  239.         return(1);
  240.     }
  241.  
  242.     while(len) {
  243.         num = (len > BUFSIZ) ? BUFSIZ : len;
  244.         fread((char *) buf, sizeof(buf[0]), num, fp);
  245.         fwrite((char *) buf, sizeof(buf[0]), num, tempfp);
  246.         len -= num;
  247.     }
  248.  
  249.     fclose(fp);
  250.     fclose(tempfp);
  251.  
  252.     if (unlink(file) < 0)
  253.         return(1);
  254.  
  255.     if (link(tempfile, file) < 0)
  256.         return(1);
  257.  
  258.     if (unlink(tempfile) < 0)
  259.         return(1);
  260.  
  261.     return(0);
  262. }
  263.