ftp.nice.ch/pub/next/unix/communication/pcomm.NIHS.bs.tar.gz#/pcomm/Source/x_ascii.c

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.