|
|
1.1 root 1: /*
2: * Copyright (c) 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)slc.c 5.4 (Berkeley) 6/28/90";
22: #endif /* not lint */
23:
24: #include "telnetd.h"
25:
26: #ifdef LINEMODE
27: /*
28: * local varibles
29: */
30: static unsigned char *def_slcbuf = (unsigned char *)0;
31: static int def_slclen = 0;
32: static int slcchange; /* change to slc is requested */
33: static unsigned char *slcptr; /* pointer into slc buffer */
34: static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */
35:
36: /*
37: * send_slc
38: *
39: * Write out the current special characters to the client.
40: */
41: send_slc()
42: {
43: register int i;
44:
45: /*
46: * Send out list of triplets of special characters
47: * to client. We only send info on the characters
48: * that are currently supported.
49: */
50: for (i = 1; i <= NSLC; i++) {
51: if ((slctab[i].current.flag & SLC_LEVELBITS) != SLC_NOSUPPORT) {
52: add_slc((unsigned char)i, slctab[i].current.flag,
53: slctab[i].current.val);
54: }
55: }
56:
57: } /* end of send_slc */
58:
59: /*
60: * default_slc
61: *
62: * Set pty special characters to all the defaults.
63: */
64: default_slc()
65: {
66: register int i;
67:
68: for (i = 1; i <= NSLC; i++) {
69: slctab[i].current.flag = slctab[i].defset.flag;
70: slctab[i].current.val = slctab[i].defset.val;
71: if (slctab[i].sptr) {
72: *(slctab[i].sptr) = slctab[i].defset.val;
73: }
74: }
75: slcchange = 1;
76:
77: } /* end of default_slc */
78: #endif LINEMODE
79:
80: /*
81: * get_slc_defaults
82: *
83: * Initialize the slc mapping table.
84: */
85: get_slc_defaults()
86: {
87: register int i;
88:
89: init_termbuf();
90:
91: for (i = 1; i <= NSLC; i++) {
92: slctab[i].defset.flag =
93: spcset(i, &slctab[i].defset.val, &slctab[i].sptr);
94: slctab[i].current.flag = SLC_NOSUPPORT;
95: slctab[i].current.val = 0;
96: }
97:
98: } /* end of get_slc_defaults */
99:
100: #ifdef LINEMODE
101: /*
102: * add_slc
103: *
104: * Add an slc triplet to the slc buffer.
105: */
106: add_slc(func, flag, val)
107: register unsigned char func, flag;
108: cc_t val;
109: {
110:
111: if ((*slcptr++ = func) == 0xff)
112: *slcptr++ = 0xff;
113:
114: if ((*slcptr++ = flag) == 0xff)
115: *slcptr++ = 0xff;
116:
117: if ((*slcptr++ = (unsigned char)val) == 0xff)
118: *slcptr++ = 0xff;
119:
120: } /* end of add_slc */
121:
122: /*
123: * start_slc
124: *
125: * Get ready to process incoming slc's and respond to them.
126: *
127: * The parameter getit is non-zero if it is necessary to grab a copy
128: * of the terminal control structures.
129: */
130: start_slc(getit)
131: register int getit;
132: {
133:
134: slcchange = 0;
135: if (getit)
136: init_termbuf();
137: (void) sprintf(slcbuf, "%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC);
138: slcptr = slcbuf + 4;
139:
140: } /* end of start_slc */
141:
142: /*
143: * end_slc
144: *
145: * Finish up the slc negotiation. If something to send, then send it.
146: */
147: end_slc(bufp)
148: register unsigned char **bufp;
149: {
150: register int len;
151: void netflush();
152:
153: /*
154: * If a change has occured, store the new terminal control
155: * structures back to the terminal driver.
156: */
157: if (slcchange) {
158: set_termbuf();
159: }
160:
161: /*
162: * If the pty state has not yet been fully processed and there is a
163: * deferred slc request from the client, then do not send any
164: * sort of slc negotiation now. We will respond to the client's
165: * request very soon.
166: */
167: if (def_slcbuf && (terminit() == 0)) {
168: return;
169: }
170:
171: if (slcptr > (slcbuf + 4)) {
172: if (bufp) {
173: *bufp = &slcbuf[4];
174: return(slcptr - slcbuf - 4);
175: } else {
176: (void) sprintf(slcptr, "%c%c", IAC, SE);
177: slcptr += 2;
178: len = slcptr - slcbuf;
179: writenet(slcbuf, len);
180: netflush(); /* force it out immediately */
181: }
182: }
183:
184: } /* end of end_slc */
185:
186: /*
187: * process_slc
188: *
189: * Figure out what to do about the client's slc
190: */
191: process_slc(func, flag, val)
192: register unsigned char func, flag;
193: cc_t val;
194: {
195: register int hislevel, mylevel, ack;
196:
197: /*
198: * Ensure that we know something about this function
199: */
200: if (func > NSLC) {
201: add_slc(func, SLC_NOSUPPORT, 0);
202: return;
203: }
204:
205: /*
206: * Process the special case requests of 0 SLC_DEFAULT 0
207: * and 0 SLC_VARIABLE 0. Be a little forgiving here, don't
208: * worry about whether the value is actually 0 or not.
209: */
210: if (func == 0) {
211: if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) {
212: default_slc();
213: }
214: if (flag == SLC_DEFAULT || flag == SLC_VARIABLE) {
215: send_slc();
216: }
217: return;
218: }
219:
220: /*
221: * Appears to be a function that we know something about. So
222: * get on with it and see what we know.
223: */
224:
225: hislevel = flag & SLC_LEVELBITS;
226: mylevel = slctab[func].current.flag & SLC_LEVELBITS;
227: ack = flag & SLC_ACK;
228: /*
229: * ignore the command if:
230: * the function value and level are the same as what we already have;
231: * or the level is the same and the ack bit is set
232: */
233: if (hislevel == mylevel && (val == slctab[func].current.val || ack)) {
234: return;
235: } else {
236: change_slc(func, flag, val);
237: }
238:
239: } /* end of process_slc */
240:
241: /*
242: * change_slc
243: *
244: * Process a request to change one of our special characters.
245: * Compare client's request with what we are capable of supporting.
246: */
247: change_slc(func, flag, val)
248: register unsigned char func, flag;
249: cc_t val;
250: {
251: register int hislevel, mylevel;
252:
253: hislevel = flag & SLC_LEVELBITS;
254: mylevel = slctab[func].defset.flag & SLC_LEVELBITS;
255: /*
256: * If client is setting a function to NOSUPPORT
257: * or DEFAULT, then we can easily and directly
258: * accomodate the request.
259: */
260: if (hislevel == SLC_NOSUPPORT) {
261: slctab[func].current.flag = flag;
262: slctab[func].current.val = val;
263: flag |= SLC_ACK;
264: add_slc(func, flag, val);
265: return;
266: }
267: if (hislevel == SLC_DEFAULT) {
268: /*
269: * Special case here. If client tells us to use
270: * the default on a function we don't support, then
271: * return NOSUPPORT instead of what we may have as a
272: * default level of DEFAULT.
273: */
274: if (mylevel == SLC_DEFAULT) {
275: slctab[func].current.flag = SLC_NOSUPPORT;
276: } else {
277: slctab[func].current.flag = slctab[func].defset.flag;
278: }
279: slctab[func].current.val = slctab[func].defset.val;
280: add_slc(func, slctab[func].current.flag,
281: slctab[func].current.val);
282: return;
283: }
284:
285: /*
286: * Client wants us to change to a new value or he
287: * is telling us that he can't change to our value.
288: * Some of the slc's we support and can change,
289: * some we do support but can't change,
290: * and others we don't support at all.
291: * If we can change it then we have a pointer to
292: * the place to put the new value, so change it,
293: * otherwise, continue the negotiation.
294: */
295: if (slctab[func].sptr) {
296: /*
297: * We can change this one.
298: */
299: slctab[func].current.val = val;
300: *(slctab[func].sptr) = val;
301: slctab[func].current.flag = flag;
302: flag |= SLC_ACK;
303: slcchange = 1;
304: add_slc(func, flag, val);
305: } else {
306: /*
307: * It is not possible for us to support this
308: * request as he asks.
309: *
310: * If our level is DEFAULT, then just ack whatever was
311: * sent.
312: *
313: * If he can't change and we can't change,
314: * then degenerate to NOSUPPORT.
315: *
316: * Otherwise we send our level back to him, (CANTCHANGE
317: * or NOSUPPORT) and if CANTCHANGE, send
318: * our value as well.
319: */
320: if (mylevel == SLC_DEFAULT) {
321: slctab[func].current.flag = flag;
322: slctab[func].current.val = val;
323: flag |= SLC_ACK;
324: } else if (hislevel == SLC_CANTCHANGE &&
325: mylevel == SLC_CANTCHANGE) {
326: flag &= ~SLC_LEVELBITS;
327: flag |= SLC_NOSUPPORT;
328: slctab[func].current.flag = flag;
329: } else {
330: flag &= ~SLC_LEVELBITS;
331: flag |= mylevel;
332: slctab[func].current.flag = flag;
333: if (mylevel == SLC_CANTCHANGE) {
334: slctab[func].current.val =
335: slctab[func].defset.val;
336: val = slctab[func].current.val;
337: }
338:
339: }
340: add_slc(func, flag, val);
341: }
342:
343: } /* end of change_slc */
344:
345: #if defined(USE_TERMIO) && defined(SYSV_TERMIO)
346: cc_t oldeofc = '\004';
347: #endif
348:
349: /*
350: * check_slc
351: *
352: * Check the special characters in use and notify the client if any have
353: * changed. Only those characters that are capable of being changed are
354: * likely to have changed. If a local change occurs, kick the support level
355: * and flags up to the defaults.
356: */
357: check_slc()
358: {
359: register int i;
360:
361: for (i = 1; i <= NSLC; i++) {
362: #if defined(USE_TERMIO) && defined(SYSV_TERMIO)
363: /*
364: * In a perfect world this would be a neat little
365: * function. But in this world, we should not notify
366: * client of changes to the VEOF char when
367: * ICANON is off, because it is not representing
368: * a special character.
369: */
370: if (i == SLC_EOF) {
371: if (!tty_isediting())
372: continue;
373: else if (slctab[i].sptr)
374: oldeofc = *(slctab[i].sptr);
375: }
376: #endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */
377: if (slctab[i].sptr &&
378: (*(slctab[i].sptr) != slctab[i].current.val)) {
379: slctab[i].current.val = *(slctab[i].sptr);
380: slctab[i].current.flag = slctab[i].defset.flag;
381: add_slc((unsigned char)i, slctab[i].current.flag,
382: slctab[i].current.val);
383: }
384: }
385:
386: } /* check_slc */
387:
388: /*
389: * do_opt_slc
390: *
391: * Process an slc option buffer. Defer processing of incoming slc's
392: * until after the terminal state has been processed. Save the first slc
393: * request that comes along, but discard all others.
394: *
395: * ptr points to the beginning of the buffer, len is the length.
396: */
397: do_opt_slc(ptr, len)
398: register char *ptr;
399: register int len;
400: {
401: register unsigned char func, flag;
402: cc_t val;
403: register char *end = (char *)(ptr + len);
404: char *malloc();
405:
406: if (terminit()) { /* go ahead */
407: while (ptr < end) {
408: func = *ptr++;
409: if (ptr >= end) break;
410: flag = *ptr++;
411: if (ptr >= end) break;
412: val = (cc_t)*ptr++;
413:
414: process_slc(func, flag, val);
415:
416: }
417: } else {
418: /*
419: * save this slc buffer if it is the first, otherwise dump
420: * it.
421: */
422: if (def_slcbuf == (unsigned char *)0) {
423: def_slclen = len;
424: def_slcbuf = (unsigned char *)malloc((unsigned)len);
425: if (def_slcbuf == (unsigned char *)0)
426: return; /* too bad */
427: bcopy(ptr, def_slcbuf, len);
428: }
429: }
430:
431: } /* end of do_opt_slc */
432:
433: /*
434: * deferslc
435: *
436: * Do slc stuff that was deferred.
437: */
438: deferslc()
439: {
440: if (def_slcbuf) {
441: start_slc(1);
442: do_opt_slc(def_slcbuf, def_slclen);
443: end_slc(0);
444: free(def_slcbuf);
445: def_slcbuf = (unsigned char *)0;
446: def_slclen = 0;
447: }
448:
449: } /* end of deferslc */
450:
451: #endif /* LINEMODE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.