131 lines
2.9 KiB
C
131 lines
2.9 KiB
C
/* Unix pty slave program -- David Decotigny 2005
|
|
License: GNU GPL version 2
|
|
Most of it taken from the GNU C library doc examples */
|
|
#include <utmp.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <termios.h>
|
|
|
|
/**
|
|
* @file termslave.c
|
|
*
|
|
* Linux pseudo-TTY slave program. To be used with "qemu -monitor pty"
|
|
* to access qemu's monitor from any linux terminal. To use it, launch
|
|
* a "qemu -monitor pty" in one terminal, take a look at the first
|
|
* line stating "char device redirected to /dev/pts/4" for example,
|
|
* and lauch the termslave program as "./termslave /dev/pts/4" in
|
|
* another terminal.
|
|
*
|
|
* To make this correctly work, one has to apply the
|
|
* patch-qemu-pty.diff patch to qemu < 0.8.0 (qemu 0.8.0 and beyond
|
|
* already includes this patch).
|
|
*
|
|
* This program also works with the "-serial pty" flag of qemu. It can
|
|
* be used to send commands to the SOS serial-line shell (article 9).
|
|
*/
|
|
|
|
|
|
/* Use this variable to remember original terminal attributes. */
|
|
struct termios saved_attributes;
|
|
|
|
static void
|
|
reset_input_mode (void)
|
|
{
|
|
tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes);
|
|
}
|
|
|
|
static void
|
|
set_input_mode (void)
|
|
{
|
|
struct termios tattr;
|
|
|
|
/* Make sure stdin is a terminal. */
|
|
if (!isatty (STDIN_FILENO))
|
|
{
|
|
fprintf (stderr, "Not a terminal.\n");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
/* Save the terminal attributes so we can restore them later. */
|
|
tcgetattr (STDIN_FILENO, &saved_attributes);
|
|
atexit (reset_input_mode);
|
|
|
|
/* Set the funny terminal modes. */
|
|
tcgetattr (STDIN_FILENO, &tattr);
|
|
tattr.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|
|
|INLCR|IGNCR|ICRNL|IXON);
|
|
tattr.c_lflag &= ~(ICANON|ECHO);
|
|
tattr.c_cflag |= CLOCAL;
|
|
tattr.c_cc[VMIN] = 1;
|
|
tattr.c_cc[VTIME] = 0;
|
|
tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
|
|
}
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
int term;
|
|
|
|
if (argc < 2)
|
|
{
|
|
fprintf(stderr, "Usage: %s /dev/pts/number\n", argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
term = open(argv[1], O_RDWR);
|
|
if (term < 0)
|
|
{
|
|
perror("open");
|
|
return -1;
|
|
}
|
|
if (! isatty(term))
|
|
{
|
|
fprintf(stderr, "%s is not a valid terminal\n", argv[1]);
|
|
return -1;
|
|
}
|
|
|
|
set_input_mode();
|
|
|
|
while (1)
|
|
{
|
|
fd_set cur_set;
|
|
FD_ZERO(& cur_set);
|
|
FD_SET(STDIN_FILENO, & cur_set);
|
|
FD_SET(term, & cur_set);
|
|
if (select(FD_SETSIZE, & cur_set, NULL, NULL, NULL) < 1)
|
|
continue;
|
|
|
|
if (FD_ISSET(term, & cur_set))
|
|
{
|
|
char buf[1024];
|
|
int len = read(term, buf, sizeof(buf));
|
|
|
|
if (len >= 1)
|
|
write(STDOUT_FILENO, buf, len);
|
|
else
|
|
{
|
|
fprintf(stderr, "Master exitted\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FD_ISSET(STDIN_FILENO, & cur_set))
|
|
{
|
|
char c;
|
|
if (read(STDIN_FILENO, &c, 1) == 1)
|
|
{
|
|
if (c == 0x4) /* ctrl-D */
|
|
break;
|
|
write(term, &c, 1);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|