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 <fcntl.h>
- #include <curses.h>
- #include <signal.h>
- #include "param.h"
- #include "status.h"
-
- void
- xfer_ascii(list, up)
- char *list;
- int up;
- {
- int cr_lf;
- char *file, *strtok();
- void send_ascii(), rcv_ascii(), line_set(), status_line();
- unsigned int sleep();
-
- /* only one file from list */
- file = strtok(list, " ");
-
- cr_lf = ascii_mode(up);
- if (up) {
- /* un-suspend the input routine */
- if (status->pid != -1)
- kill(status->pid, SIGINT);
-
- send_ascii(file, cr_lf);
- /* re-suspend the input routine */
- if (status->pid != -1)
- kill(status->pid, SIGINT);
- }
- 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);
- fixterm();
- line_set();
- sleep(1);
-
- status_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. Returns the status of the
- * cr_lf parameter flag.
- */
-
- int
- ascii_mode(up)
- int up;
- {
- int cr_lf;
- struct termio tbuf;
- void input_off();
-
- ioctl(status->fd, TCGETA, &tbuf);
- tbuf.c_oflag = 0;
- /* flow control & 8th bit stripping */
- if (up) {
- tbuf.c_iflag = (ISTRIP|IXON|IXANY);
-
- /* 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(status->fd, TCSETA, &tbuf);
- ioctl(status->fd, TCFLSH, 2);
- /* out of curses mode */
- resetterm();
- cr_lf = raw_mode();
- /* non-blocking mode */
- fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY);
- return(cr_lf);
- }
-
- /*
- * 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.
- */
-
- void
- send_ascii(file, cr_lf)
- char *file;
- int cr_lf;
- {
- FILE *fp;
- int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, last;
- int lecho, pace;
- unsigned int sleep();
- unsigned char c;
- /* 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 27: /* ESC key for abort */
- fclose(fp);
- ioctl(status->fd, TCFLSH, 2);
- return;
- default: /* send the char */
- c = j;
- putc_line(c);
- if (c == 13 && cr_lf)
- putc_line(10);
- break;
- }
- c = i;
- /* expand blank lines */
- if (expand && last == 10 && c == 10)
- putc_line(' ');
- last = c;
-
- /* CR translations */
- if (c == 13 && strip_cr)
- continue;
- if (c == 13 && add_lf) {
- putc_line(c);
- putc_line(10);
- continue;
- }
- /* LF translations */
- if (c == 10 && strip_lf)
- continue;
- if (c == 10 && add_cr) {
- putc_line(13);
- 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(status->fd, TCSBRK, 1);
- if (lecho)
- write(1, (char *) &c, 1);
- }
- sleep(1);
- ioctl(status->fd, TCSBRK, 1);
- fclose(fp);
- 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 getc_line()
- * and non-blocking input makes it seem like full duplex, but it's not.
- * Beware that while the timer is active the keyboard is deaf. Input is
- * NOT loaded into the virtual screen!!
- */
-
- 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;
- unsigned 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 27: /* ESC key */
- fclose(fp);
- return;
- default: /* send it */
- c = i;
- putc_line(c);
- if (c == 13 && cr_lf)
- putc_line(10);
- break;
- }
- /* read a character */
- if ((i = getc_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 & 0177;
- /* display it on the screen */
- write(1, (char *) &c, 1);
- /* CR translations */
- if (c == 13 && strip_cr)
- continue;
- if (c == 13 && add_lf) {
- fputc((char) c, fp);
- fputc(10, fp);
- continue;
- }
- /* LF translations */
- if (c == 10 && strip_lf)
- continue;
- if (c == 10 && add_cr) {
- fputc(13, fp);
- fputc((char) c, fp);
- continue;
- }
- fputc((char) c, fp);
- }
- }
-