1 typedef struct Opt Opt;
4 #define DPRINT if(debug)fprint
8 /* control characters */
9 Se= 240, /* end subnegotiation */
11 Mark= 242, /* data mark */
14 Abort= 245, /* TENEX ^O */
16 Erasechar= 247, /* erase last character */
17 Eraseline= 248, /* erase line */
18 GoAhead= 249, /* half duplex clear to send */
19 Sb= 250, /* start subnegotiation */
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 */
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, },
82 int control(Biobuf*, int);
89 int send2(int, int, int);
90 int send3(int, int, int, int);
91 int sendnote(int, char*);
92 void fatal(char*, void*, void*);
95 long iread(int, void*, int);
96 long iwrite(int, void*, int);
97 void binit(Biobuf*, int);
102 * parse telnet control messages
105 control(Biobuf *bp, int c)
111 fprint(Bfildes(bp), "Plan 9 telnet, version 1\r\n");
124 fprint(2, "telnet: SE without an SB\n");
137 for(o = opt; o <= &opt[Extend]; o++)
153 DPRINT(2, "will %d\n", c);
156 send3(Bfildes(bp), Iac, Dont, c);
160 send3(Bfildes(bp), Iac, Dont, c);
161 else if(o->remote == 0)
162 rv |= send3(Bfildes(bp), Iac, Do, c);
165 rv |= (*o->change)(bp, Will);
181 DPRINT(2, "wont %d\n", c);
187 rv |= (*o->change)(bp, Wont);
188 rv |= send3(Bfildes(bp), Iac, Dont, c);
204 DPRINT(2, "do %d\n", c);
206 if(o == 0 || o->noway){
207 send3(Bfildes(bp), Iac, Wont, c);
214 rv |= (*o->change)(bp, Do);
215 rv |= send3(Bfildes(bp), Iac, Will, c);
231 DPRINT(2, "dont %d\n", c);
240 rv |= (*o->change)(bp, Dont);
241 rv |= send3(Bfildes(bp), Iac, Wont, c);
247 /* read in a subnegotiation message and pass it to a routine for that option */
263 if(p < &subneg[sizeof(subneg)])
268 if(p < &subneg[sizeof(subneg)])
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)
277 return (*o->sub)(bp, subneg+1, p - subneg - 1);
281 sendd(int c0, int c1)
300 DPRINT(2, "r %s %d\n", t, c1);
304 send2(int f, int c0, int c1)
310 return iwrite(f, buf, 2) == 2 ? 0 : -1;
314 send3(int f, int c0, int c1, int c2)
322 return iwrite(f, buf, 3) == 3 ? 0 : -1;
326 sendnote(int pid, char *msg)
331 sprint(name, "/proc/%d/note", pid);
332 fd = open(name, OWRITE);
335 if(write(fd, msg, strlen(msg))!=strlen(msg))
341 fatal(char *fmt, void *a0, void *a1)
345 sprint(buf, fmt, a0, a1);
346 fprint(2, "%s: %s\n", argv0, buf);
353 static char err[ERRMAX];
355 errstr(err, sizeof err);
362 return strcmp(syserr(), "interrupted") == 0;
366 iread(int f, void *a, int n)
372 if(m >= 0 || !wasintr())
379 iwrite(int f, void *a, int n)
384 if(m < 0 && wasintr())