示例#1
0
void
do_command(char c)
{
	switch (c) {
	case '.':
	case '\004': /* ^D */
		event_loopexit(NULL);
		break;
	case '\032': /* ^Z */
		restore_termios();
		kill(getpid(), SIGTSTP);
		set_termios();
		break;
	case 'C':
		connect_command();
		break;
	case 'D':
		ioctl(line_fd, TIOCCDTR, NULL);
		sleep(1);
		ioctl(line_fd, TIOCSDTR, NULL);
		break;
	case 'R':
		start_record();
		break;
	case 'S':
		set_speed();
		break;
	case 'X':
		send_xmodem();
		break;
	case '$':
		pipe_command();
		break;
	case '>':
		send_file();
		break;
	case '#':
		ioctl(line_fd, TIOCSBRK, NULL);
		sleep(1);
		ioctl(line_fd, TIOCCBRK, NULL);
		break;
	case '~':
		bufferevent_write(line_ev, "~", 1);
		break;
	case '?':
		printf("\r\n"
		    "~#      send break\r\n"
		    "~$      pipe local command to remote host\r\n"
		    "~>      send file to remote host\r\n"
		    "~C      connect program to remote host\r\n"
		    "~D      de-assert DTR line briefly\r\n"
		    "~R      start recording to file\r\n"
		    "~S      set speed\r\n"
		    "~X      send file with XMODEM\r\n"
		    "~?      get this summary\r\n"
		);
		break;
	}
}
示例#2
0
文件: lcd.c 项目: ohdarling/routerlcd
void lcd_connect() {
	if (serial_fd == 0) {
		serial_fd = open_port();
		if (serial_fd > 0) {
		    struct termios options;
		    set_termios(&options, B9600);
		    tcsetattr(serial_fd, TCSANOW, &options);
			usleep(100);
		}
	}
}
示例#3
0
int 
profibus_serial_open(const char *device,  unsigned int rate, GError **err)
{
  int fd = open(device, O_RDWR);
  if (fd < 0) {
    g_set_error(err, G_FILE_ERROR, g_file_error_from_errno(errno),
		"open failed: %s", strerror(errno));
    return -1;
  }
  if (!set_termios(fd, rate, err)) {
    close(fd);
    return -1;
  }
  return fd;
}
示例#4
0
void
connect_command(void)
{
	const char	*cmd;
	pid_t		 pid;

	/*
	 * Fork a program with:
	 *  0 <-> remote tty in
	 *  1 <-> remote tty out
	 *  2 <-> local tty stderr
	 */

	cmd = get_input("Local command?");
	if (cmd == NULL || *cmd == '\0')
		return;

	restore_termios();

	switch (pid = fork()) {
	case -1:
		cu_err(1, "fork");
	case 0:
		if (signal(SIGINT, SIG_DFL) == SIG_ERR)
			_exit(1);
		if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
			_exit(1);

		/* attach stdout and stdin to line */
		if (dup2(line_fd, STDOUT_FILENO) == -1)
			_exit(1);
		if (dup2(line_fd, STDIN_FILENO) == -1)
			_exit(1);

		if (closefrom(STDERR_FILENO + 1) != 0)
			_exit(1);

		execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL);
		_exit(1);
	default:
		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
			/* nothing */;
		break;
	}

	set_termios();
}
示例#5
0
void
pipe_command(void)
{
	const char	*cmd;
	pid_t		 pid;
	int		 fd;

	cmd = get_input("Local command?");
	if (cmd == NULL || *cmd == '\0')
		return;

	restore_termios();

	switch (pid = fork()) {
	case -1:
		cu_err(1, "fork");
	case 0:
		fd = open(_PATH_DEVNULL, O_RDWR);
		if (fd < 0 || dup2(fd, STDIN_FILENO) == -1)
			_exit(1);
		close(fd);

		if (signal(SIGINT, SIG_DFL) == SIG_ERR)
			_exit(1);
		if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
			_exit(1);

		/* attach stdout to line */
		if (dup2(line_fd, STDOUT_FILENO) == -1)
			_exit(1);

		if (closefrom(STDERR_FILENO + 1) != 0)
			_exit(1);

		execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL);
		_exit(1);
	default:
		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
			/* nothing */;
		break;
	}

	set_termios();
}
示例#6
0
int
open_pseudo_terminal(GError **err)
{
  int fd = posix_openpt(O_RDWR);
  if (fd < 0) {
    g_set_error(err, G_FILE_ERROR, g_file_error_from_errno(errno),
		"posix_openpt failed: %s", strerror(errno));
    return -1;
  }
  if (!set_termios(fd, 115200, err)) {
    close(fd);
    return -1;
  }
  if (unlockpt(fd) < 0) {
    g_set_error(err, G_FILE_ERROR, g_file_error_from_errno(errno),
		"unlockpt failed: %s", strerror(errno));
    return -1;
  }
  g_message("Use %s as tty", ptsname(fd));
  return fd;
}
示例#7
0
int tty_ioctl(struct inode * inode, struct file * file,
	unsigned int cmd, unsigned int arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	int pgrp;
	int dev;

	if (MAJOR(file->f_rdev) != 4) {
		printk("tty_ioctl: tty pseudo-major != 4\n");
		return -EINVAL;
	}
	dev = MINOR(file->f_rdev);
	tty = TTY_TABLE(dev);
	if (!tty)
		return -EINVAL;

	if (IS_A_PTY(dev))
		other_tty = tty_table[PTY_OTHER(dev)];
	else
		other_tty = NULL;
		
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush_input(tty);
		/* fallthrough */
		case TCSETSW:
			wait_until_sent(tty);
		/* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg, dev);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush_input(tty);
		/* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg, dev);
		case TCXONC:
			switch (arg) {
			case TCOOFF:
				tty->stopped = 1;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCOON:
				tty->stopped = 0;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCIOFF:
				if (STOP_CHAR(tty))
					put_tty_queue(STOP_CHAR(tty),
						      &tty->write_q);
				return 0;
			case TCION:
				if (START_CHAR(tty))
					put_tty_queue(START_CHAR(tty),
						      &tty->write_q);
				return 0;
			}
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0)
				flush_input(tty);
			else if (arg==1)
				flush_output(tty);
			else if (arg==2) {
				flush_input(tty);
				flush_output(tty);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			if ((current->tty < 0) ||
			    (current->tty != dev) ||
			    (tty->session != current->session))
				return -ENOTTY;
			pgrp=get_fs_long((unsigned long *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			tty->pgrp = pgrp;			
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(&tty->write_q),
				    (unsigned long *) arg);
			return 0;
		case TIOCINQ:
			verify_area((void *) arg,4);
			if (L_CANON(tty) && !tty->secondary.data)
				put_fs_long(0, (unsigned long *) arg);
			else
				put_fs_long(CHARS(&tty->secondary),
					(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return get_window_size(tty,(struct winsize *) arg);
		case TIOCSWINSZ:
			if (IS_A_PTY_MASTER(dev))
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
				default: 
					return -EINVAL;
			}
		case TIOCCONS:
			if (!IS_A_PTY(dev))
				return -EINVAL;
			if (redirect)
				return -EBUSY;
			if (!suser())
				return -EPERM;
			if (IS_A_PTY_MASTER(dev))
				redirect = other_tty;
			else
				redirect = tty;
			return 0;
		case FIONBIO:
			if (arg)
				file->f_flags |= O_NONBLOCK;
			else
				file->f_flags &= ~O_NONBLOCK;
			return 0;
		case TIOCNOTTY:
			if (MINOR(file->f_rdev) != current->tty)
				return -EINVAL;
			current->tty = -1;
			if (current->leader) {
				if (tty->pgrp > 0)
					kill_pg(tty->pgrp, SIGHUP, 0);
				tty->pgrp = -1;
				tty->session = 0;
			}
			return 0;

	       case TIOCPKT:
			{
			   int on;
			   if (!IS_A_PTY_MASTER(dev))
			     return (-EINVAL);
			   verify_area ((unsigned long *)arg, sizeof (int));
			   on=get_fs_long ((unsigned long *)arg);
			   if (on )
			     tty->packet = 1;
			   else
			     tty->packet = 0;
			   return (0);
			}

		default:
			if (tty->ioctl)
				return (tty->ioctl)(tty, file, cmd, arg);
			else
				return -EINVAL;
	}
}
示例#8
0
int tty_ioctl(int dev, int cmd, int arg)
{
	struct tty_struct * tty;
	if (MAJOR(dev) == 5) {
		dev=current->tty;
		if (dev<0)
			panic("tty_ioctl: dev<0");
	} else
		dev=MINOR(dev);
	tty = dev + tty_table;
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush(&tty->read_q); /* fallthrough */
		case TCSETSW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush(&tty->read_q); /* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg);
		case TCSBRK:
			if (!arg) {
				wait_until_sent(tty);
				send_break(tty);
			}
			return 0;
		case TCXONC:
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0)
				flush(&tty->read_q);
			else if (arg==1)
				flush(&tty->write_q);
			else if (arg==2) {
				flush(&tty->read_q);
				flush(&tty->write_q);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			tty->pgrp=get_fs_long((unsigned long *) arg);
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return -EINVAL; /* not implemented */
		case TIOCSWINSZ:
			return -EINVAL; /* not implemented */
		case TIOCMGET:
			return -EINVAL; /* not implemented */
		case TIOCMBIS:
			return -EINVAL; /* not implemented */
		case TIOCMBIC:
			return -EINVAL; /* not implemented */
		case TIOCMSET:
			return -EINVAL; /* not implemented */
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		default:
			return -EINVAL;
	}
}
示例#9
0
static uint32
serial_control(IRP * irp)
{
	int flush_mask, purge_mask;
	uint32 result, modemstate;
	uint8 immediate;
	int size = 0, ret = RD_STATUS_SUCCESS;
	SERIAL_DEVICE_INFO *info = (SERIAL_DEVICE_INFO *) irp->dev->info;
	char *inbuf = irp->inputBuffer;
	char *outbuf = NULL;

	/* the server commands, we obbey */
	switch (irp->ioControlCode)
	{
		case IOCTL_SERIAL_SET_BAUD_RATE:
			info->baud_rate = GET_UINT32(inbuf, 0);
			set_termios(info);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BAUD_RATE %d", info->baud_rate));
			break;
		case IOCTL_SERIAL_GET_BAUD_RATE:
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, info->baud_rate);
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_BAUD_RATE %d", info->baud_rate));
			break;
		case IOCTL_SERIAL_SET_QUEUE_SIZE:
			info->queue_in_size = GET_UINT32(inbuf, 0);
			info->queue_out_size = GET_UINT32(inbuf, 4);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d", info->queue_in_size, info->queue_out_size));
			break;
		case IOCTL_SERIAL_SET_LINE_CONTROL:
			info->stop_bits = GET_UINT8(inbuf, 0);
			info->parity = GET_UINT8(inbuf, 1);
			info->word_length = GET_UINT8(inbuf, 2);
			set_termios(info);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d",
					info->stop_bits, info->parity, info->word_length));
			break;
		case IOCTL_SERIAL_GET_LINE_CONTROL:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_LINE_CONTROL"));
			size = 3;
			outbuf = malloc(size);
			SET_UINT8(outbuf, 0, info->stop_bits);
			SET_UINT8(outbuf, 1, info->parity);
			SET_UINT8(outbuf, 2, info->word_length);
			break;
		case IOCTL_SERIAL_IMMEDIATE_CHAR:
			LLOGLN(10, ("serial_ioctl -> SERIAL_IMMEDIATE_CHAR"));
			immediate = GET_UINT8(inbuf, 0);
			serial_write_data(irp, &immediate, 1);
			break;
		case IOCTL_SERIAL_CONFIG_SIZE:
			LLOGLN(10, ("serial_ioctl -> SERIAL_CONFIG_SIZE"));
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, 0);
			break;
		case IOCTL_SERIAL_GET_CHARS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_CHARS"));
			size = 6;
			outbuf = malloc(size);
			memcpy(outbuf, info->chars, size);
			break;
		case IOCTL_SERIAL_SET_CHARS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_CHARS"));
			memcpy(info->chars, inbuf, 6);
			set_termios(info);
			break;
		case IOCTL_SERIAL_GET_HANDFLOW:
			LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_GET_HANDFLOW"));
			size = 16;
			outbuf = malloc(size);
			get_termios(info);
			SET_UINT32(outbuf, 0, info->control);
			SET_UINT32(outbuf, 4, info->xonoff);
			SET_UINT32(outbuf, 8, info->onlimit);
			SET_UINT32(outbuf, 12, info->offlimit);
			break;
		case IOCTL_SERIAL_SET_HANDFLOW:
			info->control = GET_UINT32(inbuf, 0);
			info->xonoff = GET_UINT32(inbuf, 4);
			info->onlimit = GET_UINT32(inbuf, 8);
			info->offlimit = GET_UINT32(inbuf, 12);
			LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_SET_HANDFLOW %x %x %x %x",
				      info->control, info->xonoff, info->onlimit, info->onlimit));
			set_termios(info);
			break;
		case IOCTL_SERIAL_SET_TIMEOUTS:
			info->read_interval_timeout = GET_UINT32(inbuf, 0);
			info->read_total_timeout_multiplier = GET_UINT32(inbuf, 4);
			info->read_total_timeout_constant = GET_UINT32(inbuf, 8);
			info->write_total_timeout_multiplier = GET_UINT32(inbuf, 12);
			info->write_total_timeout_constant = GET_UINT32(inbuf, 16);

			/* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section
				http://msdn.microsoft.com/en-us/library/ms885171.aspx */
			if (info->read_interval_timeout == SERIAL_TIMEOUT_MAX)
			{
				info->read_interval_timeout = 0;
				info->read_total_timeout_multiplier = 0;
			}

			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d",
				      info->read_interval_timeout,
				      info->read_total_timeout_multiplier,
				      info->read_total_timeout_constant));
			break;
		case IOCTL_SERIAL_GET_TIMEOUTS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d",
				      info->read_interval_timeout,
				      info->read_total_timeout_multiplier,
				      info->read_total_timeout_constant));
			size = 20;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, info->read_interval_timeout);
			SET_UINT32(outbuf, 4, info->read_total_timeout_multiplier);
			SET_UINT32(outbuf, 8, info->read_total_timeout_constant);
			SET_UINT32(outbuf, 12, info->write_total_timeout_multiplier);
			SET_UINT32(outbuf, 16, info->write_total_timeout_constant);
			break;
		case IOCTL_SERIAL_GET_WAIT_MASK:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_WAIT_MASK %X", info->wait_mask));
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, info->wait_mask);
			break;
		case IOCTL_SERIAL_SET_WAIT_MASK:
			info->wait_mask = GET_UINT32(inbuf, 0);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_WAIT_MASK %X", info->wait_mask));
			break;
		case IOCTL_SERIAL_SET_DTR:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_DTR"));
			ioctl(info->file, TIOCMGET, &result);
			result |= TIOCM_DTR;
			ioctl(info->file, TIOCMSET, &result);
			info->dtr = 1;
			break;
		case IOCTL_SERIAL_CLR_DTR:
			LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_DTR"));
			ioctl(info->file, TIOCMGET, &result);
			result &= ~TIOCM_DTR;
			ioctl(info->file, TIOCMSET, &result);
			info->dtr = 0;
			break;
		case IOCTL_SERIAL_SET_RTS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_RTS"));
			ioctl(info->file, TIOCMGET, &result);
			result |= TIOCM_RTS;
			ioctl(info->file, TIOCMSET, &result);
			info->rts = 1;
			break;
		case IOCTL_SERIAL_CLR_RTS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_RTS"));
			ioctl(info->file, TIOCMGET, &result);
			result &= ~TIOCM_RTS;
			ioctl(info->file, TIOCMSET, &result);
			info->rts = 0;
			break;
		case IOCTL_SERIAL_GET_MODEMSTATUS:
			modemstate = 0;
