| 106 | | suboption(noit_console_closure_t ncct); |
|---|
| | 136 | send_slc(noit_console_closure_t ncct) |
|---|
| | 137 | { |
|---|
| | 138 | int i; |
|---|
| | 139 | |
|---|
| | 140 | /* |
|---|
| | 141 | * Send out list of triplets of special characters |
|---|
| | 142 | * to client. We only send info on the characters |
|---|
| | 143 | * that are currently supported. |
|---|
| | 144 | */ |
|---|
| | 145 | for (i = 1; i <= NSLC; i++) { |
|---|
| | 146 | if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT) |
|---|
| | 147 | continue; |
|---|
| | 148 | add_slc(ncct, (unsigned char)i, slctab[i].current.flag, |
|---|
| | 149 | slctab[i].current.val); |
|---|
| | 150 | } |
|---|
| | 151 | |
|---|
| | 152 | } /* end of send_slc */ |
|---|
| | 153 | |
|---|
| | 154 | /* |
|---|
| | 155 | * default_slc |
|---|
| | 156 | * |
|---|
| | 157 | * Set pty special characters to all the defaults. |
|---|
| | 158 | */ |
|---|
| | 159 | static void |
|---|
| | 160 | default_slc(noit_console_closure_t ncct) |
|---|
| | 161 | { |
|---|
| | 162 | int i; |
|---|
| | 163 | |
|---|
| | 164 | for (i = 1; i <= NSLC; i++) { |
|---|
| | 165 | slctab[i].current.val = slctab[i].defset.val; |
|---|
| | 166 | if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE)) |
|---|
| | 167 | slctab[i].current.flag = SLC_NOSUPPORT; |
|---|
| | 168 | else |
|---|
| | 169 | slctab[i].current.flag = slctab[i].defset.flag; |
|---|
| | 170 | if (slctab[i].sptr) { |
|---|
| | 171 | *(slctab[i].sptr) = slctab[i].defset.val; |
|---|
| | 172 | } |
|---|
| | 173 | } |
|---|
| | 174 | slcchange = 1; |
|---|
| | 175 | |
|---|
| | 176 | } /* end of default_slc */ |
|---|
| | 177 | #endif /* LINEMODE */ |
|---|
| | 178 | |
|---|
| | 179 | /* |
|---|
| | 180 | * get_slc_defaults |
|---|
| | 181 | * |
|---|
| | 182 | * Initialize the slc mapping table. |
|---|
| | 183 | */ |
|---|
| | 184 | static void |
|---|
| | 185 | get_slc_defaults(noit_console_closure_t ncct) |
|---|
| | 186 | { |
|---|
| | 187 | int i; |
|---|
| | 188 | |
|---|
| | 189 | init_termbuf(ncct); |
|---|
| | 190 | |
|---|
| | 191 | for (i = 1; i <= NSLC; i++) { |
|---|
| | 192 | slctab[i].defset.flag = |
|---|
| | 193 | spcset(ncct, i, &slctab[i].defset.val, &slctab[i].sptr); |
|---|
| | 194 | slctab[i].current.flag = SLC_NOSUPPORT; |
|---|
| | 195 | slctab[i].current.val = 0; |
|---|
| | 196 | } |
|---|
| | 197 | |
|---|
| | 198 | } /* end of get_slc_defaults */ |
|---|
| | 199 | |
|---|
| | 200 | #ifdef LINEMODE |
|---|
| | 201 | /* |
|---|
| | 202 | * add_slc |
|---|
| | 203 | * |
|---|
| | 204 | * Add an slc triplet to the slc buffer. |
|---|
| | 205 | */ |
|---|
| | 206 | static void |
|---|
| | 207 | add_slc(noit_console_closure_t ncct, char func, char flag, cc_t val) |
|---|
| | 208 | { |
|---|
| | 209 | |
|---|
| | 210 | if ((*slcptr++ = (unsigned char)func) == 0xff) |
|---|
| | 211 | *slcptr++ = 0xff; |
|---|
| | 212 | |
|---|
| | 213 | if ((*slcptr++ = (unsigned char)flag) == 0xff) |
|---|
| | 214 | *slcptr++ = 0xff; |
|---|
| | 215 | |
|---|
| | 216 | if ((*slcptr++ = (unsigned char)val) == 0xff) |
|---|
| | 217 | *slcptr++ = 0xff; |
|---|
| | 218 | |
|---|
| | 219 | } /* end of add_slc */ |
|---|
| | 220 | |
|---|
| | 221 | /* |
|---|
| | 222 | * start_slc |
|---|
| | 223 | * |
|---|
| | 224 | * Get ready to process incoming slc's and respond to them. |
|---|
| | 225 | * |
|---|
| | 226 | * The parameter getit is non-zero if it is necessary to grab a copy |
|---|
| | 227 | * of the terminal control structures. |
|---|
| | 228 | */ |
|---|
| | 229 | static void |
|---|
| | 230 | start_slc(noit_console_closure_t ncct, int getit) |
|---|
| | 231 | { |
|---|
| | 232 | |
|---|
| | 233 | slcchange = 0; |
|---|
| | 234 | if (getit) |
|---|
| | 235 | init_termbuf(ncct); |
|---|
| | 236 | (void) sprintf((char *)slcbuf, "%c%c%c%c", |
|---|
| | 237 | IAC, SB, TELOPT_LINEMODE, LM_SLC); |
|---|
| | 238 | slcptr = slcbuf + 4; |
|---|
| | 239 | |
|---|
| | 240 | } /* end of start_slc */ |
|---|
| | 241 | |
|---|
| | 242 | /* |
|---|
| | 243 | * end_slc |
|---|
| | 244 | * |
|---|
| | 245 | * Finish up the slc negotiation. If something to send, then send it. |
|---|
| | 246 | */ |
|---|
| | 247 | int |
|---|
| | 248 | end_slc(noit_console_closure_t ncct, unsigned char **bufp) |
|---|
| | 249 | { |
|---|
| | 250 | int len; |
|---|
| | 251 | |
|---|
| | 252 | /* |
|---|
| | 253 | * If a change has occured, store the new terminal control |
|---|
| | 254 | * structures back to the terminal driver. |
|---|
| | 255 | */ |
|---|
| | 256 | if (slcchange) { |
|---|
| | 257 | set_termbuf(ncct); |
|---|
| | 258 | } |
|---|
| | 259 | |
|---|
| | 260 | /* |
|---|
| | 261 | * If the pty state has not yet been fully processed and there is a |
|---|
| | 262 | * deferred slc request from the client, then do not send any |
|---|
| | 263 | * sort of slc negotiation now. We will respond to the client's |
|---|
| | 264 | * request very soon. |
|---|
| | 265 | */ |
|---|
| | 266 | if (def_slcbuf && (_terminit == 0)) { |
|---|
| | 267 | return(0); |
|---|
| | 268 | } |
|---|
| | 269 | |
|---|
| | 270 | if (slcptr > (slcbuf + 4)) { |
|---|
| | 271 | if (bufp) { |
|---|
| | 272 | *bufp = &slcbuf[4]; |
|---|
| | 273 | return(slcptr - slcbuf - 4); |
|---|
| | 274 | } else { |
|---|
| | 275 | (void) sprintf((char *)slcptr, "%c%c", IAC, SE); |
|---|
| | 276 | slcptr += 2; |
|---|
| | 277 | len = slcptr - slcbuf; |
|---|
| | 278 | nc_write(ncct, slcbuf, len); |
|---|
| | 279 | netflush(ncct); /* force it out immediately */ |
|---|
| | 280 | } |
|---|
| | 281 | } |
|---|
| | 282 | return (0); |
|---|
| | 283 | |
|---|
| | 284 | } /* end of end_slc */ |
|---|
| | 285 | |
|---|
| | 286 | /* |
|---|
| | 287 | * process_slc |
|---|
| | 288 | * |
|---|
| | 289 | * Figure out what to do about the client's slc |
|---|
| | 290 | */ |
|---|
| | 291 | static void |
|---|
| | 292 | process_slc(noit_console_closure_t ncct, unsigned char func, unsigned char flag, cc_t val) |
|---|
| | 293 | { |
|---|
| | 294 | int hislevel, mylevel, ack; |
|---|
| | 295 | |
|---|
| | 296 | /* |
|---|
| | 297 | * Ensure that we know something about this function |
|---|
| | 298 | */ |
|---|
| | 299 | if (func > NSLC) { |
|---|
| | 300 | add_slc(ncct, func, SLC_NOSUPPORT, 0); |
|---|
| | 301 | return; |
|---|
| | 302 | } |
|---|
| | 303 | |
|---|
| | 304 | /* |
|---|
| | 305 | * Process the special case requests of 0 SLC_DEFAULT 0 |
|---|
| | 306 | * and 0 SLC_VARIABLE 0. Be a little forgiving here, don't |
|---|
| | 307 | * worry about whether the value is actually 0 or not. |
|---|
| | 308 | */ |
|---|
| | 309 | if (func == 0) { |
|---|
| | 310 | if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) { |
|---|
| | 311 | default_slc(ncct); |
|---|
| | 312 | send_slc(ncct); |
|---|
| | 313 | } else if (flag == SLC_VARIABLE) { |
|---|
| | 314 | send_slc(ncct); |
|---|
| | 315 | } |
|---|
| | 316 | return; |
|---|
| | 317 | } |
|---|
| | 318 | |
|---|
| | 319 | /* |
|---|
| | 320 | * Appears to be a function that we know something about. So |
|---|
| | 321 | * get on with it and see what we know. |
|---|
| | 322 | */ |
|---|
| | 323 | |
|---|
| | 324 | hislevel = flag & SLC_LEVELBITS; |
|---|
| | 325 | mylevel = slctab[func].current.flag & SLC_LEVELBITS; |
|---|
| | 326 | ack = flag & SLC_ACK; |
|---|
| | 327 | /* |
|---|
| | 328 | * ignore the command if: |
|---|
| | 329 | * the function value and level are the same as what we already have; |
|---|
| | 330 | * or the level is the same and the ack bit is set |
|---|
| | 331 | */ |
|---|
| | 332 | if (hislevel == mylevel && (val == slctab[func].current.val || ack)) { |
|---|
| | 333 | return; |
|---|
| | 334 | } else if (ack) { |
|---|
| | 335 | /* |
|---|
| | 336 | * If we get here, we got an ack, but the levels don't match. |
|---|
| | 337 | * This shouldn't happen. If it does, it is probably because |
|---|
| | 338 | * we have sent two requests to set a variable without getting |
|---|
| | 339 | * a response between them, and this is the first response. |
|---|
| | 340 | * So, ignore it, and wait for the next response. |
|---|
| | 341 | */ |
|---|
| | 342 | return; |
|---|
| | 343 | } else { |
|---|
| | 344 | change_slc(ncct, func, flag, val); |
|---|
| | 345 | } |
|---|
| | 346 | |
|---|
| | 347 | } /* end of process_slc */ |
|---|
| | 348 | |
|---|
| | 349 | /* |
|---|
| | 350 | * change_slc |
|---|
| | 351 | * |
|---|
| | 352 | * Process a request to change one of our special characters. |
|---|
| | 353 | * Compare client's request with what we are capable of supporting. |
|---|
| | 354 | */ |
|---|
| | 355 | static void |
|---|
| | 356 | change_slc(noit_console_closure_t ncct, char func, char flag, cc_t val) |
|---|
| | 357 | { |
|---|
| | 358 | int hislevel, mylevel; |
|---|
| | 359 | |
|---|
| | 360 | hislevel = flag & SLC_LEVELBITS; |
|---|
| | 361 | mylevel = slctab[(int)func].defset.flag & SLC_LEVELBITS; |
|---|
| | 362 | /* |
|---|
| | 363 | * If client is setting a function to NOSUPPORT |
|---|
| | 364 | * or DEFAULT, then we can easily and directly |
|---|
| | 365 | * accomodate the request. |
|---|
| | 366 | */ |
|---|
| | 367 | if (hislevel == SLC_NOSUPPORT) { |
|---|
| | 368 | slctab[(int)func].current.flag = flag; |
|---|
| | 369 | slctab[(int)func].current.val = (cc_t)_POSIX_VDISABLE; |
|---|
| | 370 | flag |= SLC_ACK; |
|---|
| | 371 | add_slc(ncct, func, flag, val); |
|---|
| | 372 | return; |
|---|
| | 373 | } |
|---|
| | 374 | if (hislevel == SLC_DEFAULT) { |
|---|
| | 375 | /* |
|---|
| | 376 | * Special case here. If client tells us to use |
|---|
| | 377 | * the default on a function we don't support, then |
|---|
| | 378 | * return NOSUPPORT instead of what we may have as a |
|---|
| | 379 | * default level of DEFAULT. |
|---|
| | 380 | */ |
|---|
| | 381 | if (mylevel == SLC_DEFAULT) { |
|---|
| | 382 | slctab[(int)func].current.flag = SLC_NOSUPPORT; |
|---|
| | 383 | } else { |
|---|
| | 384 | slctab[(int)func].current.flag = slctab[(int)func].defset.flag; |
|---|
| | 385 | } |
|---|
| | 386 | slctab[(int)func].current.val = slctab[(int)func].defset.val; |
|---|
| | 387 | add_slc(ncct, func, slctab[(int)func].current.flag, |
|---|
| | 388 | slctab[(int)func].current.val); |
|---|
| | 389 | return; |
|---|
| | 390 | } |
|---|
| | 391 | |
|---|
| | 392 | /* |
|---|
| | 393 | * Client wants us to change to a new value or he |
|---|
| | 394 | * is telling us that he can't change to our value. |
|---|
| | 395 | * Some of the slc's we support and can change, |
|---|
| | 396 | * some we do support but can't change, |
|---|
| | 397 | * and others we don't support at all. |
|---|
| | 398 | * If we can change it then we have a pointer to |
|---|
| | 399 | * the place to put the new value, so change it, |
|---|
| | 400 | * otherwise, continue the negotiation. |
|---|
| | 401 | */ |
|---|
| | 402 | if (slctab[(int)func].sptr) { |
|---|
| | 403 | /* |
|---|
| | 404 | * We can change this one. |
|---|
| | 405 | */ |
|---|
| | 406 | slctab[(int)func].current.val = val; |
|---|
| | 407 | *(slctab[(int)func].sptr) = val; |
|---|
| | 408 | slctab[(int)func].current.flag = flag; |
|---|
| | 409 | flag |= SLC_ACK; |
|---|
| | 410 | slcchange = 1; |
|---|
| | 411 | add_slc(ncct, func, flag, val); |
|---|
| | 412 | } else { |
|---|
| | 413 | /* |
|---|
| | 414 | * It is not possible for us to support this |
|---|
| | 415 | * request as he asks. |
|---|
| | 416 | * |
|---|
| | 417 | * If our level is DEFAULT, then just ack whatever was |
|---|
| | 418 | * sent. |
|---|
| | 419 | * |
|---|
| | 420 | * If he can't change and we can't change, |
|---|
| | 421 | * then degenerate to NOSUPPORT. |
|---|
| | 422 | * |
|---|
| | 423 | * Otherwise we send our level back to him, (CANTCHANGE |
|---|
| | 424 | * or NOSUPPORT) and if CANTCHANGE, send |
|---|
| | 425 | * our value as well. |
|---|
| | 426 | */ |
|---|
| | 427 | if (mylevel == SLC_DEFAULT) { |
|---|
| | 428 | slctab[(int)func].current.flag = flag; |
|---|
| | 429 | slctab[(int)func].current.val = val; |
|---|
| | 430 | flag |= SLC_ACK; |
|---|
| | 431 | } else if (hislevel == SLC_CANTCHANGE && |
|---|
| | 432 | mylevel == SLC_CANTCHANGE) { |
|---|
| | 433 | flag &= ~SLC_LEVELBITS; |
|---|
| | 434 | flag |= SLC_NOSUPPORT; |
|---|
| | 435 | slctab[(int)func].current.flag = flag; |
|---|
| | 436 | } else { |
|---|
| | 437 | flag &= ~SLC_LEVELBITS; |
|---|
| | 438 | flag |= mylevel; |
|---|
| | 439 | slctab[(int)func].current.flag = flag; |
|---|
| | 440 | if (mylevel == SLC_CANTCHANGE) { |
|---|
| | 441 | slctab[(int)func].current.val = |
|---|
| | 442 | slctab[(int)func].defset.val; |
|---|
| | 443 | val = slctab[(int)func].current.val; |
|---|
| | 444 | } |
|---|
| | 445 | } |
|---|
| | 446 | add_slc(ncct, func, flag, val); |
|---|
| | 447 | } |
|---|
| | 448 | |
|---|
| | 449 | } /* end of change_slc */ |
|---|
| | 450 | |
|---|
| | 451 | #if defined(USE_TERMIO) && (VEOF == VMIN) |
|---|
| | 452 | cc_t oldeofc = '\004'; |
|---|
| | 453 | #endif |
|---|
| | 454 | |
|---|
| | 455 | /* |
|---|
| | 456 | * check_slc |
|---|
| | 457 | * |
|---|
| | 458 | * Check the special characters in use and notify the client if any have |
|---|
| | 459 | * changed. Only those characters that are capable of being changed are |
|---|
| | 460 | * likely to have changed. If a local change occurs, kick the support level |
|---|
| | 461 | * and flags up to the defaults. |
|---|
| | 462 | */ |
|---|
| | 463 | static void |
|---|
| | 464 | check_slc(noit_console_closure_t ncct) |
|---|
| | 465 | { |
|---|
| | 466 | int i; |
|---|
| | 467 | |
|---|
| | 468 | for (i = 1; i <= NSLC; i++) { |
|---|
| | 469 | #if defined(USE_TERMIO) && (VEOF == VMIN) |
|---|
| | 470 | /* |
|---|
| | 471 | * In a perfect world this would be a neat little |
|---|
| | 472 | * function. But in this world, we should not notify |
|---|
| | 473 | * client of changes to the VEOF char when |
|---|
| | 474 | * ICANON is off, because it is not representing |
|---|
| | 475 | * a special character. |
|---|
| | 476 | */ |
|---|
| | 477 | if (i == SLC_EOF) { |
|---|
| | 478 | if (!noit_console_telnet_tty_isediting(ncct)) |
|---|
| | 479 | continue; |
|---|
| | 480 | else if (slctab[i].sptr) |
|---|
| | 481 | oldeofc = *(slctab[i].sptr); |
|---|
| | 482 | } |
|---|
| | 483 | #endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */ |
|---|
| | 484 | if (slctab[i].sptr && |
|---|
| | 485 | (*(slctab[i].sptr) != slctab[i].current.val)) { |
|---|
| | 486 | slctab[i].current.val = *(slctab[i].sptr); |
|---|
| | 487 | if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE) |
|---|
| | 488 | slctab[i].current.flag = SLC_NOSUPPORT; |
|---|
| | 489 | else |
|---|
| | 490 | slctab[i].current.flag = slctab[i].defset.flag; |
|---|
| | 491 | add_slc(ncct, (unsigned char)i, slctab[i].current.flag, |
|---|
| | 492 | slctab[i].current.val); |
|---|
| | 493 | } |
|---|
| | 494 | } |
|---|
| | 495 | } /* check_slc */ |
|---|
| | 496 | |
|---|
| | 497 | /* |
|---|
| | 498 | * do_opt_slc |
|---|
| | 499 | * |
|---|
| | 500 | * Process an slc option buffer. Defer processing of incoming slc's |
|---|
| | 501 | * until after the terminal state has been processed. Save the first slc |
|---|
| | 502 | * request that comes along, but discard all others. |
|---|
| | 503 | * |
|---|
| | 504 | * ptr points to the beginning of the buffer, len is the length. |
|---|
| | 505 | */ |
|---|
| | 506 | static void |
|---|
| | 507 | do_opt_slc(noit_console_closure_t ncct, unsigned char *ptr, int len) |
|---|
| | 508 | { |
|---|
| | 509 | unsigned char func, flag; |
|---|
| | 510 | cc_t val; |
|---|
| | 511 | unsigned char *end = ptr + len; |
|---|
| | 512 | |
|---|
| | 513 | if (_terminit) { /* go ahead */ |
|---|
| | 514 | while (ptr < end) { |
|---|
| | 515 | func = *ptr++; |
|---|
| | 516 | if (ptr >= end) break; |
|---|
| | 517 | flag = *ptr++; |
|---|
| | 518 | if (ptr >= end) break; |
|---|
| | 519 | val = (cc_t)*ptr++; |
|---|
| | 520 | |
|---|
| | 521 | process_slc(ncct, func, flag, val); |
|---|
| | 522 | |
|---|
| | 523 | } |
|---|
| | 524 | } else { |
|---|
| | 525 | /* |
|---|
| | 526 | * save this slc buffer if it is the first, otherwise dump |
|---|
| | 527 | * it. |
|---|
| | 528 | */ |
|---|
| | 529 | if (def_slcbuf == (unsigned char *)0) { |
|---|
| | 530 | def_slclen = len; |
|---|
| | 531 | def_slcbuf = (unsigned char *)malloc((unsigned)len); |
|---|
| | 532 | if (def_slcbuf == (unsigned char *)0) |
|---|
| | 533 | return; /* too bad */ |
|---|
| | 534 | memmove(def_slcbuf, ptr, len); |
|---|
| | 535 | } |
|---|
| | 536 | } |
|---|
| | 537 | |
|---|
| | 538 | } /* end of do_opt_slc */ |
|---|
| | 539 | |
|---|
| | 540 | /* |
|---|
| | 541 | * deferslc |
|---|
| | 542 | * |
|---|
| | 543 | * Do slc stuff that was deferred. |
|---|
| | 544 | */ |
|---|
| | 545 | static void |
|---|
| | 546 | deferslc(noit_console_closure_t ncct) |
|---|
| | 547 | { |
|---|
| | 548 | if (def_slcbuf) { |
|---|
| | 549 | start_slc(ncct, 1); |
|---|
| | 550 | do_opt_slc(ncct, def_slcbuf, def_slclen); |
|---|
| | 551 | (void) end_slc(ncct, 0); |
|---|
| | 552 | free(def_slcbuf); |
|---|
| | 553 | def_slcbuf = (unsigned char *)0; |
|---|
| | 554 | def_slclen = 0; |
|---|
| | 555 | } |
|---|
| | 556 | |
|---|
| | 557 | } /* end of deferslc */ |
|---|
| | 558 | #endif |
|---|
| | 559 | |
|---|
| | 560 | #ifdef LINEMODE |
|---|
| | 561 | /* |
|---|
| | 562 | * tty_flowmode() Find out if flow control is enabled or disabled. |
|---|
| | 563 | * tty_linemode() Find out if linemode (external processing) is enabled. |
|---|
| | 564 | * tty_setlinemod(on) Turn on/off linemode. |
|---|
| | 565 | * tty_isecho() Find out if echoing is turned on. |
|---|
| | 566 | * tty_setecho(on) Enable/disable character echoing. |
|---|
| | 567 | * tty_israw() Find out if terminal is in RAW mode. |
|---|
| | 568 | * tty_binaryin(on) Turn on/off BINARY on input. |
|---|
| | 569 | * tty_binaryout(on) Turn on/off BINARY on output. |
|---|
| | 570 | * tty_isediting() Find out if line editing is enabled. |
|---|
| | 571 | * tty_istrapsig() Find out if signal trapping is enabled. |
|---|
| | 572 | * tty_setedit(on) Turn on/off line editing. |
|---|
| | 573 | * tty_setsig(on) Turn on/off signal trapping. |
|---|
| | 574 | * tty_issofttab() Find out if tab expansion is enabled. |
|---|
| | 575 | * tty_setsofttab(on) Turn on/off soft tab expansion. |
|---|
| | 576 | * tty_islitecho() Find out if typed control chars are echoed literally |
|---|
| | 577 | * tty_setlitecho() Turn on/off literal echo of control chars |
|---|
| | 578 | * tty_tspeed(val) Set transmit speed to val. |
|---|
| | 579 | * tty_rspeed(val) Set receive speed to val. |
|---|
| | 580 | */ |
|---|
| | 581 | |
|---|
| | 582 | |
|---|
| | 583 | int |
|---|
| | 584 | noit_console_telnet_tty_linemode(noit_console_closure_t ncct) |
|---|
| | 585 | { |
|---|
| | 586 | #ifndef USE_TERMIO |
|---|
| | 587 | #ifdef TS_EXTPROC |
|---|
| | 588 | return(termbuf.state & TS_EXTPROC); |
|---|
| | 589 | #else |
|---|
| | 590 | return 0; |
|---|
| | 591 | #endif |
|---|
| | 592 | #else |
|---|
| | 593 | return(termbuf.c_lflag & EXTPROC); |
|---|
| | 594 | #endif |
|---|
| | 595 | } |
|---|
| | 596 | |
|---|
| | 597 | void |
|---|
| | 598 | noit_console_telnet_tty_setlinemode(noit_console_closure_t ncct, int on) |
|---|
| | 599 | { |
|---|
| | 600 | #ifdef TIOCEXT |
|---|
| | 601 | set_termbuf(ncct); |
|---|
| | 602 | (void) ioctl(pty, TIOCEXT, (char *)&on); |
|---|
| | 603 | init_termbuf(ncct); |
|---|
| | 604 | #else /* !TIOCEXT */ |
|---|
| | 605 | # ifdef EXTPROC |
|---|
| | 606 | if (on) |
|---|
| | 607 | termbuf.c_lflag |= EXTPROC; |
|---|
| | 608 | else |
|---|
| | 609 | termbuf.c_lflag &= ~EXTPROC; |
|---|
| | 610 | # endif |
|---|
| | 611 | #endif /* TIOCEXT */ |
|---|
| | 612 | } |
|---|
| | 613 | |
|---|
| | 614 | void |
|---|
| | 615 | noit_console_telnet_tty_setsig(noit_console_closure_t ncct, int on) |
|---|
| | 616 | { |
|---|
| | 617 | #ifndef USE_TERMIO |
|---|
| | 618 | if (on) |
|---|
| | 619 | ; |
|---|
| | 620 | #else |
|---|
| | 621 | if (on) |
|---|
| | 622 | termbuf.c_lflag |= ISIG; |
|---|
| | 623 | else |
|---|
| | 624 | termbuf.c_lflag &= ~ISIG; |
|---|
| | 625 | #endif |
|---|
| | 626 | } |
|---|
| | 627 | |
|---|
| | 628 | void |
|---|
| | 629 | noit_console_telnet_tty_setedit(noit_console_closure_t ncct, int on) |
|---|
| | 630 | { |
|---|
| | 631 | #ifndef USE_TERMIO |
|---|
| | 632 | if (on) |
|---|
| | 633 | termbuf.sg.sg_flags &= ~CBREAK; |
|---|
| | 634 | else |
|---|
| | 635 | termbuf.sg.sg_flags |= CBREAK; |
|---|
| | 636 | #else |
|---|
| | 637 | if (on) |
|---|
| | 638 | termbuf.c_lflag |= ICANON; |
|---|
| | 639 | else |
|---|
| | 640 | termbuf.c_lflag &= ~ICANON; |
|---|
| | 641 | #endif |
|---|
| | 642 | } |
|---|
| | 643 | #endif /* LINEMODE */ |
|---|
| | 644 | |
|---|
| | 645 | int |
|---|
| | 646 | noit_console_telnet_tty_istrapsig(noit_console_closure_t ncct) |
|---|
| | 647 | { |
|---|
| | 648 | #ifndef USE_TERMIO |
|---|
| | 649 | return(!(termbuf.sg.sg_flags&RAW)); |
|---|
| | 650 | #else |
|---|
| | 651 | return(termbuf.c_lflag & ISIG); |
|---|
| | 652 | #endif |
|---|
| | 653 | } |
|---|
| | 654 | |
|---|
| | 655 | #ifdef LINEMODE |
|---|
| | 656 | int |
|---|
| | 657 | noit_console_telnet_tty_isediting(noit_console_closure_t ncct) |
|---|
| | 658 | { |
|---|
| | 659 | #ifndef USE_TERMIO |
|---|
| | 660 | return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); |
|---|
| | 661 | #else |
|---|
| | 662 | return(termbuf.c_lflag & ICANON); |
|---|
| | 663 | #endif |
|---|
| | 664 | } |
|---|
| | 665 | #endif |
|---|
| | 666 | |
|---|
| | 667 | int |
|---|
| | 668 | noit_console_telnet_tty_issofttab(noit_console_closure_t ncct) |
|---|
| | 669 | { |
|---|
| | 670 | #ifndef USE_TERMIO |
|---|
| | 671 | return (termbuf.sg.sg_flags & XTABS); |
|---|
| | 672 | #else |
|---|
| | 673 | # ifdef OXTABS |
|---|
| | 674 | return (termbuf.c_oflag & OXTABS); |
|---|
| | 675 | # endif |
|---|
| | 676 | # ifdef TABDLY |
|---|
| | 677 | return ((termbuf.c_oflag & TABDLY) == TAB3); |
|---|
| | 678 | # endif |
|---|
| | 679 | #endif |
|---|
| | 680 | } |
|---|
| | 681 | |
|---|
| | 682 | void |
|---|
| | 683 | noit_console_telnet_tty_setsofttab(noit_console_closure_t ncct, int on) |
|---|
| | 684 | { |
|---|
| | 685 | #ifndef USE_TERMIO |
|---|
| | 686 | if (on) |
|---|
| | 687 | termbuf.sg.sg_flags |= XTABS; |
|---|
| | 688 | else |
|---|
| | 689 | termbuf.sg.sg_flags &= ~XTABS; |
|---|
| | 690 | #else |
|---|
| | 691 | if (on) { |
|---|
| | 692 | # ifdef OXTABS |
|---|
| | 693 | termbuf.c_oflag |= OXTABS; |
|---|
| | 694 | # endif |
|---|
| | 695 | # ifdef TABDLY |
|---|
| | 696 | termbuf.c_oflag &= ~TABDLY; |
|---|
| | 697 | termbuf.c_oflag |= TAB3; |
|---|
| | 698 | # endif |
|---|
| | 699 | } else { |
|---|
| | 700 | # ifdef OXTABS |
|---|
| | 701 | termbuf.c_oflag &= ~OXTABS; |
|---|
| | 702 | # endif |
|---|
| | 703 | # ifdef TABDLY |
|---|
| | 704 | termbuf.c_oflag &= ~TABDLY; |
|---|
| | 705 | termbuf.c_oflag |= TAB0; |
|---|
| | 706 | # endif |
|---|
| | 707 | } |
|---|
| | 708 | #endif |
|---|
| | 709 | } |
|---|
| | 710 | |
|---|
| | 711 | int |
|---|
| | 712 | noit_console_telnet_tty_islitecho(noit_console_closure_t ncct) |
|---|
| | 713 | { |
|---|
| | 714 | #ifndef USE_TERMIO |
|---|
| | 715 | return (!(termbuf.lflags & LCTLECH)); |
|---|
| | 716 | #else |
|---|
| | 717 | # ifdef ECHOCTL |
|---|
| | 718 | return (!(termbuf.c_lflag & ECHOCTL)); |
|---|
| | 719 | # endif |
|---|
| | 720 | # ifdef TCTLECH |
|---|
| | 721 | return (!(termbuf.c_lflag & TCTLECH)); |
|---|
| | 722 | # endif |
|---|
| | 723 | # if !defined(ECHOCTL) && !defined(TCTLECH) |
|---|
| | 724 | return (0); /* assumes ctl chars are echoed '^x' */ |
|---|
| | 725 | # endif |
|---|
| | 726 | #endif |
|---|
| | 727 | } |
|---|
| | 728 | |
|---|
| | 729 | void |
|---|
| | 730 | noit_console_telnet_tty_setlitecho(noit_console_closure_t ncct, int on) |
|---|
| | 731 | { |
|---|
| | 732 | #ifndef USE_TERMIO |
|---|
| | 733 | if (on) |
|---|
| | 734 | termbuf.lflags &= ~LCTLECH; |
|---|
| | 735 | else |
|---|
| | 736 | termbuf.lflags |= LCTLECH; |
|---|
| | 737 | #else |
|---|
| | 738 | # ifdef ECHOCTL |
|---|
| | 739 | if (on) |
|---|
| | 740 | termbuf.c_lflag &= ~ECHOCTL; |
|---|
| | 741 | else |
|---|
| | 742 | termbuf.c_lflag |= ECHOCTL; |
|---|
| | 743 | # endif |
|---|
| | 744 | # ifdef TCTLECH |
|---|
| | 745 | if (on) |
|---|
| | 746 | termbuf.c_lflag &= ~TCTLECH; |
|---|
| | 747 | else |
|---|
| | 748 | termbuf.c_lflag |= TCTLECH; |
|---|
| | 749 | # endif |
|---|
| | 750 | #endif |
|---|
| | 751 | } |
|---|
| | 752 | |
|---|
| | 753 | int |
|---|
| | 754 | noit_console_telnet_tty_iscrnl(noit_console_closure_t ncct) |
|---|
| | 755 | { |
|---|
| | 756 | #ifndef USE_TERMIO |
|---|
| | 757 | return (termbuf.sg.sg_flags & CRMOD); |
|---|
| | 758 | #else |
|---|
| | 759 | return (termbuf.c_iflag & ICRNL); |
|---|
| | 760 | #endif |
|---|
| | 761 | } |
|---|
| | 959 | #ifdef LINEMODE |
|---|
| | 960 | /* |
|---|
| | 961 | * localstat |
|---|
| | 962 | * |
|---|
| | 963 | * This function handles all management of linemode. |
|---|
| | 964 | * |
|---|
| | 965 | * Linemode allows the client to do the local editing of data |
|---|
| | 966 | * and send only complete lines to the server. Linemode state is |
|---|
| | 967 | * based on the state of the pty driver. If the pty is set for |
|---|
| | 968 | * external processing, then we can use linemode. Further, if we |
|---|
| | 969 | * can use real linemode, then we can look at the edit control bits |
|---|
| | 970 | * in the pty to determine what editing the client should do. |
|---|
| | 971 | * |
|---|
| | 972 | * Linemode support uses the following state flags to keep track of |
|---|
| | 973 | * current and desired linemode state. |
|---|
| | 974 | * alwayslinemode : true if -l was specified on the telnetd |
|---|
| | 975 | * command line. It means to have linemode on as much as |
|---|
| | 976 | * possible. |
|---|
| | 977 | * |
|---|
| | 978 | * lmodetype: signifies whether the client can |
|---|
| | 979 | * handle real linemode, or if use of kludgeomatic linemode |
|---|
| | 980 | * is preferred. It will be set to one of the following: |
|---|
| | 981 | * REAL_LINEMODE : use linemode option |
|---|
| | 982 | * NO_KLUDGE : don't initiate kludge linemode. |
|---|
| | 983 | * KLUDGE_LINEMODE : use kludge linemode |
|---|
| | 984 | * NO_LINEMODE : client is ignorant of linemode |
|---|
| | 985 | * |
|---|
| | 986 | * linemode, uselinemode : linemode is true if linemode |
|---|
| | 987 | * is currently on, uselinemode is the state that we wish |
|---|
| | 988 | * to be in. If another function wishes to turn linemode |
|---|
| | 989 | * on or off, it sets or clears uselinemode. |
|---|
| | 990 | * |
|---|
| | 991 | * editmode, useeditmode : like linemode/uselinemode, but |
|---|
| | 992 | * these contain the edit mode states (edit and trapsig). |
|---|
| | 993 | * |
|---|
| | 994 | * The state variables correspond to some of the state information |
|---|
| | 995 | * in the pty. |
|---|
| | 996 | * linemode: |
|---|
| | 997 | * In real linemode, this corresponds to whether the pty |
|---|
| | 998 | * expects external processing of incoming data. |
|---|
| | 999 | * In kludge linemode, this more closely corresponds to the |
|---|
| | 1000 | * whether normal processing is on or not. (ICANON in |
|---|
| | 1001 | * system V, or COOKED mode in BSD.) |
|---|
| | 1002 | * If the -l option was specified (alwayslinemode), then |
|---|
| | 1003 | * an attempt is made to force external processing on at |
|---|
| | 1004 | * all times. |
|---|
| | 1005 | * |
|---|
| | 1006 | * The following heuristics are applied to determine linemode |
|---|
| | 1007 | * handling within the server. |
|---|
| | 1008 | * 1) Early on in starting up the server, an attempt is made |
|---|
| | 1009 | * to negotiate the linemode option. If this succeeds |
|---|
| | 1010 | * then lmodetype is set to REAL_LINEMODE and all linemode |
|---|
| | 1011 | * processing occurs in the context of the linemode option. |
|---|
| | 1012 | * 2) If the attempt to negotiate the linemode option failed, |
|---|
| | 1013 | * and the "-k" (don't initiate kludge linemode) isn't set, |
|---|
| | 1014 | * then we try to use kludge linemode. We test for this |
|---|
| | 1015 | * capability by sending "do Timing Mark". If a positive |
|---|
| | 1016 | * response comes back, then we assume that the client |
|---|
| | 1017 | * understands kludge linemode (ech!) and the |
|---|
| | 1018 | * lmodetype flag is set to KLUDGE_LINEMODE. |
|---|
| | 1019 | * 3) Otherwise, linemode is not supported at all and |
|---|
| | 1020 | * lmodetype remains set to NO_LINEMODE (which happens |
|---|
| | 1021 | * to be 0 for convenience). |
|---|
| | 1022 | * 4) At any time a command arrives that implies a higher |
|---|
| | 1023 | * state of linemode support in the client, we move to that |
|---|
| | 1024 | * linemode support. |
|---|
| | 1025 | * |
|---|
| | 1026 | * A short explanation of kludge linemode is in order here. |
|---|
| | 1027 | * 1) The heuristic to determine support for kludge linemode |
|---|
| | 1028 | * is to send a do timing mark. We assume that a client |
|---|
| | 1029 | * that supports timing marks also supports kludge linemode. |
|---|
| | 1030 | * A risky proposition at best. |
|---|
| | 1031 | * 2) Further negotiation of linemode is done by changing the |
|---|
| | 1032 | * the server's state regarding SGA. If server will SGA, |
|---|
| | 1033 | * then linemode is off, if server won't SGA, then linemode |
|---|
| | 1034 | * is on. |
|---|
| | 1035 | */ |
|---|
| | 1036 | static void |
|---|
| | 1037 | localstat(noit_console_closure_t ncct) |
|---|
| | 1038 | { |
|---|
| | 1039 | int need_will_echo = 0; |
|---|
| | 1040 | |
|---|
| | 1041 | /* |
|---|
| | 1042 | * Check for changes to flow control if client supports it. |
|---|
| | 1043 | */ |
|---|
| | 1044 | flowstat(ncct); |
|---|
| | 1045 | |
|---|
| | 1046 | /* |
|---|
| | 1047 | * Check linemode on/off state |
|---|
| | 1048 | */ |
|---|
| | 1049 | uselinemode = noit_console_telnet_tty_linemode(ncct); |
|---|
| | 1050 | |
|---|
| | 1051 | /* |
|---|
| | 1052 | * If alwayslinemode is on, and pty is changing to turn it off, then |
|---|
| | 1053 | * force linemode back on. |
|---|
| | 1054 | */ |
|---|
| | 1055 | if (alwayslinemode && linemode && !uselinemode) { |
|---|
| | 1056 | uselinemode = 1; |
|---|
| | 1057 | noit_console_telnet_tty_setlinemode(ncct, uselinemode); |
|---|
| | 1058 | } |
|---|
| | 1059 | |
|---|
| | 1060 | if (uselinemode) { |
|---|
| | 1061 | /* |
|---|
| | 1062 | * Check for state of BINARY options. |
|---|
| | 1063 | * |
|---|
| | 1064 | * We only need to do the binary dance if we are actually going |
|---|
| | 1065 | * to use linemode. As this confuses some telnet clients |
|---|
| | 1066 | * that don't support linemode, and doesn't gain us |
|---|
| | 1067 | * anything, we don't do it unless we're doing linemode. |
|---|
| | 1068 | * -Crh (henrich@msu.edu) |
|---|
| | 1069 | */ |
|---|
| | 1070 | |
|---|
| | 1071 | if (noit_console_telnet_tty_isbinaryin(ncct)) { |
|---|
| | 1072 | if (his_want_state_is_wont(TELOPT_BINARY)) |
|---|
| | 1073 | send_do(TELOPT_BINARY, 1); |
|---|
| | 1074 | } else { |
|---|
| | 1075 | if (his_want_state_is_will(TELOPT_BINARY)) |
|---|
| | 1076 | send_dont(TELOPT_BINARY, 1); |
|---|
| | 1077 | } |
|---|
| | 1078 | |
|---|
| | 1079 | if (noit_console_telnet_tty_isbinaryout(ncct)) { |
|---|
| | 1080 | if (my_want_state_is_wont(TELOPT_BINARY)) |
|---|
| | 1081 | send_will(TELOPT_BINARY, 1); |
|---|
| | 1082 | } else { |
|---|
| | 1083 | if (my_want_state_is_will(TELOPT_BINARY)) |
|---|
| | 1084 | send_wont(TELOPT_BINARY, 1); |
|---|
| | 1085 | } |
|---|
| | 1086 | } |
|---|
| | 1087 | |
|---|
| | 1088 | |
|---|
| | 1089 | /* |
|---|
| | 1090 | * Do echo mode handling as soon as we know what the |
|---|
| | 1091 | * linemode is going to be. |
|---|
| | 1092 | * If the pty has echo turned off, then tell the client that |
|---|
| | 1093 | * the server will echo. If echo is on, then the server |
|---|
| | 1094 | * will echo if in character mode, but in linemode the |
|---|
| | 1095 | * client should do local echoing. The state machine will |
|---|
| | 1096 | * not send anything if it is unnecessary, so don't worry |
|---|
| | 1097 | * about that here. |
|---|
| | 1098 | * |
|---|
| | 1099 | * If we need to send the WILL ECHO (because echo is off), |
|---|
| | 1100 | * then delay that until after we have changed the MODE. |
|---|
| | 1101 | * This way, when the user is turning off both editing |
|---|
| | 1102 | * and echo, the client will get editing turned off first. |
|---|
| | 1103 | * This keeps the client from going into encryption mode |
|---|
| | 1104 | * and then right back out if it is doing auto-encryption |
|---|
| | 1105 | * when passwords are being typed. |
|---|
| | 1106 | */ |
|---|
| | 1107 | if (uselinemode) { |
|---|
| | 1108 | if (noit_console_telnet_tty_isecho(ncct)) |
|---|
| | 1109 | send_wont(TELOPT_ECHO, 1); |
|---|
| | 1110 | else |
|---|
| | 1111 | need_will_echo = 1; |
|---|
| | 1112 | #ifdef KLUDGELINEMODE |
|---|
| | 1113 | if (lmodetype == KLUDGE_OK) |
|---|
| | 1114 | lmodetype = KLUDGE_LINEMODE; |
|---|
| | 1115 | #endif |
|---|
| | 1116 | } |
|---|
| | 1117 | |
|---|
| | 1118 | /* |
|---|
| | 1119 | * If linemode is being turned off, send appropriate |
|---|
| | 1120 | * command and then we're all done. |
|---|
| | 1121 | */ |
|---|
| | 1122 | if (!uselinemode && linemode) { |
|---|
| | 1123 | # ifdef KLUDGELINEMODE |
|---|
| | 1124 | if (lmodetype == REAL_LINEMODE) { |
|---|
| | 1125 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1126 | send_dont(TELOPT_LINEMODE, 1); |
|---|
| | 1127 | # ifdef KLUDGELINEMODE |
|---|
| | 1128 | } else if (lmodetype == KLUDGE_LINEMODE) |
|---|
| | 1129 | send_will(TELOPT_SGA, 1); |
|---|
| | 1130 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1131 | send_will(TELOPT_ECHO, 1); |
|---|
| | 1132 | linemode = uselinemode; |
|---|
| | 1133 | goto done; |
|---|
| | 1134 | } |
|---|
| | 1135 | |
|---|
| | 1136 | # ifdef KLUDGELINEMODE |
|---|
| | 1137 | /* |
|---|
| | 1138 | * If using real linemode check edit modes for possible later use. |
|---|
| | 1139 | * If we are in kludge linemode, do the SGA negotiation. |
|---|
| | 1140 | */ |
|---|
| | 1141 | if (lmodetype == REAL_LINEMODE) { |
|---|
| | 1142 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1143 | useeditmode = 0; |
|---|
| | 1144 | if (noit_console_telnet_tty_isediting(ncct)) |
|---|
| | 1145 | useeditmode |= MODE_EDIT; |
|---|
| | 1146 | if (noit_console_telnet_tty_istrapsig(ncct)) |
|---|
| | 1147 | useeditmode |= MODE_TRAPSIG; |
|---|
| | 1148 | if (noit_console_telnet_tty_issofttab(ncct)) |
|---|
| | 1149 | useeditmode |= MODE_SOFT_TAB; |
|---|
| | 1150 | if (noit_console_telnet_tty_islitecho(ncct)) |
|---|
| | 1151 | useeditmode |= MODE_LIT_ECHO; |
|---|
| | 1152 | # ifdef KLUDGELINEMODE |
|---|
| | 1153 | } else if (lmodetype == KLUDGE_LINEMODE) { |
|---|
| | 1154 | if (noit_console_telnet_tty_isediting(ncct) && uselinemode) |
|---|
| | 1155 | send_wont(TELOPT_SGA, 1); |
|---|
| | 1156 | else |
|---|
| | 1157 | send_will(TELOPT_SGA, 1); |
|---|
| | 1158 | } |
|---|
| | 1159 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1160 | |
|---|
| | 1161 | /* |
|---|
| | 1162 | * Negotiate linemode on if pty state has changed to turn it on. |
|---|
| | 1163 | * Send appropriate command and send along edit mode, then all done. |
|---|
| | 1164 | */ |
|---|
| | 1165 | if (uselinemode && !linemode) { |
|---|
| | 1166 | # ifdef KLUDGELINEMODE |
|---|
| | 1167 | if (lmodetype == KLUDGE_LINEMODE) { |
|---|
| | 1168 | send_wont(TELOPT_SGA, 1); |
|---|
| | 1169 | } else if (lmodetype == REAL_LINEMODE) { |
|---|
| | 1170 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1171 | send_do(TELOPT_LINEMODE, 1); |
|---|
| | 1172 | /* send along edit modes */ |
|---|
| | 1173 | nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, SB, |
|---|
| | 1174 | TELOPT_LINEMODE, LM_MODE, useeditmode, |
|---|
| | 1175 | IAC, SE); |
|---|
| | 1176 | editmode = useeditmode; |
|---|
| | 1177 | # ifdef KLUDGELINEMODE |
|---|
| | 1178 | } |
|---|
| | 1179 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1180 | linemode = uselinemode; |
|---|
| | 1181 | goto done; |
|---|
| | 1182 | } |
|---|
| | 1183 | |
|---|
| | 1184 | # ifdef KLUDGELINEMODE |
|---|
| | 1185 | /* |
|---|
| | 1186 | * None of what follows is of any value if not using |
|---|
| | 1187 | * real linemode. |
|---|
| | 1188 | */ |
|---|
| | 1189 | if (lmodetype < REAL_LINEMODE) |
|---|
| | 1190 | goto done; |
|---|
| | 1191 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1192 | |
|---|
| | 1193 | if (linemode && his_state_is_will(TELOPT_LINEMODE)) { |
|---|
| | 1194 | /* |
|---|
| | 1195 | * If edit mode changed, send edit mode. |
|---|
| | 1196 | */ |
|---|
| | 1197 | if (useeditmode != editmode) { |
|---|
| | 1198 | /* |
|---|
| | 1199 | * Send along appropriate edit mode mask. |
|---|
| | 1200 | */ |
|---|
| | 1201 | nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, SB, |
|---|
| | 1202 | TELOPT_LINEMODE, LM_MODE, useeditmode, |
|---|
| | 1203 | IAC, SE); |
|---|
| | 1204 | editmode = useeditmode; |
|---|
| | 1205 | } |
|---|
| | 1206 | |
|---|
| | 1207 | |
|---|
| | 1208 | /* |
|---|
| | 1209 | * Check for changes to special characters in use. |
|---|
| | 1210 | */ |
|---|
| | 1211 | start_slc(ncct, 0); |
|---|
| | 1212 | check_slc(ncct); |
|---|
| | 1213 | (void) end_slc(ncct, 0); |
|---|
| | 1214 | } |
|---|
| | 1215 | |
|---|
| | 1216 | done: |
|---|
| | 1217 | if (need_will_echo) |
|---|
| | 1218 | send_will(TELOPT_ECHO, 1); |
|---|
| | 1219 | /* |
|---|
| | 1220 | * Some things should be deferred until after the pty state has |
|---|
| | 1221 | * been set by the local process. Do those things that have been |
|---|
| | 1222 | * deferred now. This only happens once. |
|---|
| | 1223 | */ |
|---|
| | 1224 | if (_terminit == 0) { |
|---|
| | 1225 | _terminit = 1; |
|---|
| | 1226 | defer_terminit(ncct); |
|---|
| | 1227 | } |
|---|
| | 1228 | |
|---|
| | 1229 | netflush(ncct); |
|---|
| | 1230 | set_termbuf(ncct); |
|---|
| | 1231 | return; |
|---|
| | 1232 | |
|---|
| | 1233 | } /* end of localstat */ |
|---|
| | 1234 | #endif /* LINEMODE */ |
|---|
| | 1235 | |
|---|
| | 1283 | #ifdef LINEMODE |
|---|
| | 1284 | case TELOPT_LINEMODE: |
|---|
| | 1285 | /* |
|---|
| | 1286 | * Don't do anything unless client is asking us to change |
|---|
| | 1287 | * modes. |
|---|
| | 1288 | */ |
|---|
| | 1289 | uselinemode = (parm1 == WILL); |
|---|
| | 1290 | if (uselinemode != linemode) { |
|---|
| | 1291 | # ifdef KLUDGELINEMODE |
|---|
| | 1292 | /* |
|---|
| | 1293 | * If using kludge linemode, make sure that |
|---|
| | 1294 | * we can do what the client asks. |
|---|
| | 1295 | * We can not turn off linemode if alwayslinemode |
|---|
| | 1296 | * and the ICANON bit is set. |
|---|
| | 1297 | */ |
|---|
| | 1298 | if (lmodetype == KLUDGE_LINEMODE) { |
|---|
| | 1299 | if (alwayslinemode && noit_console_telnet_tty_isediting(ncct)) { |
|---|
| | 1300 | uselinemode = 1; |
|---|
| | 1301 | } |
|---|
| | 1302 | } |
|---|
| | 1303 | |
|---|
| | 1304 | /* |
|---|
| | 1305 | * Quit now if we can't do it. |
|---|
| | 1306 | */ |
|---|
| | 1307 | if (uselinemode == linemode) |
|---|
| | 1308 | return; |
|---|
| | 1309 | |
|---|
| | 1310 | /* |
|---|
| | 1311 | * If using real linemode and linemode is being |
|---|
| | 1312 | * turned on, send along the edit mode mask. |
|---|
| | 1313 | */ |
|---|
| | 1314 | if (lmodetype == REAL_LINEMODE && uselinemode) |
|---|
| | 1315 | # else /* KLUDGELINEMODE */ |
|---|
| | 1316 | if (uselinemode) |
|---|
| | 1317 | # endif /* KLUDGELINEMODE */ |
|---|
| | 1318 | { |
|---|
| | 1319 | useeditmode = 0; |
|---|
| | 1320 | if (noit_console_telnet_tty_isediting(ncct)) |
|---|
| | 1321 | useeditmode |= MODE_EDIT; |
|---|
| | 1322 | if (noit_console_telnet_tty_istrapsig(ncct)) |
|---|
| | 1323 | useeditmode |= MODE_TRAPSIG; |
|---|
| | 1324 | if (noit_console_telnet_tty_issofttab(ncct)) |
|---|
| | 1325 | useeditmode |= MODE_SOFT_TAB; |
|---|
| | 1326 | if (noit_console_telnet_tty_islitecho(ncct)) |
|---|
| | 1327 | useeditmode |= MODE_LIT_ECHO; |
|---|
| | 1328 | nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, |
|---|
| | 1329 | SB, TELOPT_LINEMODE, LM_MODE, |
|---|
| | 1330 | useeditmode, IAC, SE); |
|---|
| | 1331 | editmode = useeditmode; |
|---|
| | 1332 | } |
|---|
| | 1333 | |
|---|
| | 1334 | |
|---|
| | 1335 | noit_console_telnet_tty_setlinemode(ncct, uselinemode); |
|---|
| | 1336 | |
|---|
| | 1337 | linemode = uselinemode; |
|---|
| | 1338 | |
|---|
| | 1339 | if (!linemode) |
|---|
| | 1340 | send_will(TELOPT_ECHO, 1); |
|---|
| | 1341 | } |
|---|
| | 1342 | break; |
|---|
| | 1343 | |
|---|
| | 1344 | case LM_MODE: |
|---|
| | 1345 | { |
|---|
| | 1346 | int ack, changed; |
|---|
| | 1347 | |
|---|
| | 1348 | /* |
|---|
| | 1349 | * Client has sent along a mode mask. If it agrees with |
|---|
| | 1350 | * what we are currently doing, ignore it; if not, it could |
|---|
| | 1351 | * be viewed as a request to change. Note that the server |
|---|
| | 1352 | * will change to the modes in an ack if it is different from |
|---|
| | 1353 | * what we currently have, but we will not ack the ack. |
|---|
| | 1354 | */ |
|---|
| | 1355 | useeditmode &= MODE_MASK; |
|---|
| | 1356 | ack = (useeditmode & MODE_ACK); |
|---|
| | 1357 | useeditmode &= ~MODE_ACK; |
|---|
| | 1358 | |
|---|
| | 1359 | if ((changed = (useeditmode ^ editmode))) { |
|---|
| | 1360 | /* |
|---|
| | 1361 | * This check is for a timing problem. If the |
|---|
| | 1362 | * state of the tty has changed (due to the user |
|---|
| | 1363 | * application) we need to process that info |
|---|
| | 1364 | * before we write in the state contained in the |
|---|
| | 1365 | * ack!!! This gets out the new MODE request, |
|---|
| | 1366 | * and when the ack to that command comes back |
|---|
| | 1367 | * we'll set it and be in the right mode. |
|---|
| | 1368 | */ |
|---|
| | 1369 | if (ack) |
|---|
| | 1370 | localstat(ncct); |
|---|
| | 1371 | if (changed & MODE_EDIT) |
|---|
| | 1372 | noit_console_telnet_tty_setedit(ncct, useeditmode & MODE_EDIT); |
|---|
| | 1373 | |
|---|
| | 1374 | if (changed & MODE_TRAPSIG) |
|---|
| | 1375 | noit_console_telnet_tty_setsig(ncct, useeditmode & MODE_TRAPSIG); |
|---|
| | 1376 | |
|---|
| | 1377 | if (changed & MODE_SOFT_TAB) |
|---|
| | 1378 | noit_console_telnet_tty_setsofttab(ncct, useeditmode & MODE_SOFT_TAB); |
|---|
| | 1379 | |
|---|
| | 1380 | if (changed & MODE_LIT_ECHO) |
|---|
| | 1381 | noit_console_telnet_tty_setlitecho(ncct, useeditmode & MODE_LIT_ECHO); |
|---|
| | 1382 | |
|---|
| | 1383 | set_termbuf(ncct); |
|---|
| | 1384 | |
|---|
| | 1385 | if (!ack) { |
|---|
| | 1386 | nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, |
|---|
| | 1387 | SB, TELOPT_LINEMODE, LM_MODE, |
|---|
| | 1388 | useeditmode|MODE_ACK, |
|---|
| | 1389 | IAC, SE); |
|---|
| | 1390 | } |
|---|
| | 1391 | |
|---|
| | 1392 | editmode = useeditmode; |
|---|
| | 1393 | } |
|---|
| | 1394 | |
|---|
| | 1395 | break; |
|---|
| | 1396 | |
|---|
| | 1397 | } /* end of case LM_MODE */ |
|---|
| | 1398 | #endif /* LINEMODE */ |
|---|