home *** CD-ROM | disk | FTP | other *** search
- /*
- * Transfer a file using just XON/XOFF flow control. Currently limited to
- * 7 bit ASCII codes. (If this causes too much trouble, I'll change it).
- */
-
- #define CLIST 64
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <curses.h>
- #include <signal.h>
- #include "config.h"
- #include "misc.h"
- #include "param.h"
-
- void
- xfer_ascii(list, up)
- char *list;
- int up;
- {
- int cr_lf;
- char *file, *strtok();
- void send_ascii(), rcv_ascii(), line_set(), st_line(), suspend();
- void load_vs(), ascii_mode();
- unsigned int sleep();
-
- touchwin(stdscr);
- refresh();
- /* only one file from list */
- file = strtok(list, " ");
-
- cr_lf = !strcmp(param->cr_out, "CR/LF");
- ascii_mode(up);
- if (up) {
- /* un-suspend the input routine */
- suspend(0);
-
- send_ascii(file, cr_lf);
- /* re-suspend the input routine */
- suspend(1);
- }
- else
- rcv_ascii(file, cr_lf);
-
- /*
- * Restoring the TTY modes is easier than setting them... The
- * fixterm() and line_set() routines fix most of the damage.
- */
- fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY);
- line_set();
- fixterm();
-
- /*
- * On downloading, the contents of the virtual screen won't contain
- * the characters shown during the transfer. Too bad...
- */
- load_vs();
- beep();
- st_line("xfer complete");
-
- sleep(2);
- return;
- }
-
- /*
- * Put the TTY line in a mode suitable for the ASCII transfer. Puts the
- * terminal in the raw, non-blocking mode.
- */
-
- static void
- ascii_mode(up)
- int up;
- {
- extern int fd;
- struct termio tbuf;
- void input_off(), term_mode();
-
- ioctl(fd, TCGETA, &tbuf);
- tbuf.c_oflag = 0;
- /* flow control & 8th bit stripping */
- if (up) {
- tbuf.c_iflag = (ISTRIP|IXON);
-
- /* use NL delays if no CR */
- if (!strcmp(param->cr_up, "STRIP"))
- tbuf.c_oflag = (OPOST|ONLRET);
-
- /* CR delay times */
- switch (param->cr_delay) {
- case 0:
- tbuf.c_oflag = 0;
- break;
- case 100:
- tbuf.c_oflag |= (OPOST|CR2);
- break;
- case 150:
- tbuf.c_oflag |= (OPOST|CR3);
- break;
- }
- }
- /* if down loading */
- else {
- tbuf.c_iflag = (ISTRIP|IXOFF);
- /* kill the input routine */
- input_off();
- }
-
- ioctl(fd, TCSETA, &tbuf);
- ioctl(fd, TCFLSH, 2);
- /* out of curses mode */
- resetterm();
- term_mode();
- /* non-blocking mode */
- fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY);
- return;
- }
-
- /*
- * Send a file. The local echo option is independent of the duplex option,
- * and would very rarely be used since the characters are most likely
- * being echoed on the screen anyway.
- */
-
- static void
- send_ascii(file, cr_lf)
- char *file;
- int cr_lf;
- {
- extern int fd;
- FILE *fp;
- int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, lecho, pace;
- unsigned char c, last;
- unsigned int sleep();
- /* permission already checked */
- if (!(fp = fopen(file, "r")))
- return;
- /* ASCII transfer options */
- strip_cr = !strcmp(param->cr_up, "STRIP");
- add_lf = !strcmp(param->cr_up, "ADD LF");
- strip_lf = !strcmp(param->lf_up, "STRIP");
- add_cr = !strcmp(param->lf_up, "ADD CR");
- expand = !strcmp(param->expand, "YES");
- lecho = !strcmp(param->lecho, "YES");
- pace = !strcmp(param->pace, "YES");
-
- last = 0;
- while ((i = fgetc(fp)) != EOF) {
- /* any keyboard activity? */
- switch (j = getchar()) {
- case -1: /* no key was pressed */
- break;
- case ESC: /* <ESC> key for abort */
- fclose(fp);
- sleep(2);
- ioctl(fd, TCSBRK, 1);
- return;
- default: /* send the char */
- c = j & 0xff;
- putc_line(c);
- if (c == '\r' && cr_lf)
- putc_line('\n');
- break;
- }
- c = i & 0xff;
- /* expand blank lines */
- if (expand && last == '\n' && c == '\n')
- putc_line(' ');
- last = c;
-
- /* CR translations */
- if (c == '\r' && strip_cr)
- continue;
- if (c == '\r' && add_lf) {
- putc_line(c);
- putc_line('\n');
- continue;
- }
- /* LF translations */
- if (c == '\n' && strip_lf)
- continue;
- if (c == '\n' && add_cr) {
- putc_line('\r');
- putc_line(c);
- continue;
- }
- putc_line(c);
- /*
- * There's really no mechanism for delaying characters
- * going to the output, so we fake it by waiting for
- * each character to clear the I/O buffer.
- */
- if (pace)
- ioctl(fd, TCSBRK, 1);
- if (lecho) {
- putchar((char) c);
- fflush(stdout);
- }
- }
- fclose(fp);
- sleep(2);
- ioctl(fd, TCSBRK, 1);
- return;
- }
-
- /*
- * Receive a file. The timer is used to end the transfer. This is not
- * that much different from the data logging option. The use of bgetc_line()
- * and non-blocking input makes it seem like full duplex, but it's not.
- * Be aware that while the timer is active the keyboard is deaf. Input is
- * NOT loaded into the virtual screen!!
- */
-
- static void
- rcv_ascii(file, cr_lf)
- char *file;
- int cr_lf;
- {
- FILE *fp;
- int i, strip_cr, strip_lf, add_cr, add_lf, got_first;
- unsigned int delay;
- char c;
- /* permission already checked */
- if (!(fp = fopen(file, "w")))
- return;
- /* ASCII transfer options */
- strip_cr = !strcmp(param->cr_dn, "STRIP");
- add_lf = !strcmp(param->cr_dn, "ADD LF");
- strip_lf = !strcmp(param->lf_dn, "STRIP");
- add_cr = !strcmp(param->lf_dn, "ADD CR");
-
- got_first = 0;
- delay = 1;
- while (1) {
- /* keyboard activity */
- switch (i = getchar()) {
- case -1: /* no key was pressed */
- break;
- case ESC: /* <ESC> key */
- fclose(fp);
- return;
- default: /* send it */
- c = i & 0xff;
- putc_line((unsigned char) c);
- if (c == '\r' && cr_lf)
- putc_line('\n');
- break;
- }
- /* read a character */
- if ((i = bgetc_line(delay)) == -1) {
- /*
- * The transfer timeout is not activated until the
- * first character is received. Until then, it polls
- * the line for one second and loops backs for
- * keyboard input.
- */
- if (got_first) {
- fclose(fp);
- return;
- }
- continue;
- }
- got_first = 1;
- delay = param->timer;
- c = i & 0xff;
- /* display it on the screen */
- putchar(c);
- fflush(stdout);
- /* CR translations */
- if (c == '\r' && strip_cr)
- continue;
- if (c == '\r' && add_lf) {
- fputc(c, fp);
- fputc('\n', fp);
- continue;
- }
- /* LF translations */
- if (c == '\n' && strip_lf)
- continue;
- if (c == '\n' && add_cr) {
- fputc('\r', fp);
- fputc(c, fp);
- continue;
- }
- fputc(c, fp);
- }
- }
-
- /*
- * Get a character from the line (using buffered I/O) with a specified
- * time-out period in seconds. If the function times-out, it returns a -1.
- */
-
- static int bl_flag;
-
- static int
- bgetc_line(sec)
- unsigned int sec;
- {
- int bl_force();
- char c;
- unsigned int alarm();
-
- signal(SIGALRM, bl_force);
- bl_flag = 0;
-
- alarm(sec);
- if ((int) (c = buf_read()) < 0) {
- alarm(0);
- return(-1);
- }
- if (bl_flag)
- return(-1);
- alarm(0);
- return(c & 0xff);
- }
- /*ARGSUSED*/
- static int
- bl_force(dummy)
- int dummy;
- {
- bl_flag = 1;
- }
-
- /*
- * Do a single character buffered read from the serial port.
- */
-
- static int
- buf_read()
- {
- extern int fd;
- static char buf[CLIST];
- static char *bufp = buf;
- static int n = 0;
-
- if (n <= 0) {
- if ((n = read(fd, buf, CLIST)) <= 0)
- return(-1);
- bufp = buf;
- }
- while (--n >= 0)
- return(*bufp++ & 0xff);
- return(-1);
- }
-