debuggers.hg

view tools/misc/miniterm/miniterm.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents ab85c20d33e5
children
line source
1 /******************************************************************************
2 * miniterm.c
3 *
4 * Adapted from the example program distributed with the Linux Programmer's
5 * Guide (LPG). This has been robustified and tweaked to work as a debugging
6 * terminal for Xen-based machines.
7 *
8 * Modifications are released under GPL and copyright (c) 2003, K A Fraser
9 * The original copyright message and license is fully intact below.
10 */
12 /*
13 * AUTHOR: Sven Goldt (goldt@math.tu-berlin.de)
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 */
27 #include <termios.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <signal.h>
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <string.h>
37 #define DEFAULT_BAUDRATE 115200
38 #define DEFAULT_SERDEVICE "/dev/ttyS0"
39 #define ENDMINITERM 0x1d
41 volatile int stop = 0;
43 void child_handler(int s)
44 {
45 stop = 1;
46 }
48 int cook_baud(int baud)
49 {
50 int cooked_baud = 0;
51 switch ( baud )
52 {
53 case 50: cooked_baud = B50; break;
54 case 75: cooked_baud = B75; break;
55 case 110: cooked_baud = B110; break;
56 case 134: cooked_baud = B134; break;
57 case 150: cooked_baud = B150; break;
58 case 200: cooked_baud = B200; break;
59 case 300: cooked_baud = B300; break;
60 case 600: cooked_baud = B600; break;
61 case 1200: cooked_baud = B1200; break;
62 case 1800: cooked_baud = B1800; break;
63 case 2400: cooked_baud = B2400; break;
64 case 4800: cooked_baud = B4800; break;
65 case 9600: cooked_baud = B9600; break;
66 case 19200: cooked_baud = B19200; break;
67 case 38400: cooked_baud = B38400; break;
68 case 57600: cooked_baud = B57600; break;
69 case 115200: cooked_baud = B115200; break;
70 }
71 return cooked_baud;
72 }
74 int main(int argc, char **argv)
75 {
76 int fd, c, cooked_baud = cook_baud(DEFAULT_BAUDRATE);
77 char *sername = DEFAULT_SERDEVICE;
78 struct termios oldsertio, newsertio, oldstdtio, newstdtio;
79 struct sigaction sa;
80 static char start_str[] =
81 "************ REMOTE CONSOLE: CTRL-] TO QUIT ********\r\n";
82 static char end_str[] =
83 "\n************ REMOTE CONSOLE EXITED *****************\n";
85 while ( --argc != 0 )
86 {
87 char *p = argv[argc];
88 if ( *p++ != '-' )
89 goto usage;
90 if ( *p == 'b' )
91 {
92 p++;
93 if ( (cooked_baud = cook_baud(atoi(p))) == 0 )
94 {
95 fprintf(stderr, "Bad baud rate '%d'\n", atoi(p));
96 goto usage;
97 }
98 }
99 else if ( *p == 'd' )
100 {
101 sername = ++p;
102 if ( *sername == '\0' )
103 goto usage;
104 }
105 else
106 goto usage;
107 }
109 /* Not a controlling tty: CTRL-C shouldn't kill us. */
110 fd = open(sername, O_RDWR | O_NOCTTY);
111 if ( fd < 0 )
112 {
113 perror(sername);
114 exit(-1);
115 }
117 tcgetattr(fd, &oldsertio); /* save current modem settings */
119 /*
120 * 8 data, no parity, 1 stop bit. Ignore modem control lines. Enable
121 * receive. Set appropriate baud rate. NO HARDWARE FLOW CONTROL!
122 */
123 newsertio.c_cflag = cooked_baud | CS8 | CLOCAL | CREAD;
125 /* Raw input. Ignore errors and breaks. */
126 newsertio.c_iflag = IGNBRK | IGNPAR;
128 /* Raw output. */
129 newsertio.c_oflag = OPOST;
131 /* No echo and no signals. */
132 newsertio.c_lflag = 0;
134 /* blocking read until 1 char arrives */
135 newsertio.c_cc[VMIN]=1;
136 newsertio.c_cc[VTIME]=0;
138 /* now clean the modem line and activate the settings for modem */
139 tcflush(fd, TCIFLUSH);
140 tcsetattr(fd,TCSANOW,&newsertio);
142 /* next stop echo and buffering for stdin */
143 tcgetattr(0,&oldstdtio);
144 tcgetattr(0,&newstdtio); /* get working stdtio */
145 newstdtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
146 newstdtio.c_oflag &= ~OPOST;
147 newstdtio.c_cflag &= ~(CSIZE | PARENB);
148 newstdtio.c_cflag |= CS8;
149 newstdtio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
150 newstdtio.c_cc[VMIN]=1;
151 newstdtio.c_cc[VTIME]=0;
152 tcsetattr(0,TCSANOW,&newstdtio);
154 /* Terminal settings done: now enter the main I/O loops. */
155 switch ( fork() )
156 {
157 case 0:
158 close(1); /* stdout not needed */
159 for ( c = (char)getchar(); c != ENDMINITERM; c = (char)getchar() )
160 write(fd,&c,1);
161 tcsetattr(fd,TCSANOW,&oldsertio);
162 tcsetattr(0,TCSANOW,&oldstdtio);
163 close(fd);
164 exit(0); /* will send a SIGCHLD to the parent */
165 break;
166 case -1:
167 perror("fork");
168 tcsetattr(fd,TCSANOW,&oldsertio);
169 close(fd);
170 exit(-1);
171 default:
172 write(1, start_str, strlen(start_str));
173 close(0); /* stdin not needed */
174 sa.sa_handler = child_handler;
175 sa.sa_flags = 0;
176 sigaction(SIGCHLD,&sa,NULL); /* handle dying child */
177 while ( !stop )
178 {
179 read(fd,&c,1); /* modem */
180 c = (char)c;
181 write(1,&c,1); /* stdout */
182 }
183 wait(NULL); /* wait for child to die or it will become a zombie */
184 write(1, end_str, strlen(end_str));
185 break;
186 }
188 return 0;
190 usage:
191 printf("miniterm [-b<baudrate>] [-d<devicename>]\n");
192 printf("Default baud rate: %d\n", DEFAULT_BAUDRATE);
193 printf("Default device: %s\n", DEFAULT_SERDEVICE);
194 return 1;
195 }