Example #1
0
void
loop(void)
{
	enum {
		ST_COMMAND,
		ST_TRANSPARENT
	} state;
	int dtr_up;
	fd_set rdset, wrset;
	int newbaud, newflow, newparity, newbits;
	char *newflow_str, *newparity_str;
	char fname[128];
	int r, n;
	unsigned char c;


	tty_q.len = 0;
	state = ST_TRANSPARENT;
	dtr_up = 0;

	for (;;) {
		FD_ZERO(&rdset);
		FD_ZERO(&wrset);
		FD_SET(STI, &rdset);
		FD_SET(tty_fd, &rdset);
		if ( tty_q.len ) FD_SET(tty_fd, &wrset);

		if (select(FD_SETSIZE, &rdset, &wrset, NULL, NULL) < 0)
			fatal("select failed: %d : %s", errno, strerror(errno));

		if ( FD_ISSET(STI, &rdset) ) {

			/* read from terminal */

			do {
				n = read(STI, &c, 1);
			} while (n < 0 && errno == EINTR);
			if (n == 0)
				fatal("stdin closed");
			else if (n < 0)
				fatal("read from stdin failed: %s", strerror(errno));

			switch (state) {

			case ST_COMMAND:
				if ( c == opts.escape ) {
					state = ST_TRANSPARENT;
					/* pass the escape character down */
					if (tty_q.len <= TTY_Q_SZ)
						tty_q.buff[tty_q.len++] = c;
					else
						fd_printf(STO, "\x07");
					break;
				}
				state = ST_TRANSPARENT;
				switch (c) {
				case KEY_EXIT:
					return;
				case KEY_QUIT:
					term_set_hupcl(tty_fd, 0);
					term_flush(tty_fd);
					term_apply(tty_fd);
					term_erase(tty_fd);
					return;
				case KEY_STATUS:
					fd_printf(STO, "\r\n");
					fd_printf(STO, "*** baud: %d\r\n", opts.baud);
					fd_printf(STO, "*** flow: %s\r\n", opts.flow_str);
					fd_printf(STO, "*** parity: %s\r\n", opts.parity_str);
					fd_printf(STO, "*** databits: %d\r\n", opts.databits);
					fd_printf(STO, "*** dtr: %s\r\n", dtr_up ? "up" : "down");
					break;
				case KEY_PULSE:
					fd_printf(STO, "\r\n*** pulse DTR ***\r\n");
					if ( term_pulse_dtr(tty_fd) < 0 )
						fd_printf(STO, "*** FAILED\r\n");
					break;
				case KEY_TOGGLE:
					if ( dtr_up )
						r = term_lower_dtr(tty_fd);
					else
						r = term_raise_dtr(tty_fd);
					if ( r >= 0 ) dtr_up = ! dtr_up;
					fd_printf(STO, "\r\n*** DTR: %s ***\r\n", 
							  dtr_up ? "up" : "down");
					break;
				case KEY_BAUD_UP:
					newbaud = baud_up(opts.baud);
					term_set_baudrate(tty_fd, newbaud);
					tty_q.len = 0; term_flush(tty_fd);
					if ( term_apply(tty_fd) >= 0 ) opts.baud = newbaud;
					fd_printf(STO, "\r\n*** baud: %d ***\r\n", opts.baud);
					break;
				case KEY_BAUD_DN:
					newbaud = baud_down(opts.baud);
					term_set_baudrate(tty_fd, newbaud);
					tty_q.len = 0; term_flush(tty_fd);
					if ( term_apply(tty_fd) >= 0 ) opts.baud = newbaud;
					fd_printf(STO, "\r\n*** baud: %d ***\r\n", opts.baud);
					break;
				case KEY_FLOW:
					newflow = flow_next(opts.flow, &newflow_str);
					term_set_flowcntrl(tty_fd, newflow);
					tty_q.len = 0; term_flush(tty_fd);
					if ( term_apply(tty_fd) >= 0 ) {
						opts.flow = newflow;
						opts.flow_str = newflow_str;
					}
					fd_printf(STO, "\r\n*** flow: %s ***\r\n", opts.flow_str);
					break;
				case KEY_PARITY:
					newparity = parity_next(opts.parity, &newparity_str);
					term_set_parity(tty_fd, newparity);
					tty_q.len = 0; term_flush(tty_fd);
					if ( term_apply(tty_fd) >= 0 ) {
						opts.parity = newparity;
						opts.parity_str = newparity_str;
					}
					fd_printf(STO, "\r\n*** parity: %s ***\r\n", 
							  opts.parity_str);
					break;
				case KEY_BITS:
					newbits = bits_next(opts.databits);
					term_set_databits(tty_fd, newbits);
					tty_q.len = 0; term_flush(tty_fd);
					if ( term_apply(tty_fd) >= 0 ) opts.databits = newbits;
					fd_printf(STO, "\r\n*** databits: %d ***\r\n", 
							  opts.databits);
					break;
				case KEY_SEND:
					fd_printf(STO, "\r\n*** file: ");
					r = fd_readline(STI, STO, fname, sizeof(fname));
					fd_printf(STO, "\r\n");
					if ( r < -1 && errno == EINTR ) break;
					if ( r <= -1 )
						fatal("cannot read filename: %s", strerror(errno));
					run_cmd(tty_fd, opts.send_cmd, fname, NULL);
					break;
				case KEY_RECEIVE:
					fd_printf(STO, "*** file: ");
					r = fd_readline(STI, STO, fname, sizeof(fname));
					fd_printf(STO, "\r\n");
					if ( r < -1 && errno == EINTR ) break;
					if ( r <= -1 )
						fatal("cannot read filename: %s", strerror(errno));
					if ( fname[0] )
						run_cmd(tty_fd, opts.send_cmd, fname, NULL);
					else
						run_cmd(tty_fd, opts.receive_cmd, NULL);
					break;
				case KEY_BREAK:
					term_break(tty_fd);
					fd_printf(STO, "\r\n*** break sent ***\r\n");
					break;
				default:
					break;
				}
				break;

			case ST_TRANSPARENT:
				if ( c == opts.escape ) {
					state = ST_COMMAND;
				} else {
					if (tty_q.len <= TTY_Q_SZ)
						tty_q.buff[tty_q.len++] = c;
					else
						fd_printf(STO, "\x07");
				}
				break;

			default:
				assert(0);
				break;
			}
		}

		if ( FD_ISSET(tty_fd, &rdset) ) {

			/* read from port */

			do {
				n = read(tty_fd, &c, 1);
			} while (n < 0 && errno == EINTR);
			if (n == 0)
				fatal("term closed");
			else if ( n < 0 )
				fatal("read from term failed: %s", strerror(errno));
			
			do {
				n = write(STO, &c, 1);
			} while ( errno == EAGAIN 
					  || errno == EWOULDBLOCK
					  || errno == EINTR );
			if ( n <= 0 )
				fatal("write to stdout failed: %s", strerror(errno));
		}

		if ( FD_ISSET(tty_fd, &wrset) ) {

			/* write to port */

			do {
				n = write(tty_fd, tty_q.buff, tty_q.len);
			} while ( n < 0 && errno == EINTR );
			if ( n <= 0 )
				fatal("write to term failed: %s", strerror(errno));
			memcpy(tty_q.buff, tty_q.buff + n, tty_q.len - n);
			tty_q.len -= n;
		}
	}
}
Example #2
0
/* Process command key. Returns non-zero if command results in picocom
   exit, zero otherwise. */
