sconsole.c
3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Copyright (C) 1996-1998 by the Board of Trustees
* of Leland Stanford Junior University.
*
* This file is part of the SimOS distribution.
* See LICENSE file for terms of the license.
*
*/
/*
* sconsole.c: use this instead of telnet to connect to simos slave consoles
*
* telnet does character echoing, line buffering, etc. that interact badly
* with the operating system running inside of simos
*
* Connect stdin/out to a tcp socket connection with no line editing or anything
*/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/termios.h>
#include <stropts.h>
#include <poll.h>
#define BUFSIZ 4096
char buf[BUFSIZ];
int main(int argc, char** argv)
{
int sock_fd, tmp;
struct sockaddr_in server;
struct hostent* hp;
struct termios ios, ios_save;
if (argc != 3) {
fprintf(stderr, "usage: %s machine_name port\n", argv[0]);
return 1;
}
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
perror("opening stream socket");
return 1;
}
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if (hp == 0) {
fprintf(stderr, "%s: unknown host\n", argv[1]);
return 1;
}
memcpy((char*) &server.sin_addr, (char*) hp->h_addr, (uint) hp->h_length);
server.sin_port = (ushort) atoi(argv[2]);
if (connect(sock_fd, (struct sockaddr*) &server, sizeof(server)) < 0) {
perror("connecting stream socket");
return 1;
}
/* Tell TCP not to delay small packets. This greatly speeds up
interactive response. */
tmp = 1;
if (setsockopt (sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp))<0) {
perror("setting socket option");
return 1;
}
/* Turn off all local character processing by my tty. This
* is the responsibility of the simos I am connected to.
*/
if (tcgetattr(0, &ios_save) < 0) {
perror("tcgetattr\n");
}
ios = ios_save;
ios.c_iflag &= ~(ISTRIP|IGNCR|IXOFF|IXON|ICRNL);
ios.c_oflag &= ~OPOST;
ios.c_lflag &= ~(ISIG|ICANON|ECHO);
ios.c_cc[VMIN] = 1;
ios.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSANOW, &ios) < 0) {
perror("tcsetattr\n");
}
/* set up for nonblocking I/O */
if (fcntl(0, F_SETFL, FNONBLK)) {
perror("setting noblock on stdin");
return 1;
}
if (fcntl(sock_fd, F_SETFL, FNONBLK)) {
perror("setting noblock on socket");
return 1;
}
/* main loop */
{
struct pollfd fds[2];
int done;
/* we poll on stdin and on the socket */
fds[0].fd = 0;
fds[0].events = POLLIN;
fds[1].fd = sock_fd;
fds[1].events = POLLIN;
while (1) {
fds[0].revents = 0;
fds[1].revents = 0;
poll(fds, 2, -1);
if (fds[0].revents & POLLIN) {
done = read(0, buf, BUFSIZ);
if (done == 0) break;
if (done > 0) write(sock_fd, buf, done);
}
if (fds[1].revents & POLLIN) {
done = read(sock_fd, buf, BUFSIZ);
if (done == 0) break;
if (done > 0) write(1, buf, done);
}
}
}
if (tcsetattr(0, TCSAFLUSH, &ios_save) < 0) {
perror("tcsetattr\n");
}
if (fcntl(0, F_SETFL, 0)) {
perror("turning off noblock on stdin");
return 1;
}
printf("\n");
return 0;
}