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).
- */
-
- #include <stdio.h>
- #include <curses.h>
- #include <signal.h>
- #include "config.h"
- #include "misc.h"
- #include "param.h"
-
- #ifdef BSD
- #include <setjmp.h>
- jmp_buf bl_buf;
- #endif /* BSD */
-
- static void send_ascii(), rcv_ascii(), putc_ascii();
- static int bgetc_line(), buf_read();
-
- void
- xfer_ascii(list, up)
- char *list;
- int up;
- {
- int cr_lf;
- char *file, *strtok();
- void line_set(), st_line();
- void ascii_mode(), term_mode();
- unsigned int sleep();
-
- touchwin(stdscr);
- refresh();
- /* only one file from list */
- file = strtok(list, " \t");
-
- cr_lf = !strcmp(param->cr_out, "CR/LF");
- ascii_mode(up);
- /* out of curses mode */
- resetterm();
- term_mode();
- tty_noblock(0, TRUE);
-
- if (up)
- send_ascii(file, cr_lf);
- 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.
- */
- line_set();
- fixterm();
- tty_noblock(0, FALSE);
-
- beep();
- st_line("xfer complete");
-
- sleep(2);
- 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, *uid_fopen();
- int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, local_echo, pace;
- char buf[80], c, last;
- unsigned int sleep();
- void error_win();
- /* permission already checked */
- if (!(fp = uid_fopen(file, "r"))) {
- sprintf(buf, "\"%s\"", file);
- error_win(0, "Can't open file for read", buf);
- 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");
- local_echo = !strcmp(param->local_echo, "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);
- tty_drain(fd);
- return;
- default: /* send the char */
- c = (char) j & 0x7f;
- putc_ascii(c, local_echo);
- if (c == '\r' && cr_lf)
- putc_ascii('\n', local_echo);
- break;
- }
- c = (char) i & 0x7f;
- /* expand blank lines */
- if (expand && last == '\n' && c == '\n')
- putc_ascii(' ', local_echo);
- last = c;
-
- /* CR translations */
- if (c == '\r' && strip_cr)
- continue;
- if (c == '\r' && add_lf) {
- putc_ascii(c, local_echo);
- putc_ascii('\n', local_echo);
- continue;
- }
- /* LF translations */
- if (c == '\n' && strip_lf)
- continue;
- if (c == '\n' && add_cr)
- putc_ascii('\r', local_echo);
-
- putc_ascii(c, local_echo);
- /*
- * 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)
- tty_drain(fd);
- }
- fclose(fp);
- sleep(2);
- tty_drain(fd);
- return;
- }
-
- /* Put a character on the line, echo it too, if required */
-
- static void
- putc_ascii(c, local_echo)
- char c;
- int local_echo;
- {
- extern int fd;
- void vs_putchar();
-
- write(fd, &c, 1);
- if (local_echo) {
- write(1, &c, 1);
- vs_putchar(c);
- }
- 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.
- */
-
- static void
- rcv_ascii(file, cr_lf)
- char *file;
- int cr_lf;
- {
- FILE *fp, *uid_fopen();
- int i, strip_cr, strip_lf, add_cr, add_lf, got_first;
- unsigned int delay;
- char c, buf[80];
- void error_win(), vs_putchar();
- /* permission already checked */
- if (!(fp = uid_fopen(file, "w"))) {
- sprintf(buf, "\"%s\"", file);
- error_win(0, "Can't open file for write", buf);
- 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;
- /* CONSTCOND */
- 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 = (unsigned int) i;
- 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 & 0x7f;
- /* display it on the screen */
- write(1, &c, 1);
- vs_putchar(c);
- /* 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 bl_force();
-
- static int
- bgetc_line(sec)
- unsigned int sec;
- {
- int c;
- unsigned int alarm();
-
- signal(SIGALRM, (SIG_TYPE(*) ()) bl_force);
- bl_flag = 0;
-
- alarm(sec);
-
- #ifdef BSD
- if (setjmp(bl_buf))
- return(-1);
- #endif /* BSD */
-
- if ((c = buf_read()) < 0) {
- alarm(0);
- return(-1);
- }
- if (bl_flag)
- return(-1);
- alarm(0);
- return(c);
- }
-
- /* ARGSUSED */
- static int
- bl_force(dummy)
- int dummy;
- {
- #ifdef BSD
- longjmp(bl_buf, 1);
- #else /* BSD */
- signal(SIGALRM, (SIG_TYPE(*) ()) bl_force);
- bl_flag = 1;
- return(0);
- #endif /* BSD */
- }
-
- /*
- * Do a single character buffered read from the serial port.
- */
-
- static int
- buf_read()
- {
- extern int fd;
- static char buf[CLIST_SIZ];
- static char *bufp = buf;
- static int n = 0;
-
- if (n <= 0) {
- n = read(fd, buf, CLIST_SIZ);
- bufp = buf;
- }
- if (--n >= 0)
- return(*bufp++ & 0xff);
- return(-1);
- }
-