-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathserverside.d
124 lines (99 loc) · 2.93 KB
/
serverside.d
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
// OBSOLETE - the Windows version can now speak ssh.
// ****************************
// dmd serverside.d -L-lutil
deprecated:
// the following is just cuz the forkpty example might be
// useful to me some day.
/*
This program is needed because the Windows version doesn't actually speak ssh.
So it takes some special commands in lieu of the correct ssh packets for stuff like
size ioctl calls.
*/
version(Posix) {
extern(C) {
pragma(lib, "util");
int forkpty(int* master, /*int* slave,*/ void* name, void* termp, void* winp);
int execl(const(char)* path, const(char*) arg, ...);
int write(int fd, in void* buf, int count);
int read(int fd, void* buf, int count);
void wait(int);
int ishit(int a);
alias void function(int) sighandler_t;
sighandler_t signal(int signum, sighandler_t handler);
version(linux)
enum int SIGCHLD = 17;
}
import core.sys.posix.termios;
import core.sys.posix.sys.ioctl;
import core.stdc.errno;
__gshared int childrenAlive = 0;
extern(C)
void childdead(int) {
childrenAlive--;
}
import core.sys.posix.sys.select;
}
void main(string[] args) {
int master;
signal(SIGCHLD, &childdead);
childrenAlive = 1;
int pid = forkpty(&master, null, null, null);
if(pid == -1)
throw new Exception("forkpty");
if(pid == 0) {
import std.process;
environment["TERM"] = "xterm"; // we're closest to an xterm, so definitely want to pretend to be one to the child processes
environment["TERM_EXTENSIONS"] = "arsd";
environment["LANG"] = "en_US.UTF-8"; // tell them that utf8 rox (FIXME: what about non-US?)
execl("/bin/bash", "/bin/bash", null);
} else {
ubyte[4096] buffer;
while(childrenAlive) {
fd_set rdfs;
FD_ZERO(&rdfs);
FD_SET(0, &rdfs);
FD_SET(master, &rdfs);
auto ret = select(master + 1, &rdfs, null, null, null);
if(ret == -1) {
if(errno == 4)
continue; // EINTR
else throw new Exception("select");
}
if(ret) {
if(FD_ISSET(0, &rdfs)) {
// data from ssh should be checked for magic, otherwise just forwarded
int len = read(0, buffer.ptr, buffer.length);
if(len <= 0)
break; // perhaps they disconnected
foreach(idx, b; buffer[0 .. len]) {
if(b == 254 && idx + 2 < len) {
// special command, resize
winsize win;
win.ws_col = buffer[idx + 1];
win.ws_row = buffer[idx + 2];
import core.sys.posix.sys.ioctl;
ioctl(master, TIOCSWINSZ, &win);
// cut it right out...
foreach(i; 0 .. 3) {
foreach(lol; idx .. len - 1)
buffer[lol] = buffer[lol + 1];
len--;
}
break;
}
}
if(len)
write(master, buffer.ptr, len);
}
if(FD_ISSET(master, &rdfs)) {
// data from the pty should be forwarded straight out
int len = read(master, buffer.ptr, buffer.length);
if(len <= 0)
break; // probably end of file or something cuz the child exited
if(len)
write(1, buffer.ptr, len);
}
}
}
}
}