3 * (c) Jack lange, Lei Xia, Peter Dinda 2010, 2013
10 #include <sys/ioctl.h>
12 #include <sys/types.h>
18 #include <linux/unistd.h>
25 #define STREAM_NAME_LEN 128
31 struct termios ourterm, oldterm;
36 if (tcgetattr(0,&oldterm)) {
37 fprintf(stderr,"Cannot get terminal attributes\n");
41 ourterm = oldterm; // clone existing terminal behavior
42 ourterm.c_lflag &= ~ICANON; // but without buffering
43 ourterm.c_lflag &= ~ECHO; // or echoing
44 ourterm.c_lflag &= ~ISIG; // or interrupt keys
45 ourterm.c_cc[VMIN] = 0; // or weird delays to compose
46 ourterm.c_cc[VTIME] = 0; // function keys (e.g., set raw)
47 fprintf(stderr, "Calling tcsetattr.\n");
49 if (tcsetattr(0,TCSANOW,&ourterm)) {
50 fprintf(stderr,"Cannot set terminal attributes\n");
53 fprintf(stderr,"term setup interactive\n");
55 fprintf(stderr, "term setup noninteractive\n");
64 return -!!tcsetattr(0,TCSANOW,&oldterm);
70 int pump(int in, int out)
78 // data from the stream
79 check_esc = interactive && (in == STDIN_FILENO);
80 bytes_read = read(in, buf, check_esc ? 1 : BUF_LEN);
92 fprintf(stderr,"Bye\n");
95 /* Pass the second escape! */
98 fprintf(stderr, "Unknown ESC sequence.\n");
102 } else if (buf[0] == ESC_KEY) {
108 fprintf(stderr,"read %d bytes\n", bytes_read);
112 while (bytes_written<bytes_read) {
113 thiswrite = write(out,&(buf[bytes_written]),bytes_read-bytes_written);
115 if (errno==EWOULDBLOCK) {
118 perror("Cannot write");
122 fprintf(stderr,"Hmm, surprise end-of-file on write\n");
125 bytes_written+=thiswrite;
128 fprintf(stderr,"wrote %d bytes\n",bytes_written);
135 void signal_handler(int num)
141 fprintf(stderr,"Bye\n");
145 fprintf(stderr,"Unknown signal %d ignored\n",num);
149 int main(int argc, char* argv[])
154 char * vm_dev = NULL;
155 char stream[STREAM_NAME_LEN];
160 "usage: v3_stream [-i] <vm_device> <stream_name>\n\n"
161 "Connects stdin/stdout to a bidirectional stream on the VM,\n"
162 "for example a serial port.\n\n"
163 "If the [-i] option is given, a terminal is assumed\n"
164 "and it is placed in non-echoing, interactive mode, \n"
165 "which is what you probably want for use as a console.\n");
169 if (!strcasecmp(argv[1],"-i")) {
173 // noninteractive mode
178 vm_dev = argv[argstart];
180 if (strlen(argv[argstart+1]) >= STREAM_NAME_LEN) {
181 fprintf(stderr, "ERROR: Stream name longer than maximum size (%d)\n", STREAM_NAME_LEN);
185 memcpy(stream, argv[argstart+1], strlen(argv[argstart+1]));
187 vm_fd = open(vm_dev, O_RDONLY);
190 fprintf(stderr,"Error opening VM device: %s\n", vm_dev);
194 stream_fd = ioctl(vm_fd, V3_VM_SERIAL_CONNECT, stream);
199 fprintf(stderr,"Error opening VM device: %s\n", vm_dev);
204 fprintf(stderr,"Cannot setup terminal for %s mode\n", interactive ? "interactive" : "noninteraInteractive");
209 signal(SIGINT,signal_handler);
214 FD_SET(stream_fd, &rset);
215 FD_SET(STDIN_FILENO, &rset);
217 // wait for data from stdin or from the stream
218 ret = select(stream_fd + 1, &rset, NULL, NULL, NULL);
220 fprintf(stderr,"select ret=%d\n", ret);
223 perror("select returned zero without a timer!");
229 perror("select failed");
234 // positive return - we have data on one or both
236 // check data from stream
237 if (FD_ISSET(stream_fd, &rset)) {
238 fprintf(stderr,"stream is readable\n");
239 if (pump(stream_fd, STDOUT_FILENO)) {
240 fprintf(stderr,"Cannot transfer all data from stream to stdout...\n");
245 // check data from stdin
247 if (FD_ISSET(STDIN_FILENO, &rset)) {
248 fprintf(stderr,"stdin is readable\n");
249 if (pump(STDIN_FILENO,stream_fd)) {
250 fprintf(stderr,"Cannot transfer all data from stdin to stream...\n");