Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
typedef struct Opt	Opt;
2
 
3
int debug;
4
#define DPRINT if(debug)fprint
5
 
6
enum
7
{
8
	/* control characters */
9
	Se=		240,		/* end subnegotiation */
10
	NOP=		241,
11
	Mark=		242,		/* data mark */
12
	Break=		243,
13
	Interrupt=	244,
14
	Abort=		245,		/* TENEX ^O */
15
	AreYouThere=	246,
16
	Erasechar=	247,		/* erase last character */
17
	Eraseline=	248,		/* erase line */
18
	GoAhead=	249,		/* half duplex clear to send */
19
	Sb=		250,		/* start subnegotiation */
20
	Will=		251,
21
	Wont=		252,
22
	Do=		253,
23
	Dont=		254,
24
	Iac=		255,
25
 
26
	/* options */
27
	Binary=		0,
28
	Echo,
29
	SGA,
30
	Stat,
31
	Timing,
32
	Det,
33
	Term,
34
	EOR,
35
	Uid,
36
	Outmark,
37
	Ttyloc,
38
	M3270,
39
	Padx3,
40
	Window,
41
	Speed,
42
	Flow,
43
	Line,
44
	Xloc,
45
	Extend,
46
};
47
 
48
struct Opt
49
{
50
	char	*name;
51
	int	code;
52
	char	noway;	
53
	int	(*change)(Biobuf*, int);	/* routine for status change */
54
	int	(*sub)(Biobuf*, uchar*, int n);	/* routine for subnegotiation */
55
	char	remote;				/* remote value */
56
	char	local;				/* local value */
57
};
58
 
59
Opt opt[] =
60
{
61
[Binary]	{ "binary",		0,  0, },
62
[Echo]		{ "echo",		1,  0, },
63
[SGA]		{ "suppress Go Ahead",	3,  0, },
64
[Stat]		{ "status",		5,  1, },
65
[Timing]	{ "timing",		6,  1, },
66
[Det]		{ "det",		20, 1, },
67
[Term]		{ "terminal",		24, 0, },
68
[EOR]		{ "end of record",	25, 1, },
69
[Uid]		{ "uid",		26, 1, },
70
[Outmark]	{ "outmark",		27, 1, },
71
[Ttyloc]	{ "ttyloc",		28, 1, },
72
[M3270]		{ "3270 mode",		29, 1, },
73
[Padx3]		{ "pad x.3",		30, 1, },
74
[Window]	{ "window size",	31, 1, },
75
[Speed]		{ "speed",		32, 1, },
76
[Flow]		{ "flow control",	33, 1, },
77
[Line]		{ "line mode",		34, 1, },
78
[Xloc]		{ "X display loc",	35, 0, },
79
[Extend]	{ "Extended",		255, 1, },
80
};
81
 
82
int	control(Biobuf*, int);
83
Opt*	findopt(int);
84
int	will(Biobuf*);
85
int	wont(Biobuf*);
86
int	doit(Biobuf*);
87
int	dont(Biobuf*);
88
int	sub(Biobuf*);
89
int	send2(int, int, int);
90
int	send3(int, int, int, int);
91
int	sendnote(int, char*);
92
void	fatal(char*, void*, void*);
93
char*	syserr(void);
94
int	wasintr(void);
95
long	iread(int, void*, int);
96
long	iwrite(int, void*, int);
97
void	binit(Biobuf*, int);
98
void	berase(Biobuf*);
99
void	bkill(Biobuf*);
100
 
101
/*
102
 *  parse telnet control messages
103
 */
104
int
105
control(Biobuf *bp, int c)
106
{
107
	if(c < 0)
108
		return -1;
109
	switch(c){
110
	case AreYouThere:
111
		fprint(Bfildes(bp), "Plan 9 telnet, version 1\r\n");
112
		break;
113
	case Sb:
114
		return sub(bp);
115
	case Will:
116
		return will(bp);
117
	case Wont:
118
		return wont(bp);
119
	case Do:
120
		return doit(bp);
121
	case Dont:
122
		return dont(bp);
123
	case Se:
124
		fprint(2, "telnet: SE without an SB\n");
125
		break;
126
	default:
127
		break;
128
	}
129
	return 0;
130
}
131
 
132
Opt*
133
findopt(int c)
134
{
135
	Opt *o;
136
 
137
	for(o = opt; o <= &opt[Extend]; o++)
138
		if(o->code == c)
139
			return o;
140
	return 0;
141
}
142
 
143
int
144
will(Biobuf *bp)
145
{
146
	Opt *o;
147
	int c;
148
	int rv = 0;
149
 
150
	c = Bgetc(bp);
151
	if(c < 0)
152
		return -1;
153
	DPRINT(2, "will %d\n", c);
154
	o = findopt(c);
155
	if(o == 0){
156
		send3(Bfildes(bp), Iac, Dont, c);
157
		return 0;
158
	}
159
	if(o->noway)
160
		send3(Bfildes(bp), Iac, Dont, c);
161
	else if(o->remote == 0)
162
		rv |= send3(Bfildes(bp), Iac, Do, c);
163
	if(o->remote == 0){
164
		if(o->change)
165
			rv |= (*o->change)(bp, Will);
166
	}
167
	o->remote = 1;
168
	return rv;
169
}
170
 
