home *** CD-ROM | disk | FTP | other *** search
- /*
- * Miscellaneous routines to support the xmodem file transfer protocols.
- */
-
- #include <stdio.h>
- #include <signal.h>
- #include <termio.h>
- #include <setjmp.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "param.h"
- #include "status.h"
- #include "xmodem.h"
-
- /*
- * Calculate the CRC for the given buffer
- */
-
- int
- calc_crc(buf, len)
- unsigned char *buf;
- int len;
- {
- int crc, i;
-
- crc = 0;
- while (--len >= 0) {
- /*
- * Some fancy foot work here... The algorithm looks good
- * in assembly, but in C it looks horrible!
- */
- crc = crc ^ (int) *buf++ << 8;
- for (i=0; i<8; i++) {
- if (crc & 0x8000)
- crc = crc << 1 ^ 0x1021;
- else
- crc = crc << 1;
- }
- }
- return(crc & 0xffff);
- }
-
- /*
- * Calculate the checksum for the given buffer.
- */
-
- unsigned char
- calc_sum(buf, len)
- unsigned char *buf;
- int len;
- {
- unsigned char sum;
-
- sum = 0;
- while (--len >= 0)
- sum += *buf++;
-
- return(sum);
- }
-
- /*
- * Get a character from the line with a specified time-out period in
- * seconds. If the function times-out, it returns a -1.
- */
-
- jmp_buf gl_jmp;
-
- int
- getc_line(sec)
- unsigned int sec;
- {
- int force_gl();
- unsigned char c;
- unsigned int alarm();
-
- signal(SIGALRM, force_gl);
- if (setjmp(gl_jmp))
- return(-1);
-
- alarm(sec);
- if (read(status->fd, (char *) &c, 1) <= 0) {
- alarm(0);
- return(-1);
- }
- alarm(0);
- return(c);
- }
- int
- force_gl(dummy)
- int dummy;
- {
- void longjmp();
-
- longjmp(gl_jmp, 1);
- }
-
- /*
- * Same as above, but reads a bunch of characters. The return code is
- * now just a success/fail indicator.
- */
-
- jmp_buf rl_jmp;
-
- int
- fread_line(buf, len, sec)
- unsigned char *buf;
- unsigned int len, sec;
- {
- int i, force_rl();
- unsigned int alarm();
-
- signal(SIGALRM, force_rl);
- if (setjmp(rl_jmp))
- return(-1);
-
- alarm(sec);
- /*
- * Later, this will have some fine tuning to use more than
- * single character I/O.
- */
- for (i=0; i<len; i++) {
- if (read(status->fd, (char *) buf++, 1) <= 0) {
- alarm(0);
- return(-1);
- }
- }
- alarm(0);
- return(0);
- }
- int
- force_rl(dummy)
- int dummy;
- {
- void longjmp();
-
- longjmp(rl_jmp, 1);
- }
-
- /*
- * Put a character on the tty line. This serves no useful purpose other
- * than making the code look pretty.
- */
-
- int
- putc_line(c)
- unsigned char c;
- {
- return(write(status->fd, (char *) &c, 1));
- }
-
- /*
- * Put the tty driver in the mode suitable for xmodem transfers.
- */
-
- void
- xmodem_mode(fd)
- int fd;
- {
- struct termio tbuf;
-
- ioctl(fd, TCGETA, &tbuf);
- /*
- * Turn off the XON/XOFF flow control, turn off echoing, and
- * switch to 8 bit no parity. Later, the VTIME and VMIN variables
- * will be fine tuned, to allow for more efficient I/O.
- */
- tbuf.c_cc[4] = 1; /* VMIN */
- tbuf.c_cc[5] = 0; /* VTIME */
- tbuf.c_iflag = 0; /* no flow control or mapping */
- tbuf.c_oflag = 0; /* no char mapping or delays */
- tbuf.c_lflag = 0; /* no echo or signals */
- tbuf.c_cflag &= ~PARENB; /* no parity */
- tbuf.c_cflag &= ~CSIZE;
- tbuf.c_cflag |= CS8; /* 8 bit */
-
- ioctl(fd, TCSETA, &tbuf);
- ioctl(fd, TCFLSH, 2);
- return;
- }
-
- /*
- * Cancel the file transfer. Send several ^X's to the remote, followed
- * by an equal number of backspace (in case they have already aborted and
- * we're really at the command line).
- */
-
- void
- cancel_xfer()
- {
- extern char file_name[15];
-
- if (!strcmp(param->abort, "DELETE"))
- unlink(file_name);
-
- putc_line(CAN);
- putc_line(CAN);
- putc_line(CAN);
- putc_line(8);
- putc_line(8);
- putc_line(8);
- return;
- }
-
- /*
- * Shorten a file to a predetermined length. Used to remove the ^Z
- * padding from the end of files. (Heaven help us, if one day a binary
- * file actually has ^Z's as part of the end of the file).
- */
-
- int
- fix_length(file, len)
- char *file;
- int len;
- {
- FILE *fp, *tempfp;
- int num;
- char *tempfile, *mktemp();
- unsigned char buf[BUFSIZ];
- struct stat stbuf;
-
- if (stat(file, &stbuf) < 0)
- return(1);
- /* see if we have any work to do */
- if (len >= stbuf.st_size)
- return(0);
-
- if (!(fp = fopen(file, "r")))
- return(1);
-
- /*
- * The temporary file should be in the same directory as the
- * file being received because otherwise we'd have no way of
- * guaranteeing they would be in the same file system. (Hard
- * links across different file systems aren't allowed).
- */
- tempfile = mktemp("trunXXXXXX");
- if (!(tempfp = fopen(tempfile, "w"))) {
- fclose(fp);
- return(1);
- }
-
- while(len) {
- num = (len > BUFSIZ) ? BUFSIZ : len;
- fread((char *) buf, sizeof(buf[0]), num, fp);
- fwrite((char *) buf, sizeof(buf[0]), num, tempfp);
- len -= num;
- }
-
- fclose(fp);
- fclose(tempfp);
-
- if (unlink(file) < 0)
- return(1);
-
- if (link(tempfile, file) < 0)
- return(1);
-
- if (unlink(tempfile) < 0)
- return(1);
-
- return(0);
- }
-