This is x_ascii.c in view mode; [Download] [Up]
/* * 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 */ void xfer_ascii(list, up) char *list; int up; { int cr_lf; char *file, *strtok(); void line_set(), st_line(), suspend(); void load_vs(), ascii_mode(), input_off(), term_mode(); static void send_ascii(), rcv_ascii(); 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) { /* un-suspend the input routine */ suspend(FALSE); send_ascii(file, cr_lf); suspend(TRUE); } else { input_off(); 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); /* * 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; } /* * 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, *my_fopen(); int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, lecho, pace; char buf[80]; unsigned char c, last; unsigned int sleep(); void error_win(); /* permission already checked */ if (!(fp = my_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"); 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); tty_drain(fd); return; default: /* send the char */ c = j; putc_line(c); if (c == '\r' && cr_lf) putc_line('\n'); break; } c = i & 0x7f; /* 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) tty_drain(fd); if (lecho) { putchar((char) c); fflush(stdout); } } fclose(fp); sleep(2); tty_drain(fd); 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, *my_fopen(); int i, strip_cr, strip_lf, add_cr, add_lf, got_first; static int bgetc_line(); unsigned int delay; char c, buf[80]; void error_win(); /* permission already checked */ if (!(fp = my_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; 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; 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 */ 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 c; static int buf_read(), bl_force(); 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; #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); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.