|
|
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.