mem: Clean up Request initialisation
[gem5.git] / util / term / term.c
1 /* $OpenBSD: netcat.c,v 1.57 2002/12/30 18:00:18 stevesk Exp $ */
2 /*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <arpa/telnet.h>
30 #include <netinet/in.h>
31 #include <sys/socket.h>
32 #include <sys/termios.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/un.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <netdb.h>
40 #include <poll.h>
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
48 void readwrite(int);
49 int remote_connect(char *, char *, struct addrinfo);
50
51 struct termios saved_ios;
52 void raw_term();
53 void restore_term();
54
55 char progname[256];
56 void usage(int);
57
58 int
59 main(int argc, char *argv[])
60 {
61 int ch, s, ret;
62 char *host, *port, *endp;
63 struct addrinfo hints;
64 socklen_t len;
65
66 ret = 1;
67 s = 0;
68 host = NULL;
69 port = NULL;
70 endp = NULL;
71
72 strncpy(progname, argv[0], sizeof progname);
73
74 /* Cruft to make sure options are clean, and used properly. */
75 if (argc == 2) {
76 host = "localhost";
77 port = argv[1];
78 } else if (argc == 3) {
79 host = argv[1];
80 port = argv[2];
81 } else {
82 usage(1);
83 }
84
85 if (!isatty(STDIN_FILENO))
86 errx(1, "not attached to a terminal");
87
88 raw_term();
89
90 /* Initialize addrinfo structure */
91 memset(&hints, 0, sizeof(struct addrinfo));
92 hints.ai_family = AF_UNSPEC;
93 hints.ai_socktype = SOCK_STREAM;
94 hints.ai_protocol = IPPROTO_TCP;
95
96 s = remote_connect(host, port, hints);
97 ret = 0;
98 readwrite(s);
99
100 if (s)
101 close(s);
102
103 exit(ret);
104 }
105
106 /*
107 * remote_connect()
108 * Return's a socket connected to a remote host. Properly bind's to a local
109 * port or source address if needed. Return's -1 on failure.
110 */
111 int
112 remote_connect(char *host, char *port, struct addrinfo hints)
113 {
114 struct addrinfo *res, *res0;
115 int s, error;
116
117 if ((error = getaddrinfo(host, port, &hints, &res)))
118 errx(1, "getaddrinfo: %s", gai_strerror(error));
119
120 res0 = res;
121 do {
122 if ((s = socket(res0->ai_family, res0->ai_socktype,
123 res0->ai_protocol)) < 0)
124 continue;
125
126 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
127 break;
128
129 close(s);
130 s = -1;
131 } while ((res0 = res0->ai_next) != NULL);
132
133 freeaddrinfo(res);
134
135 return (s);
136 }
137
138 /*
139 * readwrite()
140 * Loop that selects on the network file descriptor and stdin.
141 * Changed from poll() by Ali Saidi to make work on Mac OS X >= 10.4
142 */
143 void
144 readwrite(int nfd)
145 {
146 fd_set read_fds;
147 char buf[BUFSIZ];
148 int wfd = fileno(stdin), n, ret, max_fd;
149 int lfd = fileno(stdout);
150 int escape = 0;
151 struct timeval timeout;
152
153 if (nfd == -1)
154 return;
155
156 max_fd = nfd + 1;
157
158 while (1) {
159 FD_ZERO(&read_fds);
160 FD_SET(wfd, &read_fds);
161 FD_SET(nfd, &read_fds);
162 timeout.tv_sec = 1;
163 timeout.tv_usec = 0;
164
165 n = select(max_fd, &read_fds, NULL, NULL, &timeout);
166 if (n < 0) {
167 close(nfd);
168 perror("Select Error:");
169 }
170
171 if (n == 0) {
172 if (read(nfd, buf, 0) < 0)
173 return;
174 continue;
175 }
176
177 if (read(nfd, buf, 0) < 0)
178 return;
179
180 if (FD_ISSET(nfd, &read_fds)) {
181 if ((n = read(nfd, buf, sizeof(buf))) < 0)
182 return;
183 else if (n == 0) {
184 shutdown(nfd, SHUT_RD);
185 return;
186 } else {
187 if ((ret = atomicio(write, lfd, buf, n)) != n)
188 return;
189 }
190 }
191
192 if (FD_ISSET(wfd, &read_fds)) {
193 if ((n = read(wfd, buf, sizeof(buf))) < 0)
194 return;
195 else if (n == 0) {
196 shutdown(nfd, SHUT_WR);
197 } else {
198 if (escape) {
199 char buf2[] = "~";
200 if (*buf == '.') {
201 printf("quit!\n");
202 return;
203 }
204 escape = 0;
205 if (*buf != '~' &&
206 (ret = atomicio(write, nfd, buf2, 1)) != n)
207 return;
208 } else {
209 escape = (*buf == '~');
210 if (escape)
211 continue;
212 }
213
214 if ((ret = atomicio(write, nfd, buf, n)) != n)
215 return;
216 }
217 }
218 } // while
219 }
220
221 void
222 usage(int ret)
223 {
224 fprintf(stderr, "usage: %s hostname port\n", progname);
225 if (ret)
226 exit(1);
227 }
228
229 /*
230 * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
231 * All rights reserved.
232 *
233 * Redistribution and use in source and binary forms, with or without
234 * modification, are permitted provided that the following conditions
235 * are met:
236 * 1. Redistributions of source code must retain the above copyright
237 * notice, this list of conditions and the following disclaimer.
238 * 2. Redistributions in binary form must reproduce the above copyright
239 * notice, this list of conditions and the following disclaimer in the
240 * documentation and/or other materials provided with the distribution.
241 *
242 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
243 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
244 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
245 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
246 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
247 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
248 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
250 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
251 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252 */
253
254 /*
255 * ensure all of data on socket comes through. f==read || f==write
256 */
257 ssize_t
258 atomicio(ssize_t (*f) (), int fd, void *_s, size_t n)
259 {
260 char *s = _s;
261 ssize_t res, pos = 0;
262
263 while (n > pos) {
264 res = (f) (fd, s + pos, n - pos);
265 switch (res) {
266 case -1:
267 if (errno == EINTR || errno == EAGAIN)
268 continue;
269 case 0:
270 return (res);
271 default:
272 pos += res;
273 }
274 }
275 return (pos);
276 }
277
278 /*
279 * Copyright (c) 2003 Nathan L. Binkert <binkertn@umich.edu>
280 *
281 * Permission to use, copy, modify, and distribute this software for any
282 * purpose with or without fee is hereby granted, provided that the above
283 * copyright notice and this permission notice appear in all copies.
284 *
285 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
286 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
287 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
288 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
289 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
290 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
291 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
292 */
293
294 void
295 raw_term()
296 {
297 struct termios ios;
298
299 if (tcgetattr(STDIN_FILENO, &ios) < 0)
300 errx(1, "tcgetagttr\n");
301
302 memcpy(&saved_ios, &ios, sizeof(struct termios));
303
304 ios.c_iflag &= ~(ISTRIP|ICRNL|IGNCR|ICRNL|IXOFF|IXON);
305 ios.c_oflag &= ~(OPOST);
306 ios.c_oflag &= (ONLCR);
307 ios.c_lflag &= ~(ISIG|ICANON|ECHO);
308 ios.c_cc[VMIN] = 1;
309 ios.c_cc[VTIME] = 0;
310
311 if (tcsetattr(STDIN_FILENO, TCSANOW, &ios) < 0)
312 errx(1, "tcsetattr\n");
313
314 atexit(restore_term);
315 }
316
317 void
318 restore_term()
319 {
320 tcsetattr(STDIN_FILENO, TCSANOW, &saved_ios);
321 }