tty.c revision 183922
1/*- 2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Portions of this software were developed under sponsorship from Snow 6 * B.V., the Netherlands. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/sys/kern/tty.c 183922 2008-10-15 16:58:35Z ed $"); 32 33#include "opt_compat.h" 34 35#include <sys/param.h> 36#include <sys/conf.h> 37#include <sys/cons.h> 38#include <sys/fcntl.h> 39#include <sys/file.h> 40#include <sys/filio.h> 41#ifdef COMPAT_43TTY 42#include <sys/ioctl_compat.h> 43#endif /* COMPAT_43TTY */ 44#include <sys/kernel.h> 45#include <sys/limits.h> 46#include <sys/malloc.h> 47#include <sys/mount.h> 48#include <sys/poll.h> 49#include <sys/priv.h> 50#include <sys/proc.h> 51#include <sys/serial.h> 52#include <sys/signal.h> 53#include <sys/stat.h> 54#include <sys/sx.h> 55#include <sys/sysctl.h> 56#include <sys/systm.h> 57#include <sys/tty.h> 58#include <sys/ttycom.h> 59#define TTYDEFCHARS 60#include <sys/ttydefaults.h> 61#undef TTYDEFCHARS 62#include <sys/ucred.h> 63#include <sys/vnode.h> 64 65#include <machine/stdarg.h> 66 67static MALLOC_DEFINE(M_TTY, "tty", "tty device"); 68 69static void tty_rel_free(struct tty *tp); 70 71static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list); 72static struct sx tty_list_sx; 73SX_SYSINIT(tty_list, &tty_list_sx, "tty list"); 74static unsigned int tty_list_count = 0; 75 76/* 77 * Flags that are supported and stored by this implementation. 78 */ 79#define TTYSUP_IFLAG (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|\ 80 INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL) 81#define TTYSUP_OFLAG (OPOST|ONLCR|TAB3|ONOEOT|OCRNL|ONOCR|ONLRET) 82#define TTYSUP_LFLAG (ECHOKE|ECHOE|ECHOK|ECHO|ECHONL|ECHOPRT|\ 83 ECHOCTL|ISIG|ICANON|ALTWERASE|IEXTEN|TOSTOP|\ 84 FLUSHO|NOKERNINFO|NOFLSH) 85#define TTYSUP_CFLAG (CIGNORE|CSIZE|CSTOPB|CREAD|PARENB|PARODD|\ 86 HUPCL|CLOCAL|CCTS_OFLOW|CRTS_IFLOW|CDTR_IFLOW|\ 87 CDSR_OFLOW|CCAR_OFLOW) 88 89#define TTY_CALLOUT(tp,d) ((tp)->t_dev != (d)) 90 91/* 92 * Set TTY buffer sizes. 93 */ 94 95#define TTYBUF_MAX 65536 96 97static void 98tty_watermarks(struct tty *tp) 99{ 100 size_t bs; 101 102 /* Provide an input buffer for 0.2 seconds of data. */ 103 bs = MIN(tp->t_termios.c_ispeed / 5, TTYBUF_MAX); 104 ttyinq_setsize(&tp->t_inq, tp, bs); 105 106 /* Set low watermark at 10% (when 90% is available). */ 107 tp->t_inlow = (ttyinq_getsize(&tp->t_inq) * 9) / 10; 108 109 /* Provide an ouput buffer for 0.2 seconds of data. */ 110 bs = MIN(tp->t_termios.c_ospeed / 5, TTYBUF_MAX); 111 ttyoutq_setsize(&tp->t_outq, tp, bs); 112 113 /* Set low watermark at 10% (when 90% is available). */ 114 tp->t_outlow = (ttyoutq_getsize(&tp->t_outq) * 9) / 10; 115} 116 117static int 118tty_drain(struct tty *tp) 119{ 120 int error; 121 122 while (ttyoutq_bytesused(&tp->t_outq) > 0) { 123 ttydevsw_outwakeup(tp); 124 /* Could be handled synchronously. */ 125 if (ttyoutq_bytesused(&tp->t_outq) == 0) 126 return (0); 127 128 /* Wait for data to be drained. */ 129 error = tty_wait(tp, &tp->t_outwait); 130 if (error) 131 return (error); 132 } 133 134 return (0); 135} 136 137/* 138 * Though ttydev_enter() and ttydev_leave() seem to be related, they 139 * don't have to be used together. ttydev_enter() is used by the cdev 140 * operations to prevent an actual operation from being processed when 141 * the TTY has been abandoned. ttydev_leave() is used by ttydev_open() 142 * and ttydev_close() to determine whether per-TTY data should be 143 * deallocated. 144 */ 145 146static __inline int 147ttydev_enter(struct tty *tp) 148{ 149 tty_lock(tp); 150 151 if (tty_gone(tp) || !tty_opened(tp)) { 152 /* Device is already gone. */ 153 tty_unlock(tp); 154 return (ENXIO); 155 } 156 157 return (0); 158} 159 160static void 161ttydev_leave(struct tty *tp) 162{ 163 tty_lock_assert(tp, MA_OWNED); 164 165 if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) { 166 /* Device is still opened somewhere. */ 167 tty_unlock(tp); 168 return; 169 } 170 171 tp->t_flags |= TF_OPENCLOSE; 172 173 /* Stop asynchronous I/O. */ 174 funsetown(&tp->t_sigio); 175 176 /* Remove console TTY. */ 177 if (constty == tp) 178 constty_clear(); 179 180 /* Drain any output. */ 181 MPASS((tp->t_flags & TF_STOPPED) == 0); 182 if (!tty_gone(tp)) 183 tty_drain(tp); 184 185 ttydisc_close(tp); 186 187 /* Destroy associated buffers already. */ 188 ttyinq_free(&tp->t_inq); 189 tp->t_inlow = 0; 190 ttyoutq_free(&tp->t_outq); 191 tp->t_outlow = 0; 192 193 knlist_clear(&tp->t_inpoll.si_note, 1); 194 knlist_clear(&tp->t_outpoll.si_note, 1); 195 196 if (!tty_gone(tp)) 197 ttydevsw_close(tp); 198 199 tp->t_flags &= ~TF_OPENCLOSE; 200 tty_rel_free(tp); 201} 202 203/* 204 * Operations that are exposed through the character device in /dev. 205 */ 206static int 207ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 208{ 209 struct tty *tp = dev->si_drv1; 210 int error = 0; 211 212 /* Disallow access when the TTY belongs to a different prison. */ 213 if (dev->si_cred != NULL && 214 dev->si_cred->cr_prison != td->td_ucred->cr_prison && 215 priv_check(td, PRIV_TTY_PRISON)) { 216 return (EPERM); 217 } 218 219 tty_lock(tp); 220 if (tty_gone(tp)) { 221 /* Device is already gone. */ 222 tty_unlock(tp); 223 return (ENXIO); 224 } 225 /* 226 * Prevent the TTY from being opened when being torn down or 227 * built up by unrelated processes. 228 */ 229 if (tp->t_flags & TF_OPENCLOSE) { 230 tty_unlock(tp); 231 return (EBUSY); 232 } 233 tp->t_flags |= TF_OPENCLOSE; 234 235 /* 236 * Make sure the "tty" and "cua" device cannot be opened at the 237 * same time. 238 */ 239 if (TTY_CALLOUT(tp, dev)) { 240 if (tp->t_flags & TF_OPENED_IN) { 241 error = EBUSY; 242 goto done; 243 } 244 } else { 245 if (tp->t_flags & TF_OPENED_OUT) { 246 error = EBUSY; 247 goto done; 248 } 249 } 250 251 if (tp->t_flags & TF_EXCLUDE && priv_check(td, PRIV_TTY_EXCLUSIVE)) { 252 error = EBUSY; 253 goto done; 254 } 255 256 if (!tty_opened(tp)) { 257 /* Set proper termios flags. */ 258 if (TTY_CALLOUT(tp, dev)) { 259 tp->t_termios = tp->t_termios_init_out; 260 } else { 261 tp->t_termios = tp->t_termios_init_in; 262 } 263 ttydevsw_param(tp, &tp->t_termios); 264 265 ttydevsw_modem(tp, SER_DTR|SER_RTS, 0); 266 267 error = ttydevsw_open(tp); 268 if (error != 0) 269 goto done; 270 271 ttydisc_open(tp); 272 tty_watermarks(tp); 273 } 274 275 /* Wait for Carrier Detect. */ 276 if (!TTY_CALLOUT(tp, dev) && (oflags & O_NONBLOCK) == 0 && 277 (tp->t_termios.c_cflag & CLOCAL) == 0) { 278 while ((ttydevsw_modem(tp, 0, 0) & SER_DCD) == 0) { 279 error = tty_wait(tp, &tp->t_dcdwait); 280 if (error != 0) 281 goto done; 282 } 283 } 284 285 if (TTY_CALLOUT(tp, dev)) { 286 tp->t_flags |= TF_OPENED_OUT; 287 } else { 288 tp->t_flags |= TF_OPENED_IN; 289 } 290 291done: tp->t_flags &= ~TF_OPENCLOSE; 292 ttydev_leave(tp); 293 294 return (error); 295} 296 297static int 298ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 299{ 300 struct tty *tp = dev->si_drv1; 301 302 tty_lock(tp); 303 304 /* 305 * This can only be called once. The callin and the callout 306 * devices cannot be opened at the same time. 307 */ 308 MPASS((tp->t_flags & TF_OPENED) != TF_OPENED); 309 tp->t_flags &= ~(TF_OPENED|TF_EXCLUDE|TF_STOPPED); 310 311 /* Properly wake up threads that are stuck - revoke(). */ 312 tp->t_revokecnt++; 313 tty_wakeup(tp, FREAD|FWRITE); 314 cv_broadcast(&tp->t_bgwait); 315 316 ttydev_leave(tp); 317 318 return (0); 319} 320 321static __inline int 322tty_is_ctty(struct tty *tp, struct proc *p) 323{ 324 tty_lock_assert(tp, MA_OWNED); 325 326 return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT); 327} 328 329static int 330tty_wait_background(struct tty *tp, struct thread *td, int sig) 331{ 332 struct proc *p = td->td_proc; 333 struct pgrp *pg; 334 int error; 335 336 MPASS(sig == SIGTTIN || sig == SIGTTOU); 337 tty_lock_assert(tp, MA_OWNED); 338 339 for (;;) { 340 PROC_LOCK(p); 341 /* 342 * The process should only sleep, when: 343 * - This terminal is the controling terminal 344 * - Its process group is not the foreground process 345 * group 346 * - The parent process isn't waiting for the child to 347 * exit 348 * - the signal to send to the process isn't masked 349 */ 350 if (!tty_is_ctty(tp, p) || 351 p->p_pgrp == tp->t_pgrp || p->p_flag & P_PPWAIT || 352 SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) || 353 SIGISMEMBER(td->td_sigmask, sig)) { 354 /* Allow the action to happen. */ 355 PROC_UNLOCK(p); 356 return (0); 357 } 358 359 /* 360 * Send the signal and sleep until we're the new 361 * foreground process group. 362 */ 363 pg = p->p_pgrp; 364 PROC_UNLOCK(p); 365 if (pg->pg_jobc == 0) 366 return (EIO); 367 PGRP_LOCK(pg); 368 pgsignal(pg, sig, 1); 369 PGRP_UNLOCK(pg); 370 371 error = tty_wait(tp, &tp->t_bgwait); 372 if (error) 373 return (error); 374 } 375} 376 377static int 378ttydev_read(struct cdev *dev, struct uio *uio, int ioflag) 379{ 380 struct tty *tp = dev->si_drv1; 381 int error; 382 383 error = ttydev_enter(tp); 384 if (error) 385 goto done; 386 387 error = tty_wait_background(tp, curthread, SIGTTIN); 388 if (error) { 389 tty_unlock(tp); 390 goto done; 391 } 392 393 error = ttydisc_read(tp, uio, ioflag); 394 tty_unlock(tp); 395 396 /* 397 * The read() call should not throw an error when the device is 398 * being destroyed. Silently convert it to an EOF. 399 */ 400done: if (error == ENXIO) 401 error = 0; 402 return (error); 403} 404 405static int 406ttydev_write(struct cdev *dev, struct uio *uio, int ioflag) 407{ 408 struct tty *tp = dev->si_drv1; 409 int error; 410 411 error = ttydev_enter(tp); 412 if (error) 413 return (error); 414 415 if (tp->t_termios.c_lflag & TOSTOP) { 416 error = tty_wait_background(tp, curthread, SIGTTOU); 417 if (error) { 418 tty_unlock(tp); 419 return (error); 420 } 421 } 422 423 error = ttydisc_write(tp, uio, ioflag); 424 tty_unlock(tp); 425 426 return (error); 427} 428 429static int 430ttydev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 431 struct thread *td) 432{ 433 struct tty *tp = dev->si_drv1; 434 int error; 435 436 error = ttydev_enter(tp); 437 if (error) 438 return (error); 439 440 switch (cmd) { 441 case TIOCCBRK: 442 case TIOCCONS: 443 case TIOCDRAIN: 444 case TIOCEXCL: 445 case TIOCFLUSH: 446 case TIOCNXCL: 447 case TIOCSBRK: 448 case TIOCSCTTY: 449 case TIOCSETA: 450 case TIOCSETAF: 451 case TIOCSETAW: 452 case TIOCSPGRP: 453 case TIOCSTART: 454 case TIOCSTAT: 455 case TIOCSTOP: 456 case TIOCSWINSZ: 457#if 0 458 case TIOCSDRAINWAIT: 459 case TIOCSETD: 460 case TIOCSTI: 461#endif 462#ifdef COMPAT_43TTY 463 case TIOCLBIC: 464 case TIOCLBIS: 465 case TIOCLSET: 466 case TIOCSETC: 467 case OTIOCSETD: 468 case TIOCSETN: 469 case TIOCSETP: 470 case TIOCSLTC: 471#endif /* COMPAT_43TTY */ 472 /* 473 * If the ioctl() causes the TTY to be modified, let it 474 * wait in the background. 475 */ 476 error = tty_wait_background(tp, curthread, SIGTTOU); 477 if (error) 478 goto done; 479 } 480 481 error = tty_ioctl(tp, cmd, data, td); 482done: tty_unlock(tp); 483 484 return (error); 485} 486 487static int 488ttydev_poll(struct cdev *dev, int events, struct thread *td) 489{ 490 struct tty *tp = dev->si_drv1; 491 int error, revents = 0; 492 493 error = ttydev_enter(tp); 494 if (error) { 495 /* Don't return the error here, but the event mask. */ 496 return (events & 497 (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM)); 498 } 499 500 if (events & (POLLIN|POLLRDNORM)) { 501 /* See if we can read something. */ 502 if (ttydisc_read_poll(tp) > 0) 503 revents |= events & (POLLIN|POLLRDNORM); 504 } 505 if (events & (POLLOUT|POLLWRNORM)) { 506 /* See if we can write something. */ 507 if (ttydisc_write_poll(tp) > 0) 508 revents |= events & (POLLOUT|POLLWRNORM); 509 } 510 if (tp->t_flags & TF_ZOMBIE) 511 /* Hangup flag on zombie state. */ 512 revents |= events & POLLHUP; 513 514 if (revents == 0) { 515 if (events & (POLLIN|POLLRDNORM)) 516 selrecord(td, &tp->t_inpoll); 517 if (events & (POLLOUT|POLLWRNORM)) 518 selrecord(td, &tp->t_outpoll); 519 } 520 521 tty_unlock(tp); 522 523 return (revents); 524} 525 526static int 527ttydev_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot) 528{ 529 struct tty *tp = dev->si_drv1; 530 int error; 531 532 /* Handle mmap() through the driver. */ 533 534 error = ttydev_enter(tp); 535 if (error) 536 return (-1); 537 error = ttydevsw_mmap(tp, offset, paddr, nprot); 538 tty_unlock(tp); 539 540 return (error); 541} 542 543/* 544 * kqueue support. 545 */ 546 547static void 548tty_kqops_read_detach(struct knote *kn) 549{ 550 struct tty *tp = kn->kn_hook; 551 552 knlist_remove(&tp->t_inpoll.si_note, kn, 0); 553} 554 555static int 556tty_kqops_read_event(struct knote *kn, long hint) 557{ 558 struct tty *tp = kn->kn_hook; 559 560 tty_lock_assert(tp, MA_OWNED); 561 562 if (tty_gone(tp) || tp->t_flags & TF_ZOMBIE) { 563 kn->kn_flags |= EV_EOF; 564 return (1); 565 } else { 566 kn->kn_data = ttydisc_read_poll(tp); 567 return (kn->kn_data > 0); 568 } 569} 570 571static void 572tty_kqops_write_detach(struct knote *kn) 573{ 574 struct tty *tp = kn->kn_hook; 575 576 knlist_remove(&tp->t_outpoll.si_note, kn, 0); 577} 578 579static int 580tty_kqops_write_event(struct knote *kn, long hint) 581{ 582 struct tty *tp = kn->kn_hook; 583 584 tty_lock_assert(tp, MA_OWNED); 585 586 if (tty_gone(tp)) { 587 kn->kn_flags |= EV_EOF; 588 return (1); 589 } else { 590 kn->kn_data = ttydisc_write_poll(tp); 591 return (kn->kn_data > 0); 592 } 593} 594 595static struct filterops tty_kqops_read = 596 { 1, NULL, tty_kqops_read_detach, tty_kqops_read_event }; 597static struct filterops tty_kqops_write = 598 { 1, NULL, tty_kqops_write_detach, tty_kqops_write_event }; 599 600static int 601ttydev_kqfilter(struct cdev *dev, struct knote *kn) 602{ 603 struct tty *tp = dev->si_drv1; 604 int error; 605 606 error = ttydev_enter(tp); 607 if (error) 608 return (error); 609 610 switch (kn->kn_filter) { 611 case EVFILT_READ: 612 kn->kn_hook = tp; 613 kn->kn_fop = &tty_kqops_read; 614 knlist_add(&tp->t_inpoll.si_note, kn, 1); 615 break; 616 case EVFILT_WRITE: 617 kn->kn_hook = tp; 618 kn->kn_fop = &tty_kqops_write; 619 knlist_add(&tp->t_outpoll.si_note, kn, 1); 620 break; 621 default: 622 error = EINVAL; 623 break; 624 } 625 626 tty_unlock(tp); 627 return (error); 628} 629 630static struct cdevsw ttydev_cdevsw = { 631 .d_version = D_VERSION, 632 .d_open = ttydev_open, 633 .d_close = ttydev_close, 634 .d_read = ttydev_read, 635 .d_write = ttydev_write, 636 .d_ioctl = ttydev_ioctl, 637 .d_kqfilter = ttydev_kqfilter, 638 .d_poll = ttydev_poll, 639 .d_mmap = ttydev_mmap, 640 .d_name = "ttydev", 641 .d_flags = D_TTY, 642}; 643 644/* 645 * Init/lock-state devices 646 */ 647 648static int 649ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 650{ 651 struct tty *tp = dev->si_drv1; 652 int error = 0; 653 654 tty_lock(tp); 655 if (tty_gone(tp)) 656 error = ENODEV; 657 tty_unlock(tp); 658 659 return (error); 660} 661 662static int 663ttyil_close(struct cdev *dev, int flag, int mode, struct thread *td) 664{ 665 return (0); 666} 667 668static int 669ttyil_rdwr(struct cdev *dev, struct uio *uio, int ioflag) 670{ 671 return (ENODEV); 672} 673 674static int 675ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 676 struct thread *td) 677{ 678 struct tty *tp = dev->si_drv1; 679 int error = 0; 680 681 tty_lock(tp); 682 if (tty_gone(tp)) { 683 error = ENODEV; 684 goto done; 685 } 686 687 switch (cmd) { 688 case TIOCGETA: 689 /* Obtain terminal flags through tcgetattr(). */ 690 bcopy(dev->si_drv2, data, sizeof(struct termios)); 691 break; 692 case TIOCSETA: 693 /* Set terminal flags through tcsetattr(). */ 694 error = priv_check(td, PRIV_TTY_SETA); 695 if (error) 696 break; 697 bcopy(data, dev->si_drv2, sizeof(struct termios)); 698 break; 699 case TIOCGETD: 700 *(int *)data = TTYDISC; 701 break; 702 case TIOCGWINSZ: 703 bzero(data, sizeof(struct winsize)); 704 break; 705 default: 706 error = ENOTTY; 707 } 708 709done: tty_unlock(tp); 710 return (error); 711} 712 713static struct cdevsw ttyil_cdevsw = { 714 .d_version = D_VERSION, 715 .d_open = ttyil_open, 716 .d_close = ttyil_close, 717 .d_read = ttyil_rdwr, 718 .d_write = ttyil_rdwr, 719 .d_ioctl = ttyil_ioctl, 720 .d_name = "ttyil", 721 .d_flags = D_TTY, 722}; 723 724static void 725tty_init_termios(struct tty *tp) 726{ 727 struct termios *t = &tp->t_termios_init_in; 728 729 t->c_cflag = TTYDEF_CFLAG; 730 t->c_iflag = TTYDEF_IFLAG; 731 t->c_lflag = TTYDEF_LFLAG; 732 t->c_oflag = TTYDEF_OFLAG; 733 t->c_ispeed = TTYDEF_SPEED; 734 t->c_ospeed = TTYDEF_SPEED; 735 bcopy(ttydefchars, &t->c_cc, sizeof ttydefchars); 736 737 tp->t_termios_init_out = *t; 738} 739 740void 741tty_init_console(struct tty *tp, speed_t s) 742{ 743 struct termios *ti = &tp->t_termios_init_in; 744 struct termios *to = &tp->t_termios_init_out; 745 746 if (s != 0) { 747 ti->c_ispeed = ti->c_ospeed = s; 748 to->c_ispeed = to->c_ospeed = s; 749 } 750 751 ti->c_cflag |= CLOCAL; 752 to->c_cflag |= CLOCAL; 753} 754 755/* 756 * Standard device routine implementations, mostly meant for 757 * pseudo-terminal device drivers. When a driver creates a new terminal 758 * device class, missing routines are patched. 759 */ 760 761static int 762ttydevsw_defopen(struct tty *tp) 763{ 764 765 return (0); 766} 767 768static void 769ttydevsw_defclose(struct tty *tp) 770{ 771} 772 773static void 774ttydevsw_defoutwakeup(struct tty *tp) 775{ 776 777 panic("Terminal device has output, while not implemented"); 778} 779 780static void 781ttydevsw_definwakeup(struct tty *tp) 782{ 783} 784 785static int 786ttydevsw_defioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 787{ 788 789 return (ENOIOCTL); 790} 791 792static int 793ttydevsw_defparam(struct tty *tp, struct termios *t) 794{ 795 796 /* Use a fake baud rate, we're not a real device. */ 797 t->c_ispeed = t->c_ospeed = TTYDEF_SPEED_PSEUDO; 798 799 return (0); 800} 801 802static int 803ttydevsw_defmodem(struct tty *tp, int sigon, int sigoff) 804{ 805 806 /* Simulate a carrier to make the TTY layer happy. */ 807 return (SER_DCD); 808} 809 810static int 811ttydevsw_defmmap(struct tty *tp, vm_offset_t offset, vm_paddr_t *paddr, 812 int nprot) 813{ 814 815 return (-1); 816} 817 818static void 819ttydevsw_defpktnotify(struct tty *tp, char event) 820{ 821} 822 823static void 824ttydevsw_deffree(void *softc) 825{ 826 827 panic("Terminal device freed without a free-handler"); 828} 829 830/* 831 * TTY allocation and deallocation. TTY devices can be deallocated when 832 * the driver doesn't use it anymore, when the TTY isn't a session's 833 * controlling TTY and when the device node isn't opened through devfs. 834 */ 835 836struct tty * 837tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex) 838{ 839 struct tty *tp; 840 841 /* Make sure the driver defines all routines. */ 842#define PATCH_FUNC(x) do { \ 843 if (tsw->tsw_ ## x == NULL) \ 844 tsw->tsw_ ## x = ttydevsw_def ## x; \ 845} while (0) 846 PATCH_FUNC(open); 847 PATCH_FUNC(close); 848 PATCH_FUNC(outwakeup); 849 PATCH_FUNC(inwakeup); 850 PATCH_FUNC(ioctl); 851 PATCH_FUNC(param); 852 PATCH_FUNC(modem); 853 PATCH_FUNC(mmap); 854 PATCH_FUNC(pktnotify); 855 PATCH_FUNC(free); 856#undef PATCH_FUNC 857 858 tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO); 859 tp->t_devsw = tsw; 860 tp->t_devswsoftc = sc; 861 tp->t_flags = tsw->tsw_flags; 862 863 tty_init_termios(tp); 864 865 cv_init(&tp->t_inwait, "tty input"); 866 cv_init(&tp->t_outwait, "tty output"); 867 cv_init(&tp->t_bgwait, "tty background"); 868 cv_init(&tp->t_dcdwait, "tty dcd"); 869 870 ttyinq_init(&tp->t_inq); 871 ttyoutq_init(&tp->t_outq); 872 873 /* Allow drivers to use a custom mutex to lock the TTY. */ 874 if (mutex != NULL) { 875 tp->t_mtx = mutex; 876 } else { 877 tp->t_mtx = &tp->t_mtxobj; 878 mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF); 879 } 880 881 knlist_init(&tp->t_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL); 882 knlist_init(&tp->t_outpoll.si_note, tp->t_mtx, NULL, NULL, NULL); 883 884 sx_xlock(&tty_list_sx); 885 TAILQ_INSERT_TAIL(&tty_list, tp, t_list); 886 tty_list_count++; 887 sx_xunlock(&tty_list_sx); 888 889 return (tp); 890} 891 892static void 893tty_dealloc(void *arg) 894{ 895 struct tty *tp = arg; 896 897 sx_xlock(&tty_list_sx); 898 TAILQ_REMOVE(&tty_list, tp, t_list); 899 tty_list_count--; 900 sx_xunlock(&tty_list_sx); 901 902 /* Make sure we haven't leaked buffers. */ 903 MPASS(ttyinq_getsize(&tp->t_inq) == 0); 904 MPASS(ttyoutq_getsize(&tp->t_outq) == 0); 905 906 knlist_destroy(&tp->t_inpoll.si_note); 907 knlist_destroy(&tp->t_outpoll.si_note); 908 909 cv_destroy(&tp->t_inwait); 910 cv_destroy(&tp->t_outwait); 911 cv_destroy(&tp->t_bgwait); 912 cv_destroy(&tp->t_dcdwait); 913 914 if (tp->t_mtx == &tp->t_mtxobj) 915 mtx_destroy(&tp->t_mtxobj); 916 ttydevsw_free(tp); 917 free(tp, M_TTY); 918} 919 920static void 921tty_rel_free(struct tty *tp) 922{ 923 struct cdev *dev; 924 925 tty_lock_assert(tp, MA_OWNED); 926 927#define TF_ACTIVITY (TF_GONE|TF_OPENED|TF_HOOK|TF_OPENCLOSE) 928 if (tp->t_sessioncnt != 0 || (tp->t_flags & TF_ACTIVITY) != TF_GONE) { 929 /* TTY is still in use. */ 930 tty_unlock(tp); 931 return; 932 } 933 934 /* TTY can be deallocated. */ 935 dev = tp->t_dev; 936 tp->t_dev = NULL; 937 tty_unlock(tp); 938 939 destroy_dev_sched_cb(dev, tty_dealloc, tp); 940} 941 942void 943tty_rel_pgrp(struct tty *tp, struct pgrp *pg) 944{ 945 MPASS(tp->t_sessioncnt > 0); 946 tty_lock_assert(tp, MA_OWNED); 947 948 if (tp->t_pgrp == pg) 949 tp->t_pgrp = NULL; 950 951 tty_unlock(tp); 952} 953 954void 955tty_rel_sess(struct tty *tp, struct session *sess) 956{ 957 MPASS(tp->t_sessioncnt > 0); 958 959 /* Current session has left. */ 960 if (tp->t_session == sess) { 961 tp->t_session = NULL; 962 MPASS(tp->t_pgrp == NULL); 963 } 964 tp->t_sessioncnt--; 965 tty_rel_free(tp); 966} 967 968void 969tty_rel_gone(struct tty *tp) 970{ 971 MPASS(!tty_gone(tp)); 972 973 /* Simulate carrier removal. */ 974 ttydisc_modem(tp, 0); 975 976 /* Wake up all blocked threads. */ 977 tty_wakeup(tp, FREAD|FWRITE); 978 cv_broadcast(&tp->t_bgwait); 979 cv_broadcast(&tp->t_dcdwait); 980 981 tp->t_flags |= TF_GONE; 982 tty_rel_free(tp); 983} 984 985/* 986 * Exposing information about current TTY's through sysctl 987 */ 988 989static void 990tty_to_xtty(struct tty *tp, struct xtty *xt) 991{ 992 tty_lock_assert(tp, MA_OWNED); 993 994 xt->xt_size = sizeof(struct xtty); 995 xt->xt_insize = ttyinq_getsize(&tp->t_inq); 996 xt->xt_incc = ttyinq_bytescanonicalized(&tp->t_inq); 997 xt->xt_inlc = ttyinq_bytesline(&tp->t_inq); 998 xt->xt_inlow = tp->t_inlow; 999 xt->xt_outsize = ttyoutq_getsize(&tp->t_outq); 1000 xt->xt_outcc = ttyoutq_bytesused(&tp->t_outq); 1001 xt->xt_outlow = tp->t_outlow; 1002 xt->xt_column = tp->t_column; 1003 xt->xt_pgid = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 1004 xt->xt_sid = tp->t_session ? tp->t_session->s_sid : 0; 1005 xt->xt_flags = tp->t_flags; 1006 xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : NODEV; 1007} 1008 1009static int 1010sysctl_kern_ttys(SYSCTL_HANDLER_ARGS) 1011{ 1012 unsigned long lsize; 1013 struct xtty *xtlist, *xt; 1014 struct tty *tp; 1015 int error; 1016 1017 sx_slock(&tty_list_sx); 1018 lsize = tty_list_count * sizeof(struct xtty); 1019 if (lsize == 0) { 1020 sx_sunlock(&tty_list_sx); 1021 return (0); 1022 } 1023 1024 xtlist = xt = malloc(lsize, M_TEMP, M_WAITOK); 1025 1026 TAILQ_FOREACH(tp, &tty_list, t_list) { 1027 tty_lock(tp); 1028 tty_to_xtty(tp, xt); 1029 tty_unlock(tp); 1030 xt++; 1031 } 1032 sx_sunlock(&tty_list_sx); 1033 1034 error = SYSCTL_OUT(req, xtlist, lsize); 1035 free(xtlist, M_TEMP); 1036 return (error); 1037} 1038 1039SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD, 1040 0, 0, sysctl_kern_ttys, "S,xtty", "List of TTYs"); 1041 1042/* 1043 * Device node creation. Device has been set up, now we can expose it to 1044 * the user. 1045 */ 1046 1047void 1048tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...) 1049{ 1050 va_list ap; 1051 struct cdev *dev; 1052 const char *prefix = "tty"; 1053 char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */ 1054 uid_t uid; 1055 gid_t gid; 1056 mode_t mode; 1057 1058 /* Remove "tty" prefix from devices like PTY's. */ 1059 if (tp->t_flags & TF_NOPREFIX) 1060 prefix = ""; 1061 1062 va_start(ap, fmt); 1063 vsnrprintf(name, sizeof name, 32, fmt, ap); 1064 va_end(ap); 1065 1066 if (cred == NULL) { 1067 /* System device. */ 1068 uid = UID_ROOT; 1069 gid = GID_WHEEL; 1070 mode = S_IRUSR|S_IWUSR; 1071 } else { 1072 /* User device. */ 1073 uid = cred->cr_ruid; 1074 gid = GID_TTY; 1075 mode = S_IRUSR|S_IWUSR|S_IWGRP; 1076 } 1077 1078 /* Master call-in device. */ 1079 dev = make_dev_cred(&ttydev_cdevsw, 0, cred, 1080 uid, gid, mode, "%s%s", prefix, name); 1081 dev->si_drv1 = tp; 1082 tp->t_dev = dev; 1083 1084 /* Slave call-in devices. */ 1085 if (tp->t_flags & TF_INITLOCK) { 1086 dev = make_dev_cred(&ttyil_cdevsw, 0, cred, 1087 uid, gid, mode, "%s%s.init", prefix, name); 1088 dev_depends(tp->t_dev, dev); 1089 dev->si_drv1 = tp; 1090 dev->si_drv2 = &tp->t_termios_init_in; 1091 1092 dev = make_dev_cred(&ttyil_cdevsw, 0, cred, 1093 uid, gid, mode, "%s%s.lock", prefix, name); 1094 dev_depends(tp->t_dev, dev); 1095 dev->si_drv1 = tp; 1096 dev->si_drv2 = &tp->t_termios_lock_in; 1097 } 1098 1099 /* Call-out devices. */ 1100 if (tp->t_flags & TF_CALLOUT) { 1101 dev = make_dev_cred(&ttydev_cdevsw, 0, cred, 1102 UID_UUCP, GID_DIALER, 0660, "cua%s", name); 1103 dev_depends(tp->t_dev, dev); 1104 dev->si_drv1 = tp; 1105 1106 /* Slave call-out devices. */ 1107 if (tp->t_flags & TF_INITLOCK) { 1108 dev = make_dev_cred(&ttyil_cdevsw, 0, cred, 1109 UID_UUCP, GID_DIALER, 0660, "cua%s.init", name); 1110 dev_depends(tp->t_dev, dev); 1111 dev->si_drv1 = tp; 1112 dev->si_drv2 = &tp->t_termios_init_out; 1113 1114 dev = make_dev_cred(&ttyil_cdevsw, 0, cred, 1115 UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name); 1116 dev_depends(tp->t_dev, dev); 1117 dev->si_drv1 = tp; 1118 dev->si_drv2 = &tp->t_termios_lock_out; 1119 } 1120 } 1121} 1122 1123/* 1124 * Signalling processes. 1125 */ 1126 1127void 1128tty_signal_sessleader(struct tty *tp, int sig) 1129{ 1130 struct proc *p; 1131 1132 tty_lock_assert(tp, MA_OWNED); 1133 MPASS(sig >= 1 && sig < NSIG); 1134 1135 /* Make signals start output again. */ 1136 tp->t_flags &= ~TF_STOPPED; 1137 1138 if (tp->t_session != NULL && tp->t_session->s_leader != NULL) { 1139 p = tp->t_session->s_leader; 1140 PROC_LOCK(p); 1141 psignal(p, sig); 1142 PROC_UNLOCK(p); 1143 } 1144} 1145 1146void 1147tty_signal_pgrp(struct tty *tp, int sig) 1148{ 1149 tty_lock_assert(tp, MA_OWNED); 1150 MPASS(sig >= 1 && sig < NSIG); 1151 1152 /* Make signals start output again. */ 1153 tp->t_flags &= ~TF_STOPPED; 1154 1155 if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO)) 1156 tty_info(tp); 1157 if (tp->t_pgrp != NULL) { 1158 PGRP_LOCK(tp->t_pgrp); 1159 pgsignal(tp->t_pgrp, sig, 1); 1160 PGRP_UNLOCK(tp->t_pgrp); 1161 } 1162} 1163 1164void 1165tty_wakeup(struct tty *tp, int flags) 1166{ 1167 if (tp->t_flags & TF_ASYNC && tp->t_sigio != NULL) 1168 pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL)); 1169 1170 if (flags & FWRITE) { 1171 cv_broadcast(&tp->t_outwait); 1172 selwakeup(&tp->t_outpoll); 1173 KNOTE_LOCKED(&tp->t_outpoll.si_note, 0); 1174 } 1175 if (flags & FREAD) { 1176 cv_broadcast(&tp->t_inwait); 1177 selwakeup(&tp->t_inpoll); 1178 KNOTE_LOCKED(&tp->t_inpoll.si_note, 0); 1179 } 1180} 1181 1182int 1183tty_wait(struct tty *tp, struct cv *cv) 1184{ 1185 int error; 1186 int revokecnt = tp->t_revokecnt; 1187 1188#if 0 1189 /* XXX: /dev/console also picks up Giant. */ 1190 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED); 1191#endif 1192 tty_lock_assert(tp, MA_OWNED); 1193 MPASS(!tty_gone(tp)); 1194 1195 error = cv_wait_sig(cv, tp->t_mtx); 1196 1197 /* Restart the system call when we may have been revoked. */ 1198 if (tp->t_revokecnt != revokecnt) 1199 return (ERESTART); 1200 1201 /* Bail out when the device slipped away. */ 1202 if (tty_gone(tp)) 1203 return (ENXIO); 1204 1205 return (error); 1206} 1207 1208int 1209tty_timedwait(struct tty *tp, struct cv *cv, int hz) 1210{ 1211 int error; 1212 int revokecnt = tp->t_revokecnt; 1213 1214#if 0 1215 /* XXX: /dev/console also picks up Giant. */ 1216 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED); 1217#endif 1218 tty_lock_assert(tp, MA_OWNED); 1219 MPASS(!tty_gone(tp)); 1220 1221 error = cv_timedwait_sig(cv, tp->t_mtx, hz); 1222 1223 /* Restart the system call when we may have been revoked. */ 1224 if (tp->t_revokecnt != revokecnt) 1225 return (ERESTART); 1226 1227 /* Bail out when the device slipped away. */ 1228 if (tty_gone(tp)) 1229 return (ENXIO); 1230 1231 return (error); 1232} 1233 1234void 1235tty_flush(struct tty *tp, int flags) 1236{ 1237 if (flags & FWRITE) { 1238 tp->t_flags &= ~TF_HIWAT_OUT; 1239 ttyoutq_flush(&tp->t_outq); 1240 tty_wakeup(tp, FWRITE); 1241 ttydevsw_pktnotify(tp, TIOCPKT_FLUSHWRITE); 1242 } 1243 if (flags & FREAD) { 1244 tty_hiwat_in_unblock(tp); 1245 ttyinq_flush(&tp->t_inq); 1246 ttydevsw_inwakeup(tp); 1247 ttydevsw_pktnotify(tp, TIOCPKT_FLUSHREAD); 1248 } 1249} 1250 1251static int 1252tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td) 1253{ 1254 int error; 1255 1256 switch (cmd) { 1257 /* 1258 * Modem commands. 1259 * The SER_* and TIOCM_* flags are the same, but one bit 1260 * shifted. I don't know why. 1261 */ 1262 case TIOCSDTR: 1263 ttydevsw_modem(tp, SER_DTR, 0); 1264 return (0); 1265 case TIOCCDTR: 1266 ttydevsw_modem(tp, 0, SER_DTR); 1267 return (0); 1268 case TIOCMSET: { 1269 int bits = *(int *)data; 1270 ttydevsw_modem(tp, 1271 (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1, 1272 ((~bits) & (TIOCM_DTR | TIOCM_RTS)) >> 1); 1273 return (0); 1274 } 1275 case TIOCMBIS: { 1276 int bits = *(int *)data; 1277 ttydevsw_modem(tp, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1, 0); 1278 return (0); 1279 } 1280 case TIOCMBIC: { 1281 int bits = *(int *)data; 1282 ttydevsw_modem(tp, 0, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1); 1283 return (0); 1284 } 1285 case TIOCMGET: 1286 *(int *)data = TIOCM_LE + (ttydevsw_modem(tp, 0, 0) << 1); 1287 return (0); 1288 1289 case FIOASYNC: 1290 if (*(int *)data) 1291 tp->t_flags |= TF_ASYNC; 1292 else 1293 tp->t_flags &= ~TF_ASYNC; 1294 return (0); 1295 case FIONBIO: 1296 /* This device supports non-blocking operation. */ 1297 return (0); 1298 case FIONREAD: 1299 *(int *)data = ttyinq_bytescanonicalized(&tp->t_inq); 1300 return (0); 1301 case FIOSETOWN: 1302 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc)) 1303 /* Not allowed to set ownership. */ 1304 return (ENOTTY); 1305 1306 /* Temporarily unlock the TTY to set ownership. */ 1307 tty_unlock(tp); 1308 error = fsetown(*(int *)data, &tp->t_sigio); 1309 tty_lock(tp); 1310 return (error); 1311 case FIOGETOWN: 1312 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc)) 1313 /* Not allowed to set ownership. */ 1314 return (ENOTTY); 1315 1316 /* Get ownership. */ 1317 *(int *)data = fgetown(&tp->t_sigio); 1318 return (0); 1319 case TIOCGETA: 1320 /* Obtain terminal flags through tcgetattr(). */ 1321 bcopy(&tp->t_termios, data, sizeof(struct termios)); 1322 return (0); 1323 case TIOCSETA: 1324 case TIOCSETAW: 1325 case TIOCSETAF: { 1326 struct termios *t = data; 1327 1328 /* 1329 * Who makes up these funny rules? According to POSIX, 1330 * input baud rate is set equal to the output baud rate 1331 * when zero. 1332 */ 1333 if (t->c_ispeed == 0) 1334 t->c_ispeed = t->c_ospeed; 1335 1336 /* Discard any unsupported bits. */ 1337 t->c_iflag &= TTYSUP_IFLAG; 1338 t->c_oflag &= TTYSUP_OFLAG; 1339 t->c_lflag &= TTYSUP_LFLAG; 1340 t->c_cflag &= TTYSUP_CFLAG; 1341 1342 /* Set terminal flags through tcsetattr(). */ 1343 if (cmd == TIOCSETAW || cmd == TIOCSETAF) { 1344 error = tty_drain(tp); 1345 if (error) 1346 return (error); 1347 if (cmd == TIOCSETAF) 1348 tty_flush(tp, FREAD); 1349 } 1350 1351 /* 1352 * Only call param() when the flags really change. 1353 */ 1354 if ((t->c_cflag & CIGNORE) == 0 && 1355 (tp->t_termios.c_cflag != t->c_cflag || 1356 tp->t_termios.c_ispeed != t->c_ispeed || 1357 tp->t_termios.c_ospeed != t->c_ospeed)) { 1358 error = ttydevsw_param(tp, t); 1359 if (error) 1360 return (error); 1361 1362 /* XXX: CLOCAL? */ 1363 1364 tp->t_termios.c_cflag = t->c_cflag & ~CIGNORE; 1365 tp->t_termios.c_ispeed = t->c_ispeed; 1366 tp->t_termios.c_ospeed = t->c_ospeed; 1367 1368 /* Baud rate has changed - update watermarks. */ 1369 tty_watermarks(tp); 1370 } 1371 1372 /* Copy new non-device driver parameters. */ 1373 tp->t_termios.c_iflag = t->c_iflag; 1374 tp->t_termios.c_oflag = t->c_oflag; 1375 tp->t_termios.c_lflag = t->c_lflag; 1376 bcopy(t->c_cc, &tp->t_termios.c_cc, sizeof(t->c_cc)); 1377 1378 ttydisc_optimize(tp); 1379 1380 if ((t->c_lflag & ICANON) == 0) { 1381 /* 1382 * When in non-canonical mode, wake up all 1383 * readers. Canonicalize any partial input. VMIN 1384 * and VTIME could also be adjusted. 1385 */ 1386 ttyinq_canonicalize(&tp->t_inq); 1387 tty_wakeup(tp, FREAD); 1388 } 1389 1390 /* 1391 * For packet mode: notify the PTY consumer that VSTOP 1392 * and VSTART may have been changed. 1393 */ 1394 if (tp->t_termios.c_iflag & IXON && 1395 tp->t_termios.c_cc[VSTOP] == CTRL('S') && 1396 tp->t_termios.c_cc[VSTART] == CTRL('Q')) 1397 ttydevsw_pktnotify(tp, TIOCPKT_DOSTOP); 1398 else 1399 ttydevsw_pktnotify(tp, TIOCPKT_NOSTOP); 1400 return (0); 1401 } 1402 case TIOCGETD: 1403 /* For compatibility - we only support TTYDISC. */ 1404 *(int *)data = TTYDISC; 1405 return (0); 1406 case TIOCGPGRP: 1407 if (!tty_is_ctty(tp, td->td_proc)) 1408 return (ENOTTY); 1409 1410 if (tp->t_pgrp != NULL) 1411 *(int *)data = tp->t_pgrp->pg_id; 1412 else 1413 *(int *)data = NO_PID; 1414 return (0); 1415 case TIOCGSID: 1416 if (!tty_is_ctty(tp, td->td_proc)) 1417 return (ENOTTY); 1418 1419 MPASS(tp->t_session); 1420 *(int *)data = tp->t_session->s_sid; 1421 return (0); 1422 case TIOCSCTTY: { 1423 struct proc *p = td->td_proc; 1424 1425 /* XXX: This looks awful. */ 1426 tty_unlock(tp); 1427 sx_xlock(&proctree_lock); 1428 tty_lock(tp); 1429 1430 if (!SESS_LEADER(p)) { 1431 /* Only the session leader may do this. */ 1432 sx_xunlock(&proctree_lock); 1433 return (EPERM); 1434 } 1435 1436 if (tp->t_session != NULL && tp->t_session == p->p_session) { 1437 /* This is already our controlling TTY. */ 1438 sx_xunlock(&proctree_lock); 1439 return (0); 1440 } 1441 1442 if (!SESS_LEADER(p) || p->p_session->s_ttyvp != NULL || 1443 (tp->t_session != NULL && tp->t_session->s_ttyvp != NULL)) { 1444 /* 1445 * There is already a relation between a TTY and 1446 * a session, or the caller is not the session 1447 * leader. 1448 * 1449 * Allow the TTY to be stolen when the vnode is 1450 * NULL, but the reference to the TTY is still 1451 * active. 1452 */ 1453 sx_xunlock(&proctree_lock); 1454 return (EPERM); 1455 } 1456 1457 /* Connect the session to the TTY. */ 1458 tp->t_session = p->p_session; 1459 tp->t_session->s_ttyp = tp; 1460 tp->t_sessioncnt++; 1461 sx_xunlock(&proctree_lock); 1462 1463 /* Assign foreground process group. */ 1464 tp->t_pgrp = p->p_pgrp; 1465 PROC_LOCK(p); 1466 p->p_flag |= P_CONTROLT; 1467 PROC_UNLOCK(p); 1468 1469 return (0); 1470 } 1471 case TIOCSPGRP: { 1472 struct pgrp *pg; 1473 1474 /* 1475 * XXX: Temporarily unlock the TTY to locate the process 1476 * group. This code would be lot nicer if we would ever 1477 * decompose proctree_lock. 1478 */ 1479 tty_unlock(tp); 1480 sx_slock(&proctree_lock); 1481 pg = pgfind(*(int *)data); 1482 if (pg != NULL) 1483 PGRP_UNLOCK(pg); 1484 if (pg == NULL || pg->pg_session != td->td_proc->p_session) { 1485 sx_sunlock(&proctree_lock); 1486 tty_lock(tp); 1487 return (EPERM); 1488 } 1489 tty_lock(tp); 1490 1491 /* 1492 * Determine if this TTY is the controlling TTY after 1493 * relocking the TTY. 1494 */ 1495 if (!tty_is_ctty(tp, td->td_proc)) { 1496 sx_sunlock(&proctree_lock); 1497 return (ENOTTY); 1498 } 1499 tp->t_pgrp = pg; 1500 sx_sunlock(&proctree_lock); 1501 1502 /* Wake up the background process groups. */ 1503 cv_broadcast(&tp->t_bgwait); 1504 return (0); 1505 } 1506 case TIOCFLUSH: { 1507 int flags = *(int *)data; 1508 1509 if (flags == 0) 1510 flags = (FREAD|FWRITE); 1511 else 1512 flags &= (FREAD|FWRITE); 1513 tty_flush(tp, flags); 1514 return (0); 1515 } 1516 case TIOCDRAIN: 1517 /* Drain TTY output. */ 1518 return tty_drain(tp); 1519 case TIOCCONS: 1520 /* Set terminal as console TTY. */ 1521 if (*(int *)data) { 1522 error = priv_check(td, PRIV_TTY_CONSOLE); 1523 if (error) 1524 return (error); 1525 1526 /* 1527 * XXX: constty should really need to be locked! 1528 * XXX: allow disconnected constty's to be stolen! 1529 */ 1530 1531 if (constty == tp) 1532 return (0); 1533 if (constty != NULL) 1534 return (EBUSY); 1535 1536 tty_unlock(tp); 1537 constty_set(tp); 1538 tty_lock(tp); 1539 } else if (constty == tp) { 1540 constty_clear(); 1541 } 1542 return (0); 1543 case TIOCGWINSZ: 1544 /* Obtain window size. */ 1545 bcopy(&tp->t_winsize, data, sizeof(struct winsize)); 1546 return (0); 1547 case TIOCSWINSZ: 1548 /* Set window size. */ 1549 if (bcmp(&tp->t_winsize, data, sizeof(struct winsize)) == 0) 1550 return (0); 1551 bcopy(data, &tp->t_winsize, sizeof(struct winsize)); 1552 tty_signal_pgrp(tp, SIGWINCH); 1553 return (0); 1554 case TIOCEXCL: 1555 tp->t_flags |= TF_EXCLUDE; 1556 return (0); 1557 case TIOCNXCL: 1558 tp->t_flags &= ~TF_EXCLUDE; 1559 return (0); 1560 case TIOCOUTQ: 1561 *(unsigned int *)data = ttyoutq_bytesused(&tp->t_outq); 1562 return (0); 1563 case TIOCSTOP: 1564 tp->t_flags |= TF_STOPPED; 1565 ttydevsw_pktnotify(tp, TIOCPKT_STOP); 1566 return (0); 1567 case TIOCSTART: 1568 tp->t_flags &= ~TF_STOPPED; 1569 ttydevsw_outwakeup(tp); 1570 ttydevsw_pktnotify(tp, TIOCPKT_START); 1571 return (0); 1572 case TIOCSTAT: 1573 tty_info(tp); 1574 return (0); 1575 } 1576 1577#ifdef COMPAT_43TTY 1578 return tty_ioctl_compat(tp, cmd, data, td); 1579#else /* !COMPAT_43TTY */ 1580 return (ENOIOCTL); 1581#endif /* COMPAT_43TTY */ 1582} 1583 1584int 1585tty_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td) 1586{ 1587 int error; 1588 1589 tty_lock_assert(tp, MA_OWNED); 1590 1591 if (tty_gone(tp)) 1592 return (ENXIO); 1593 1594 error = ttydevsw_ioctl(tp, cmd, data, td); 1595 if (error == ENOIOCTL) 1596 error = tty_generic_ioctl(tp, cmd, data, td); 1597 1598 return (error); 1599} 1600 1601dev_t 1602tty_udev(struct tty *tp) 1603{ 1604 if (tp->t_dev) 1605 return dev2udev(tp->t_dev); 1606 else 1607 return NODEV; 1608} 1609 1610int 1611tty_checkoutq(struct tty *tp) 1612{ 1613 1614 /* 256 bytes should be enough to print a log message. */ 1615 return (ttyoutq_bytesleft(&tp->t_outq) >= 256); 1616} 1617 1618void 1619tty_hiwat_in_block(struct tty *tp) 1620{ 1621 1622 if ((tp->t_flags & TF_HIWAT_IN) == 0 && 1623 tp->t_termios.c_iflag & IXOFF && 1624 tp->t_termios.c_cc[VSTOP] != _POSIX_VDISABLE) { 1625 /* 1626 * Input flow control. Only enter the high watermark when we 1627 * can successfully store the VSTOP character. 1628 */ 1629 if (ttyoutq_write_nofrag(&tp->t_outq, 1630 &tp->t_termios.c_cc[VSTOP], 1) == 0) 1631 tp->t_flags |= TF_HIWAT_IN; 1632 } else { 1633 /* No input flow control. */ 1634 tp->t_flags |= TF_HIWAT_IN; 1635 } 1636} 1637 1638void 1639tty_hiwat_in_unblock(struct tty *tp) 1640{ 1641 1642 if (tp->t_flags & TF_HIWAT_IN && 1643 tp->t_termios.c_iflag & IXOFF && 1644 tp->t_termios.c_cc[VSTART] != _POSIX_VDISABLE) { 1645 /* 1646 * Input flow control. Only leave the high watermark when we 1647 * can successfully store the VSTART character. 1648 */ 1649 if (ttyoutq_write_nofrag(&tp->t_outq, 1650 &tp->t_termios.c_cc[VSTART], 1) == 0) 1651 tp->t_flags &= ~TF_HIWAT_IN; 1652 } else { 1653 /* No input flow control. */ 1654 tp->t_flags &= ~TF_HIWAT_IN; 1655 } 1656 1657 if (!tty_gone(tp)) 1658 ttydevsw_inwakeup(tp); 1659} 1660 1661static int 1662ttyhook_defrint(struct tty *tp, char c, int flags) 1663{ 1664 1665 if (ttyhook_rint_bypass(tp, &c, 1) != 1) 1666 return (-1); 1667 1668 return (0); 1669} 1670 1671int 1672ttyhook_register(struct tty **rtp, struct thread *td, int fd, 1673 struct ttyhook *th, void *softc) 1674{ 1675 struct tty *tp; 1676 struct file *fp; 1677 struct cdev *dev; 1678 struct cdevsw *cdp; 1679 int error; 1680 1681 /* Validate the file descriptor. */ 1682 if (fget(td, fd, &fp) != 0) 1683 return (EINVAL); 1684 1685 /* Make sure the vnode is bound to a character device. */ 1686 error = EINVAL; 1687 if (fp->f_type != DTYPE_VNODE || fp->f_vnode->v_type != VCHR || 1688 fp->f_vnode->v_rdev == NULL) 1689 goto done1; 1690 dev = fp->f_vnode->v_rdev; 1691 1692 /* Make sure it is a TTY. */ 1693 cdp = dev_refthread(dev); 1694 if (cdp == NULL) 1695 goto done1; 1696 if (cdp != &ttydev_cdevsw) 1697 goto done2; 1698 tp = dev->si_drv1; 1699 1700 /* Try to attach the hook to the TTY. */ 1701 error = EBUSY; 1702 tty_lock(tp); 1703 MPASS((tp->t_hook == NULL) == ((tp->t_flags & TF_HOOK) == 0)); 1704 if (tp->t_flags & TF_HOOK) 1705 goto done3; 1706 1707 tp->t_flags |= TF_HOOK; 1708 tp->t_hook = th; 1709 tp->t_hooksoftc = softc; 1710 *rtp = tp; 1711 error = 0; 1712 1713 /* Maybe we can switch into bypass mode now. */ 1714 ttydisc_optimize(tp); 1715 1716 /* Silently convert rint() calls to rint_bypass() when possible. */ 1717 if (!ttyhook_hashook(tp, rint) && ttyhook_hashook(tp, rint_bypass)) 1718 th->th_rint = ttyhook_defrint; 1719 1720done3: tty_unlock(tp); 1721done2: dev_relthread(dev); 1722done1: fdrop(fp, td); 1723 return (error); 1724} 1725 1726void 1727ttyhook_unregister(struct tty *tp) 1728{ 1729 1730 tty_lock_assert(tp, MA_OWNED); 1731 MPASS(tp->t_flags & TF_HOOK); 1732 1733 /* Disconnect the hook. */ 1734 tp->t_flags &= ~TF_HOOK; 1735 tp->t_hook = NULL; 1736 1737 /* Maybe we need to leave bypass mode. */ 1738 ttydisc_optimize(tp); 1739 1740 /* Maybe deallocate the TTY as well. */ 1741 tty_rel_free(tp); 1742} 1743 1744#include "opt_ddb.h" 1745#ifdef DDB 1746#include <ddb/ddb.h> 1747#include <ddb/db_sym.h> 1748 1749static struct { 1750 int flag; 1751 char val; 1752} ttystates[] = { 1753#if 0 1754 { TF_NOPREFIX, 'N' }, 1755#endif 1756 { TF_INITLOCK, 'I' }, 1757 { TF_CALLOUT, 'C' }, 1758 1759 /* Keep these together -> 'Oi' and 'Oo'. */ 1760 { TF_OPENED, 'O' }, 1761 { TF_OPENED_IN, 'i' }, 1762 { TF_OPENED_OUT,'o' }, 1763 1764 { TF_GONE, 'G' }, 1765 { TF_OPENCLOSE, 'B' }, 1766 { TF_ASYNC, 'Y' }, 1767 { TF_LITERAL, 'L' }, 1768 1769 /* Keep these together -> 'Hi' and 'Ho'. */ 1770 { TF_HIWAT, 'H' }, 1771 { TF_HIWAT_IN, 'i' }, 1772 { TF_HIWAT_OUT, 'o' }, 1773 1774 { TF_STOPPED, 'S' }, 1775 { TF_EXCLUDE, 'X' }, 1776 { TF_BYPASS, 'l' }, 1777 { TF_ZOMBIE, 'Z' }, 1778 { TF_HOOK, 's' }, 1779 1780 { 0, '\0' }, 1781}; 1782 1783#define TTY_FLAG_BITS \ 1784 "\20\1NOPREFIX\2INITLOCK\3CALLOUT\4OPENED_IN\5OPENED_OUT\6GONE" \ 1785 "\7OPENCLOSE\10ASYNC\11LITERAL\12HIWAT_IN\13HIWAT_OUT\14STOPPED" \ 1786 "\15EXCLUDE\16BYPASS\17ZOMBIE\20HOOK" 1787 1788#define DB_PRINTSYM(name, addr) \ 1789 db_printf("%s " #name ": ", sep); \ 1790 db_printsym((db_addr_t) addr, DB_STGY_ANY); \ 1791 db_printf("\n"); 1792 1793static void 1794_db_show_devsw(const char *sep, const struct ttydevsw *tsw) 1795{ 1796 db_printf("%sdevsw: ", sep); 1797 db_printsym((db_addr_t)tsw, DB_STGY_ANY); 1798 db_printf(" (%p)\n", tsw); 1799 DB_PRINTSYM(open, tsw->tsw_open); 1800 DB_PRINTSYM(close, tsw->tsw_close); 1801 DB_PRINTSYM(outwakeup, tsw->tsw_outwakeup); 1802 DB_PRINTSYM(inwakeup, tsw->tsw_inwakeup); 1803 DB_PRINTSYM(ioctl, tsw->tsw_ioctl); 1804 DB_PRINTSYM(param, tsw->tsw_param); 1805 DB_PRINTSYM(modem, tsw->tsw_modem); 1806 DB_PRINTSYM(mmap, tsw->tsw_mmap); 1807 DB_PRINTSYM(pktnotify, tsw->tsw_pktnotify); 1808 DB_PRINTSYM(free, tsw->tsw_free); 1809} 1810static void 1811_db_show_hooks(const char *sep, const struct ttyhook *th) 1812{ 1813 db_printf("%shook: ", sep); 1814 db_printsym((db_addr_t)th, DB_STGY_ANY); 1815 db_printf(" (%p)\n", th); 1816 if (th == NULL) 1817 return; 1818 DB_PRINTSYM(rint, th->th_rint); 1819 DB_PRINTSYM(rint_bypass, th->th_rint_bypass); 1820 DB_PRINTSYM(rint_done, th->th_rint_done); 1821 DB_PRINTSYM(rint_poll, th->th_rint_poll); 1822 DB_PRINTSYM(getc_inject, th->th_getc_inject); 1823 DB_PRINTSYM(getc_capture, th->th_getc_capture); 1824 DB_PRINTSYM(getc_poll, th->th_getc_poll); 1825 DB_PRINTSYM(close, th->th_close); 1826} 1827 1828static void 1829_db_show_termios(const char *name, const struct termios *t) 1830{ 1831 1832 db_printf("%s: iflag 0x%x oflag 0x%x cflag 0x%x " 1833 "lflag 0x%x ispeed %u ospeed %u\n", name, 1834 t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag, 1835 t->c_ispeed, t->c_ospeed); 1836} 1837 1838/* DDB command to show TTY statistics. */ 1839DB_SHOW_COMMAND(tty, db_show_tty) 1840{ 1841 struct tty *tp; 1842 1843 if (!have_addr) { 1844 db_printf("usage: show tty <addr>\n"); 1845 return; 1846 } 1847 tp = (struct tty *)addr; 1848 1849 db_printf("0x%p: %s\n", tp, tty_devname(tp)); 1850 db_printf("\tmtx: %p\n", tp->t_mtx); 1851 db_printf("\tflags: %b\n", tp->t_flags, TTY_FLAG_BITS); 1852 db_printf("\trevokecnt: %u\n", tp->t_revokecnt); 1853 1854 /* Buffering mechanisms. */ 1855 db_printf("\tinq: %p begin %u linestart %u reprint %u end %u " 1856 "nblocks %u quota %u\n", &tp->t_inq, tp->t_inq.ti_begin, 1857 tp->t_inq.ti_linestart, tp->t_inq.ti_reprint, tp->t_inq.ti_end, 1858 tp->t_inq.ti_nblocks, tp->t_inq.ti_quota); 1859 db_printf("\toutq: %p begin %u end %u nblocks %u quota %u\n", 1860 &tp->t_outq, tp->t_outq.to_begin, tp->t_outq.to_end, 1861 tp->t_outq.to_nblocks, tp->t_outq.to_quota); 1862 db_printf("\tinlow: %zu\n", tp->t_inlow); 1863 db_printf("\toutlow: %zu\n", tp->t_outlow); 1864 _db_show_termios("\ttermios", &tp->t_termios); 1865 db_printf("\twinsize: row %u col %u xpixel %u ypixel %u\n", 1866 tp->t_winsize.ws_row, tp->t_winsize.ws_col, 1867 tp->t_winsize.ws_xpixel, tp->t_winsize.ws_ypixel); 1868 db_printf("\tcolumn: %u\n", tp->t_column); 1869 db_printf("\twritepos: %u\n", tp->t_writepos); 1870 db_printf("\tcompatflags: 0x%x\n", tp->t_compatflags); 1871 1872 /* Init/lock-state devices. */ 1873 _db_show_termios("\ttermios_init_in", &tp->t_termios_init_in); 1874 _db_show_termios("\ttermios_init_out", &tp->t_termios_init_out); 1875 _db_show_termios("\ttermios_lock_in", &tp->t_termios_lock_in); 1876 _db_show_termios("\ttermios_lock_out", &tp->t_termios_lock_out); 1877 1878 /* Hooks */ 1879 _db_show_devsw("\t", tp->t_devsw); 1880 _db_show_hooks("\t", tp->t_hook); 1881 1882 /* Process info. */ 1883 db_printf("\tpgrp: %p gid %d jobc %d\n", tp->t_pgrp, 1884 tp->t_pgrp ? tp->t_pgrp->pg_id : 0, 1885 tp->t_pgrp ? tp->t_pgrp->pg_jobc : 0); 1886 db_printf("\tsession: %p", tp->t_session); 1887 if (tp->t_session != NULL) 1888 db_printf(" count %u leader %p tty %p sid %d login %s", 1889 tp->t_session->s_count, tp->t_session->s_leader, 1890 tp->t_session->s_ttyp, tp->t_session->s_sid, 1891 tp->t_session->s_login); 1892 db_printf("\n"); 1893 db_printf("\tsessioncnt: %u\n", tp->t_sessioncnt); 1894 db_printf("\tdevswsoftc: %p\n", tp->t_devswsoftc); 1895 db_printf("\thooksoftc: %p\n", tp->t_hooksoftc); 1896 db_printf("\tdev: %p\n", tp->t_dev); 1897} 1898 1899/* DDB command to list TTYs. */ 1900DB_SHOW_ALL_COMMAND(ttys, db_show_all_ttys) 1901{ 1902 struct tty *tp; 1903 size_t isiz, osiz; 1904 int i, j; 1905 1906 /* Make the output look like `pstat -t'. */ 1907 db_printf("PTR "); 1908#if defined(__LP64__) 1909 db_printf(" "); 1910#endif 1911 db_printf(" LINE INQ CAN LIN LOW OUTQ USE LOW " 1912 "COL SESS PGID STATE\n"); 1913 1914 TAILQ_FOREACH(tp, &tty_list, t_list) { 1915 isiz = tp->t_inq.ti_nblocks * TTYINQ_DATASIZE; 1916 osiz = tp->t_outq.to_nblocks * TTYOUTQ_DATASIZE; 1917 1918 db_printf("%p %10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ", 1919 tp, 1920 tty_devname(tp), 1921 isiz, 1922 tp->t_inq.ti_linestart - tp->t_inq.ti_begin, 1923 tp->t_inq.ti_end - tp->t_inq.ti_linestart, 1924 isiz - tp->t_inlow, 1925 osiz, 1926 tp->t_outq.to_end - tp->t_outq.to_begin, 1927 osiz - tp->t_outlow, 1928 tp->t_column, 1929 tp->t_session ? tp->t_session->s_sid : 0, 1930 tp->t_pgrp ? tp->t_pgrp->pg_id : 0); 1931 1932 /* Flag bits. */ 1933 for (i = j = 0; ttystates[i].flag; i++) 1934 if (tp->t_flags & ttystates[i].flag) { 1935 db_printf("%c", ttystates[i].val); 1936 j++; 1937 } 1938 if (j == 0) 1939 db_printf("-"); 1940 db_printf("\n"); 1941 } 1942} 1943#endif /* DDB */ 1944