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