#ifdef TIOCMGET
			ioctl(info->file, TIOCMGET, &result);
			if (result & TIOCM_CTS)
				modemstate |= SERIAL_MS_CTS;
			if (result & TIOCM_DSR)
				modemstate |= SERIAL_MS_DSR;
			if (result & TIOCM_RNG)
				modemstate |= SERIAL_MS_RNG;
			if (result & TIOCM_CAR)
				modemstate |= SERIAL_MS_CAR;
			if (result & TIOCM_DTR)
				modemstate |= SERIAL_MS_DTR;
			if (result & TIOCM_RTS)
				modemstate |= SERIAL_MS_RTS;
#endif
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X", modemstate));
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, modemstate);
			break;
		case IOCTL_SERIAL_GET_COMMSTATUS:
			size = 18;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, 0);	/* Errors */
			SET_UINT32(outbuf, 4, 0);	/* Hold reasons */

			result = 0;
#ifdef TIOCINQ
			ioctl(info->file, TIOCINQ, &result);
#endif
			SET_UINT32(outbuf, 8, result);	/* Amount in in queue */
			if (result)
				LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d", result));

			result = 0;
#ifdef TIOCOUTQ
			ioctl(info->file, TIOCOUTQ, &result);
#endif
			SET_UINT32(outbuf, 12, result);	/* Amount in out queue */
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d", result));

			SET_UINT8(outbuf, 16, 0);	/* EofReceived */
			SET_UINT8(outbuf, 17, 0);	/* WaitForImmediate */
			break;
		case IOCTL_SERIAL_PURGE:
			purge_mask = GET_UINT32(inbuf, 0);
			LLOGLN(10, ("serial_ioctl -> SERIAL_PURGE purge_mask %X", purge_mask));
			flush_mask = 0;
			if (purge_mask & SERIAL_PURGE_TXCLEAR)
				flush_mask |= TCOFLUSH;
			if (purge_mask & SERIAL_PURGE_RXCLEAR)
				flush_mask |= TCIFLUSH;
			if (flush_mask != 0)
				tcflush(info->file, flush_mask);

			if (purge_mask & SERIAL_PURGE_TXABORT)
				irp->abortIO |= RDPDR_ABORT_IO_WRITE;
			if(purge_mask & SERIAL_PURGE_RXABORT)
				irp->abortIO |= RDPDR_ABORT_IO_READ;
			break;
		case IOCTL_SERIAL_WAIT_ON_MASK:
			LLOGLN(10, ("serial_ioctl -> SERIAL_WAIT_ON_MASK %X", info->wait_mask));
			info->event_pending = 1;
			if (serial_get_event(irp, &result))
			{
				size = 4;
				outbuf = malloc(size);
				LLOGLN(10, ("WAIT end  event = %x", result));
				SET_UINT32(outbuf, 0, result);
				break;
			}
			irp->outputBufferLength = 4;
			ret = RD_STATUS_PENDING;
			break;
		case IOCTL_SERIAL_SET_BREAK_ON:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_ON"));
			tcsendbreak(info->file, 0);
			break;
		case IOCTL_SERIAL_RESET_DEVICE:
			LLOGLN(10, ("serial_ioctl -> SERIAL_RESET_DEVICE"));
			break;
		case IOCTL_SERIAL_SET_BREAK_OFF:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_OFF"));
			break;
		case IOCTL_SERIAL_SET_XOFF:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XOFF"));
			break;
		case IOCTL_SERIAL_SET_XON:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XON"));
			tcflow(info->file, TCION);
			break;
		default:
			LLOGLN(10, ("NOT FOUND IoControlCode SERIAL IOCTL %d", irp->ioControlCode));
			return RD_STATUS_INVALID_PARAMETER;
	}

	irp->outputBuffer = outbuf;
	irp->outputBufferLength = size;

	return ret;
}
示例#10
0
int tty_ioctl(struct inode * inode, struct file * file,
	unsigned int cmd, unsigned long arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	struct tty_struct * termios_tty;
	pid_t pgrp;
	int dev;
	int termios_dev;
	int retval;

	if (MAJOR(file->f_rdev) != TTY_MAJOR) {
		printk("tty_ioctl: tty pseudo-major != TTY_MAJOR\n");
		return -EINVAL;
	}
	dev = MINOR(file->f_rdev);
	tty = TTY_TABLE(dev);
	if (!tty)
		return -EINVAL;
	if (IS_A_PTY(dev))
		other_tty = tty_table[PTY_OTHER(dev)];
	else
		other_tty = NULL;
	if (IS_A_PTY_MASTER(dev)) {
		termios_tty = other_tty;
		termios_dev = PTY_OTHER(dev);
	} else {
		termios_tty = tty;
		termios_dev = dev;
	}
	switch (cmd) {
		case TCGETS:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (struct termios));
			if (retval)
				return retval;
			memcpy_tofs((struct termios *) arg,
				    termios_tty->termios,
				    sizeof (struct termios));
			return 0;
		case TCSETSF:
		case TCSETSW:
		case TCSETS:
			retval = check_change(termios_tty, termios_dev);
			if (retval)
				return retval;
			if (cmd == TCSETSF || cmd == TCSETSW) {
				if (cmd == TCSETSF)
					flush_input(termios_tty);
				wait_until_sent(termios_tty, 0);
			}
			return set_termios(termios_tty, (struct termios *) arg,
					   termios_dev);
		case TCGETA:
			return get_termio(termios_tty,(struct termio *) arg);
		case TCSETAF:
		case TCSETAW:
		case TCSETA:
			retval = check_change(termios_tty, termios_dev);
			if (retval)
				return retval;
			if (cmd == TCSETAF || cmd == TCSETAW) {
				if (cmd == TCSETAF)
					flush_input(termios_tty);
				wait_until_sent(termios_tty, 0);
			}
			return set_termio(termios_tty, (struct termio *) arg,
					  termios_dev);
		case TCXONC:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			switch (arg) {
			case TCOOFF:
				stop_tty(tty);
				break;
			case TCOON:
				start_tty(tty);
				break;
			case TCIOFF:
				if (STOP_CHAR(tty) != __DISABLED_CHAR)
					put_tty_queue(STOP_CHAR(tty),
						      &tty->write_q);
				break;
			case TCION:
				if (START_CHAR(tty) != __DISABLED_CHAR)
					put_tty_queue(START_CHAR(tty),
						      &tty->write_q);
				break;
			default:
				return -EINVAL;
			}
			return 0;
		case TCFLSH:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			switch (arg) {
			case TCIFLUSH:
				flush_input(tty);
				break;
			case TCIOFLUSH:
				flush_input(tty);
				/* fall through */
			case TCOFLUSH:
				flush_output(tty);
				break;
			default:
				return -EINVAL;
			}
			return 0;
		case TIOCEXCL:
			set_bit(TTY_EXCLUSIVE, &tty->flags);
			return 0;
		case TIOCNXCL:
			clear_bit(TTY_EXCLUSIVE, &tty->flags);
			return 0;
		case TIOCSCTTY:
			if (current->leader &&
			    (current->session == tty->session))
				return 0;
			/*
			 * The process must be a session leader and
			 * not have a controlling tty already.
			 */
			if (!current->leader || (current->tty >= 0))
				return -EPERM;
			if (tty->session > 0) {
				/*
				 * This tty is already the controlling
				 * tty for another session group!
				 */
				if ((arg == 1) && suser()) {
					/*
					 * Steal it away
					 */
					struct task_struct *p;

					for_each_task(p)
						if (p->tty == dev)
							p->tty = -1;
				} else
					return -EPERM;
			}
			current->tty = dev;
			tty->session = current->session;
			tty->pgrp = current->pgrp;
			return 0;
		case TIOCGPGRP:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (pid_t));
			if (retval)
				return retval;
			if (current->tty != termios_dev)
				return -ENOTTY;
			put_fs_long(termios_tty->pgrp, (pid_t *) arg);
			return 0;
		case TIOCSPGRP:
			retval = check_change(termios_tty, termios_dev);
			if (retval)
				return retval;
			if ((current->tty < 0) ||
			    (current->tty != termios_dev) ||
			    (termios_tty->session != current->session))
				return -ENOTTY;
			pgrp = get_fs_long((pid_t *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			termios_tty->pgrp = pgrp;
			return 0;
		case TIOCOUTQ:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			put_fs_long(CHARS(&tty->write_q),
				    (unsigned long *) arg);
			return 0;
		case TIOCINQ:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			if (L_ICANON(tty))
				put_fs_long(inq_canon(tty),
					(unsigned long *) arg);
			else
				put_fs_long(CHARS(&tty->secondary),
					(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			if ((current->tty != dev) && !suser())
				return -EPERM;
			retval = verify_area(VERIFY_READ, (void *) arg, 1);
			if (retval)
				return retval;
			put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
			TTY_READ_FLUSH(tty);
			return 0;
		case TIOCGWINSZ:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (struct winsize));
			if (retval)
				return retval;
			memcpy_tofs((struct winsize *) arg, &tty->winsize,
				    sizeof (struct winsize));
			return 0;
		case TIOCSWINSZ:
			if (IS_A_PTY_MASTER(dev))
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
#ifdef CONFIG_SELECTION
				case 2:
					return set_selection(arg);
				case 3:
					return paste_selection(tty);
				case 4:
					unblank_screen();
					return 0;
#endif /* CONFIG_SELECTION */
				default: 
					return -EINVAL;
			}
		case TIOCCONS:
			if (IS_A_CONSOLE(dev)) {
				if (!suser())
					return -EPERM;
				redirect = NULL;
				return 0;
			}
			if (redirect)
				return -EBUSY;
			if (!suser())
				return -EPERM;
			if (IS_A_PTY_MASTER(dev))
				redirect = other_tty;
			else if (IS_A_PTY_SLAVE(dev))
				redirect = tty;
			else
				return -ENOTTY;
			return 0;
		case FIONBIO:
			arg = get_fs_long((unsigned long *) arg);
			if (arg)
				file->f_flags |= O_NONBLOCK;
			else
				file->f_flags &= ~O_NONBLOCK;
			return 0;
		case TIOCNOTTY:
			if (current->tty != dev)
				return -ENOTTY;
			if (current->leader)
				disassociate_ctty(0);
			current->tty = -1;
			return 0;
		case TIOCGETD:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			put_fs_long(tty->disc, (unsigned long *) arg);
			return 0;
		case TIOCSETD:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			arg = get_fs_long((unsigned long *) arg);
			return tty_set_ldisc(tty, arg);
		case TIOCGLCKTRMIOS:
			arg = get_fs_long((unsigned long *) arg);
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (struct termios));
			if (retval)
				return retval;
			memcpy_tofs((struct termios *) arg,
				    &termios_locked[termios_dev],
				    sizeof (struct termios));
			return 0;
		case TIOCSLCKTRMIOS:
			if (!suser())
				return -EPERM;
			arg = get_fs_long((unsigned long *) arg);
			memcpy_fromfs(&termios_locked[termios_dev],
				      (struct termios *) arg,
				      sizeof (struct termios));
			return 0;
		case TIOCPKT:
			if (!IS_A_PTY_MASTER(dev))
				return -ENOTTY;
			retval = verify_area(VERIFY_READ, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			if (get_fs_long(arg)) {
				if (!tty->packet) {
					tty->packet = 1;
					tty->link->ctrl_status = 0;
				}
			} else
				tty->packet = 0;
			return 0;
		case TCSBRK: case TCSBRKP:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			wait_until_sent(tty, 0);
			if (!tty->ioctl)
				return 0;
			tty->ioctl(tty, file, cmd, arg);
			return 0;
		default:
			if (tty->ioctl) {
				retval = (tty->ioctl)(tty, file, cmd, arg);
				if (retval != -EINVAL)
					return retval;
			}
			if (ldiscs[tty->disc].ioctl) {
				retval = (ldiscs[tty->disc].ioctl)
					(tty, file, cmd, arg);
				return retval;
			}
			return -EINVAL;
	}
示例#11
0
int n_tty_ioctl(struct tty_struct * tty, struct file * file,
		       unsigned int cmd, unsigned long arg)
{
	struct tty_struct * real_tty;
	int retval;

	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
	    tty->driver->subtype == PTY_TYPE_MASTER)
		real_tty = tty->link;
	else
		real_tty = tty;

	switch (cmd) {
#ifdef TIOCGETP
		case TIOCGETP:
			return get_sgttyb(real_tty, (struct sgttyb *) arg);
		case TIOCSETP:
		case TIOCSETN:
			return set_sgttyb(real_tty, (struct sgttyb *) arg);
#endif
#ifdef TIOCGETC
		case TIOCGETC:
			return get_tchars(real_tty, (struct tchars *) arg);
		case TIOCSETC:
			return set_tchars(real_tty, (struct tchars *) arg);
#endif
#ifdef TIOCGLTC
		case TIOCGLTC:
			return get_ltchars(real_tty, (struct ltchars *) arg);
		case TIOCSLTC:
			return set_ltchars(real_tty, (struct ltchars *) arg);
#endif
		case TCGETS:
			if (kernel_termios_to_user_termios((struct termios *)arg, real_tty->termios))
				return -EFAULT;
			return 0;
		case TCSETSF:
			return set_termios(real_tty, arg,  TERMIOS_FLUSH | TERMIOS_WAIT);
		case TCSETSW:
			return set_termios(real_tty, arg, TERMIOS_WAIT);
		case TCSETS:
			return set_termios(real_tty, arg, 0);
		case TCGETA:
			return get_termio(real_tty,(struct termio *) arg);
		case TCSETAF:
			return set_termios(real_tty, arg, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
		case TCSETAW:
			return set_termios(real_tty, arg, TERMIOS_WAIT | TERMIOS_TERMIO);
		case TCSETA:
			return set_termios(real_tty, arg, TERMIOS_TERMIO);
		case TCXONC:
			retval = tty_check_change(tty);
			if (retval)
				return retval;
			switch (arg) {
			case TCOOFF:
				if (!tty->flow_stopped) {
					tty->flow_stopped = 1;
					stop_tty(tty);
				}
				break;
			case TCOON:
				if (tty->flow_stopped) {
					tty->flow_stopped = 0;
					start_tty(tty);
				}
				break;
			case TCIOFF:
				if (STOP_CHAR(tty) != __DISABLED_CHAR)
					send_prio_char(tty, STOP_CHAR(tty));
				break;
			case TCION:
				if (START_CHAR(tty) != __DISABLED_CHAR)
					send_prio_char(tty, START_CHAR(tty));
				break;
			default:
				return -EINVAL;
			}
			return 0;
		case TCFLSH:
			retval = tty_check_change(tty);
			if (retval)
				return retval;
			switch (arg) {
			case TCIFLUSH:
				if (tty->ldisc.flush_buffer)
					tty->ldisc.flush_buffer(tty);
				break;
			case TCIOFLUSH:
				if (tty->ldisc.flush_buffer)
					tty->ldisc.flush_buffer(tty);
				/* fall through */
			case TCOFLUSH:
				if (tty->driver->flush_buffer)
					tty->driver->flush_buffer(tty);
				break;
			default:
				return -EINVAL;
			}
			return 0;
		case TIOCOUTQ:
			return put_user(tty->driver->chars_in_buffer ?
					tty->driver->chars_in_buffer(tty) : 0,
					(int *) arg);
		case TIOCINQ:
			retval = tty->read_cnt;
			if (L_ICANON(tty))
				retval = inq_canon(tty);
			return put_user(retval, (unsigned int *) arg);
		case TIOCGLCKTRMIOS:
			if (kernel_termios_to_user_termios((struct termios *)arg, real_tty->termios_locked))
				return -EFAULT;
			return 0;

		case TIOCSLCKTRMIOS:
			if (!capable(CAP_SYS_ADMIN))
				return -EPERM;
			if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios *) arg))
				return -EFAULT;
			return 0;

		case TIOCPKT:
		{
			int pktmode;

			if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
			    tty->driver->subtype != PTY_TYPE_MASTER)
				return -ENOTTY;
			if (get_user(pktmode, (int *) arg))
				return -EFAULT;
			if (pktmode) {
				if (!tty->packet) {
					tty->packet = 1;
					tty->link->ctrl_status = 0;
				}
			} else
				tty->packet = 0;
			return 0;
		}
		case TIOCGSOFTCAR:
			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
		case TIOCSSOFTCAR:
			if (get_user(arg, (unsigned int *) arg))
				return -EFAULT;
			tty->termios->c_cflag =
				((tty->termios->c_cflag & ~CLOCAL) |
				 (arg ? CLOCAL : 0));
			return 0;
		default:
			return -ENOIOCTLCMD;
		}
}
示例#12
0
文件: cu.c 项目: appleorange1/bitrig
int
main(int argc, char **argv)
{
	const char	*errstr;
	char		*tmp, *s, *host;
	int		 opt, i;

	if (isatty(STDIN_FILENO) && tcgetattr(STDIN_FILENO, &saved_tio) != 0)
		err(1, "tcgetattr");

	/*
	 * Convert obsolescent -### speed to modern -s### syntax which getopt()
	 * can handle.
	 */
	for (i = 1; i < argc; i++) {
		if (strcmp("--", argv[i]) == 0)
			break;
		if (argv[i][0] != '-' || !isdigit((unsigned char)argv[i][1]))
			continue;

		if (asprintf(&argv[i], "-s%s", &argv[i][1]) == -1)
			errx(1, "speed asprintf");
	}

	while ((opt = getopt(argc, argv, "l:s:")) != -1) {
		switch (opt) {
		case 'l':
			line_path = optarg;
			break;
		case 's':
			line_speed = strtonum(optarg, 0, INT_MAX, &errstr);
			if (errstr != NULL)
				errx(1, "speed is %s: %s", errstr, optarg);
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (argc != 0 && argc != 1)
		usage();

	if (argc == 1)
		host = argv[0];
	else
		host = getenv("HOST");
	if (host != NULL && *host != '\0') {
		if (*host == '/')
			line_path = host;
		else {
			s = getenv("REMOTE");
			if (s != NULL && *s == '/')
				try_remote(host, s, NULL);
			else
				try_remote(host, NULL, s);
		}
	}

	if (line_path == NULL)
		line_path = "/dev/cua00";
	if (line_speed == -1)
		line_speed = 9600;

	if (strchr(line_path, '/') == NULL) {
		if (asprintf(&tmp, "%s%s", _PATH_DEV, line_path) == -1)
			err(1, "asprintf");
		line_path = tmp;
	}

	line_fd = open(line_path, O_RDWR);
	if (line_fd < 0)
		err(1, "open(\"%s\")", line_path);
	if (ioctl(line_fd, TIOCEXCL) != 0)
		err(1, "ioctl(TIOCEXCL)");
	if (tcgetattr(line_fd, &line_tio) != 0)
		err(1, "tcgetattr");
	if (set_line(line_speed) != 0)
		err(1, "tcsetattr");

	event_init();

	signal_set(&sigterm_ev, SIGTERM, signal_event, NULL);
	signal_add(&sigterm_ev, NULL);
	signal_set(&sighup_ev, SIGHUP, signal_event, NULL);
	signal_add(&sighup_ev, NULL);
	if (signal(SIGINT, SIG_IGN) == SIG_ERR)
		err(1, "signal");
	if (signal(SIGQUIT, SIG_IGN) == SIG_ERR)
		err(1, "signal");

	set_termios(); /* after this use cu_err and friends */

	/* stdin and stdout get separate events */
	input_ev = bufferevent_new(STDIN_FILENO, stream_read, NULL,
	    stream_error, NULL);
	bufferevent_enable(input_ev, EV_READ);
	output_ev = bufferevent_new(STDOUT_FILENO, NULL, NULL, stream_error,
	    NULL);
	bufferevent_enable(output_ev, EV_WRITE);

	line_ev = bufferevent_new(line_fd, line_read, NULL, line_error,
	    NULL);
	bufferevent_enable(line_ev, EV_READ|EV_WRITE);

	printf("Connected to %s (speed %d)\r\n", line_path, line_speed);
	event_dispatch();

	restore_termios();
	printf("\r\n[EOT]\n");

	exit(0);
}
示例#13
0
int tty_ioctl(int dev, int cmd, int arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	int pgrp;

	if (MAJOR(dev) == 5) {
		dev = current->tty;
		if (dev<0)
			return -EINVAL;
	} else
		dev=MINOR(dev);
	tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);

	if (IS_A_PTY(dev))
		other_tty = tty_table + PTY_OTHER(dev);
	else
		other_tty = NULL;
		
	if (!(tty->write_q && tty->read_q && tty->secondary && tty->write))
		return -EINVAL;
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush(tty->read_q);
			flush(tty->secondary);
			if (other_tty)
				flush(other_tty->write_q);
		/* fallthrough */
		case TCSETSW:
			wait_until_sent(tty);
		/* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg, dev);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush(tty->read_q);
			flush(tty->secondary);
			if (other_tty)
				flush(other_tty->write_q);
		/* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg, dev);
		case TCSBRK:
			if (!arg) {
				wait_until_sent(tty);
				send_break(tty);
			}
			return 0;
		case TCXONC:
			switch (arg) {
			case TCOOFF:
				tty->stopped = 1;
				tty->write(tty);
				return 0;
			case TCOON:
				tty->stopped = 0;
				tty->write(tty);
				return 0;
			case TCIOFF:
				if (STOP_CHAR(tty))
					PUTCH(STOP_CHAR(tty),tty->write_q);
				return 0;
			case TCION:
				if (START_CHAR(tty))
					PUTCH(START_CHAR(tty),tty->write_q);
				return 0;
			}
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0) {
				flush(tty->read_q);
				flush(tty->secondary);
				if (other_tty)
					flush(other_tty->write_q);
			} else if (arg==1)
				flush(tty->write_q);
			else if (arg==2) {
				flush(tty->read_q);
				flush(tty->secondary);
				flush(tty->write_q);
				if (other_tty)
					flush(other_tty->write_q);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			if ((current->tty < 0) ||
			    (current->tty != dev) ||
			    (tty->session != current->session))
				return -ENOTTY;
			pgrp=get_fs_long((unsigned long *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			tty->pgrp = pgrp;			
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
			return 0;
		case TIOCINQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->secondary),
				(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return get_window_size(tty,(struct winsize *) arg);
		case TIOCSWINSZ:
			if (other_tty)
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCMGET:
			return -EINVAL; /* not implemented */
		case TIOCMBIS:
			return -EINVAL; /* not implemented */
		case TIOCMBIC:
			return -EINVAL; /* not implemented */
		case TIOCMSET:
			return -EINVAL; /* not implemented */
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
				default: 
					return -EINVAL;
			}
		default:
			return -EINVAL;
	}
}