]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/telnet.h
ip/ipconfig: default onlink and autoflag to 1
[plan9front.git] / sys / src / cmd / ip / telnet.h
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 }