int
do_command (unsigned char c)
{
	static int dtr_up = 0;
	int newbaud, newflow, newparity, newbits, newstopbits;
	const char *xfr_cmd;
	char *fname;
	int r;

	switch (c) {
	case KEY_EXIT:
		return 1;
	case KEY_QUIT:
		term_set_hupcl(tty_fd, 0);
		term_flush(tty_fd);
		term_apply(tty_fd, 1);
		term_erase(tty_fd);
		return 1;
	case KEY_STATUS:
		show_status(dtr_up);
		break;
	case KEY_HELP:
	case KEY_KEYS:
		show_keys();
		break;
	case KEY_PULSE:
		fd_printf(STO, "\r\n*** pulse DTR ***\r\n");
		if ( term_pulse_dtr(tty_fd) < 0 )
			fd_printf(STO, "*** FAILED\r\n");
		break;
	case KEY_TOGGLE:
		if ( dtr_up )
			r = term_lower_dtr(tty_fd);
		else
			r = term_raise_dtr(tty_fd);
		if ( r >= 0 ) dtr_up = ! dtr_up;
		fd_printf(STO, "\r\n*** DTR: %s ***\r\n", 
				  dtr_up ? "up" : "down");
		break;
	case KEY_BAUD:
	case KEY_BAUD_UP:
	case KEY_BAUD_DN:
		if ( c== KEY_BAUD) {
			newbaud = read_baud();
			if ( newbaud < 0 ) {
				fd_printf(STO, "*** cannot read baudrate ***\r\n");
				break;
			}
			opts.baud = newbaud;
		} else if (c == KEY_BAUD_UP) {
			opts.baud = baud_up(opts.baud);
		} else {
			opts.baud = baud_down(opts.baud);
		}
		term_set_baudrate(tty_fd, opts.baud);
		tty_q.len = 0; term_flush(tty_fd);
		term_apply(tty_fd, 1);
		newbaud = term_get_baudrate(tty_fd, NULL);
		if ( opts.baud != newbaud ) {
			fd_printf(STO, "\r\n*** baud: %d (%d) ***\r\n", 
					  opts.baud, newbaud);
		} else {
			fd_printf(STO, "\r\n*** baud: %d ***\r\n", opts.baud);
		}
		set_tty_write_sz(newbaud);
		break;
	case KEY_FLOW:
		opts.flow = flow_next(opts.flow);
		term_set_flowcntrl(tty_fd, opts.flow);
		tty_q.len = 0; term_flush(tty_fd);
		term_apply(tty_fd, 1);
		newflow = term_get_flowcntrl(tty_fd);
		if ( opts.flow != newflow ) {
			fd_printf(STO, "\r\n*** flow: %s (%s) ***\r\n", 
					  flow_str[opts.flow], flow_str[newflow]);
		} else {
			fd_printf(STO, "\r\n*** flow: %s ***\r\n", 
					  flow_str[opts.flow]);
		}
		break;
	case KEY_PARITY:
		opts.parity = parity_next(opts.parity);
		term_set_parity(tty_fd, opts.parity);
		tty_q.len = 0; term_flush(tty_fd);
		term_apply(tty_fd, 1);
		newparity = term_get_parity(tty_fd);
		if (opts.parity != newparity ) {
			fd_printf(STO, "\r\n*** parity: %s (%s) ***\r\n",
					  parity_str[opts.parity], 
					  parity_str[newparity]);
		} else {
			fd_printf(STO, "\r\n*** parity: %s ***\r\n", 
					  parity_str[opts.parity]);
		}
		break;
	case KEY_BITS:
		opts.databits = bits_next(opts.databits);
		term_set_databits(tty_fd, opts.databits);
		tty_q.len = 0; term_flush(tty_fd);
		term_apply(tty_fd, 1);
		newbits = term_get_databits(tty_fd);
		if (opts.databits != newbits ) {
			fd_printf(STO, "\r\n*** databits: %d (%d) ***\r\n",
					  opts.databits, newbits);
		} else {
			fd_printf(STO, "\r\n*** databits: %d ***\r\n", 
					  opts.databits);
		}
		break;
	case KEY_STOP:
		opts.stopbits = stopbits_next(opts.stopbits);
		term_set_stopbits(tty_fd, opts.stopbits);
		tty_q.len = 0; term_flush(tty_fd);
		term_apply(tty_fd, 1);
		newstopbits = term_get_stopbits(tty_fd);
		if (opts.stopbits != newstopbits ) {
			fd_printf(STO, "\r\n*** stopbits: %d (%d) ***\r\n",
					  opts.stopbits, newstopbits);
		} else {
			fd_printf(STO, "\r\n*** stopbits: %d ***\r\n", 
					  opts.stopbits);
		}
		break;
	case KEY_LECHO:
		opts.lecho = ! opts.lecho;
		fd_printf(STO, "\r\n*** local echo: %s ***\r\n", 
				  opts.lecho ? "yes" : "no");
		break;
	case KEY_SEND:
	case KEY_RECEIVE:
		xfr_cmd = (c == KEY_SEND) ? opts.send_cmd : opts.receive_cmd;
		if ( xfr_cmd[0] == '\0' ) {
			fd_printf(STO, "\r\n*** command disabled ***\r\n");
			break;
		}
		fname = read_filename();
		if (fname == NULL) {
			fd_printf(STO, "*** cannot read filename ***\r\n");
			break;
		}
		run_cmd(tty_fd, xfr_cmd, fname);
		free(fname);
		break;
	case KEY_BREAK:
		term_break(tty_fd);
		fd_printf(STO, "\r\n*** break sent ***\r\n");
		break;
	default:
		break;
	}

	return 0;
}