171
int
172
wont(Biobuf *bp)
173
{
174
	Opt *o;
175
	int c;
176
	int rv = 0;
177
 
178
	c = Bgetc(bp);
179
	if(c < 0)
180
		return -1;
181
	DPRINT(2, "wont %d\n", c);
182
	o = findopt(c);
183
	if(o == 0)
184
		return 0;
185
	if(o->remote){
186
		if(o->change)
187
			rv |= (*o->change)(bp, Wont);
188
		rv |= send3(Bfildes(bp), Iac, Dont, c);
189
	}
190
	o->remote = 0;
191
	return rv;
192
}
193
 
194
int
195
doit(Biobuf *bp)
196
{
197
	Opt *o;
198
	int c;
199
	int rv = 0;
200
 
201
	c = Bgetc(bp);
202
	if(c < 0)
203
		return -1;
204
	DPRINT(2, "do %d\n", c);
205
	o = findopt(c);
206
	if(o == 0 || o->noway){
207
		send3(Bfildes(bp), Iac, Wont, c);
208
		return 0;
209
	}
210
	if(o->noway)
211
		return 0;
212
	if(o->local == 0){
213
		if(o->change)
214
			rv |= (*o->change)(bp, Do);
215
		rv |= send3(Bfildes(bp), Iac, Will, c);
216
	}
217
	o->local = 1;
218
	return rv;
219
}
220
 
221
int
222
dont(Biobuf *bp)
223
{
224
	Opt *o;
225
	int c;
226
	int rv = 0;
227
 
228
	c = Bgetc(bp);
229
	if(c < 0)
230
		return -1;
231
	DPRINT(2, "dont %d\n", c);
232
	o = findopt(c);
233
	if(o == 0)
234
		return 0;
235
	if(o->noway)
236
		return 0;
237
	if(o->local){
238
		o->local = 0;
239
		if(o->change)
240
			rv |= (*o->change)(bp, Dont);
241
		rv |= send3(Bfildes(bp), Iac, Wont, c);
242
	}
243
	o->local = 0;
244
	return rv;
245
}
246
 
247
/* read in a subnegotiation message and pass it to a routine for that option */
248
int
249
sub(Biobuf *bp)
250
{
251
	uchar subneg[128];
252
	uchar *p;
253
	Opt *o;
254
	int c;
255
 
256
	p = subneg;
257
	for(;;){
258
		c = Bgetc(bp);
259
		if(c == Iac){
260
			c = Bgetc(bp);
261
			if(c == Se)
262
				break;
263
			if(p < &subneg[sizeof(subneg)])
264
				*p++ = Iac;
265
		}
266
		if(c < 0)
267
			return -1;
268
		if(p < &subneg[sizeof(subneg)])
269
			*p++ = c;
270
	}
271
	if(p == subneg)
272
		return 0;
273
	DPRINT(2, "sub %d %d n = %d\n", subneg[0], subneg[1], (int)(p - subneg - 1));
274
	o = findopt(subneg[0]);
275
	if(o == 0 || o->sub == 0)
276
		return 0;
277
	return (*o->sub)(bp, subneg+1, p - subneg - 1);
278
}
279
 
280
void
281
sendd(int c0, int c1)
282
{
283
	char *t = 0;
284
 
285
	switch(c0){
286
	case Will:
287
		t = "Will";
288
		break;
289
	case Wont:
290
		t = "Wont";
291
		break;
292
	case Do:
293
		t = "Do";
294
		break;
295
	case Dont:
296
		t = "Dont";
297
		break;
298
	}
299
	if(t)
300
		DPRINT(2, "r %s %d\n", t, c1);
301
}
302
 
303
int
304
send2(int f, int c0, int c1)
305
{
306
	uchar buf[2];
307
 
308
	buf[0] = c0;
309
	buf[1] = c1;
310
	return iwrite(f, buf, 2) == 2 ? 0 : -1;
311
}
312
 
313
int
314
send3(int f, int c0, int c1, int c2)
315
{
316
	uchar buf[3];
317
 
318
	buf[0] = c0;
319
	buf[1] = c1;
320
	buf[2] = c2;
321
	sendd(c1, c2);
322
	return iwrite(f, buf, 3) == 3 ? 0 : -1;
323
}
324
 
325
int
326
sendnote(int pid, char *msg)
327
{
328
	int fd;
329
	char name[128];
330
 
331
	sprint(name, "/proc/%d/note", pid);
332
	fd = open(name, OWRITE);
333
	if(fd < 0)
334
		return -1;
335
	if(write(fd, msg, strlen(msg))!=strlen(msg))
336
		return -1;
337
	return close(fd);
338
}
339
 
340
void
341
fatal(char *fmt, void *a0, void *a1)
342
{
343
	char buf[128];
344
 
345
	sprint(buf, fmt, a0, a1);
346
	fprint(2, "%s: %s\n", argv0, buf);
347
	exits(buf);
348
}
349
 
350
char*
351
syserr(void)
352
{
353
	static char err[ERRMAX];
354
 
355
	errstr(err, sizeof err);
356
	return err;
357
}
358
 
359
int
360
wasintr(void)
361
{
362
	return strcmp(syserr(), "interrupted") == 0;
363
}
364
 
365
long
366
iread(int f, void *a, int n)
367
{
368
	long m;
369
 
370
	for(;;){
371
		m = read(f, a, n);
372
		if(m >= 0 || !wasintr())
373
			break;
374
	}
375
	return m;
376
}
377
 
378
long
379
iwrite(int f, void *a, int n)
380
{
381
	long m;
382
 
383
	m = write(f, a, n);
384
	if(m < 0 && wasintr())
385
		return n;
386
	return m;
387
}