1/* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 30 */ 31 32#include <sys/cdefs.h>
| 1/* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 30 */ 31 32#include <sys/cdefs.h>
|
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 129939 2004-06-01 11:57:15Z phk $");
| 33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 130054 2004-06-04 06:50:35Z phk $");
|
34 35/* 36 * Pseudo-teletype Driver 37 * (Actually two drivers, requiring two entries in 'cdevsw') 38 */ 39#include "opt_compat.h" 40#include "opt_tty.h" 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <sys/sx.h> 46#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 47#include <sys/ioctl_compat.h> 48#endif 49#include <sys/proc.h> 50#include <sys/tty.h> 51#include <sys/conf.h> 52#include <sys/fcntl.h> 53#include <sys/poll.h> 54#include <sys/kernel.h> 55#include <sys/vnode.h> 56#include <sys/signalvar.h> 57#include <sys/malloc.h> 58 59static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures"); 60 61static void ptsstart(struct tty *tp); 62static void ptsstop(struct tty *tp, int rw); 63static void ptcwakeup(struct tty *tp, int flag); 64static dev_t ptyinit(dev_t cdev); 65 66static d_open_t ptsopen; 67static d_close_t ptsclose; 68static d_read_t ptsread; 69static d_write_t ptswrite; 70static d_ioctl_t ptyioctl; 71static d_open_t ptcopen; 72static d_close_t ptcclose; 73static d_read_t ptcread; 74static d_write_t ptcwrite; 75static d_poll_t ptcpoll; 76 77#define CDEV_MAJOR_S 5 78static struct cdevsw pts_cdevsw = { 79 .d_version = D_VERSION, 80 .d_open = ptsopen, 81 .d_close = ptsclose, 82 .d_read = ptsread, 83 .d_write = ptswrite, 84 .d_ioctl = ptyioctl, 85 .d_name = "pts", 86 .d_maj = CDEV_MAJOR_S, 87 .d_flags = D_TTY | D_NEEDGIANT, 88}; 89 90#define CDEV_MAJOR_C 6 91static struct cdevsw ptc_cdevsw = { 92 .d_version = D_VERSION, 93 .d_open = ptcopen, 94 .d_close = ptcclose, 95 .d_read = ptcread, 96 .d_write = ptcwrite, 97 .d_ioctl = ptyioctl, 98 .d_poll = ptcpoll, 99 .d_name = "ptc", 100 .d_maj = CDEV_MAJOR_C, 101 .d_flags = D_TTY | D_NEEDGIANT, 102}; 103 104#define BUFSIZ 100 /* Chunk size iomoved to/from user */ 105 106struct pt_ioctl { 107 int pt_flags; 108 struct selinfo pt_selr, pt_selw; 109 u_char pt_send; 110 u_char pt_ucntl;
| 34 35/* 36 * Pseudo-teletype Driver 37 * (Actually two drivers, requiring two entries in 'cdevsw') 38 */ 39#include "opt_compat.h" 40#include "opt_tty.h" 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <sys/sx.h> 46#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 47#include <sys/ioctl_compat.h> 48#endif 49#include <sys/proc.h> 50#include <sys/tty.h> 51#include <sys/conf.h> 52#include <sys/fcntl.h> 53#include <sys/poll.h> 54#include <sys/kernel.h> 55#include <sys/vnode.h> 56#include <sys/signalvar.h> 57#include <sys/malloc.h> 58 59static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures"); 60 61static void ptsstart(struct tty *tp); 62static void ptsstop(struct tty *tp, int rw); 63static void ptcwakeup(struct tty *tp, int flag); 64static dev_t ptyinit(dev_t cdev); 65 66static d_open_t ptsopen; 67static d_close_t ptsclose; 68static d_read_t ptsread; 69static d_write_t ptswrite; 70static d_ioctl_t ptyioctl; 71static d_open_t ptcopen; 72static d_close_t ptcclose; 73static d_read_t ptcread; 74static d_write_t ptcwrite; 75static d_poll_t ptcpoll; 76 77#define CDEV_MAJOR_S 5 78static struct cdevsw pts_cdevsw = { 79 .d_version = D_VERSION, 80 .d_open = ptsopen, 81 .d_close = ptsclose, 82 .d_read = ptsread, 83 .d_write = ptswrite, 84 .d_ioctl = ptyioctl, 85 .d_name = "pts", 86 .d_maj = CDEV_MAJOR_S, 87 .d_flags = D_TTY | D_NEEDGIANT, 88}; 89 90#define CDEV_MAJOR_C 6 91static struct cdevsw ptc_cdevsw = { 92 .d_version = D_VERSION, 93 .d_open = ptcopen, 94 .d_close = ptcclose, 95 .d_read = ptcread, 96 .d_write = ptcwrite, 97 .d_ioctl = ptyioctl, 98 .d_poll = ptcpoll, 99 .d_name = "ptc", 100 .d_maj = CDEV_MAJOR_C, 101 .d_flags = D_TTY | D_NEEDGIANT, 102}; 103 104#define BUFSIZ 100 /* Chunk size iomoved to/from user */ 105 106struct pt_ioctl { 107 int pt_flags; 108 struct selinfo pt_selr, pt_selw; 109 u_char pt_send; 110 u_char pt_ucntl;
|
111 struct tty pt_tty;
| 111 struct tty *pt_tty;
|
112 dev_t devs, devc; 113 struct prison *pt_prison; 114}; 115 116#define PF_PKT 0x08 /* packet mode */ 117#define PF_STOPPED 0x10 /* user told stopped */ 118#define PF_REMOTE 0x20 /* remote and flow controlled input */ 119#define PF_NOSTOP 0x40 120#define PF_UCNTL 0x80 /* user control mode */ 121 122static char *names = "pqrsPQRS"; 123/* 124 * This function creates and initializes a pts/ptc pair 125 * 126 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 127 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 128 * 129 * XXX: define and add mapping of upper minor bits to allow more 130 * than 256 ptys. 131 */ 132static dev_t 133ptyinit(dev_t devc) 134{ 135 dev_t devs; 136 struct pt_ioctl *pt; 137 int n; 138 139 n = minor(devc); 140 /* For now we only map the lower 8 bits of the minor */ 141 if (n & ~0xff) 142 return (NODEV); 143 144 devc->si_flags &= ~SI_CHEAPCLONE; 145 146 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); 147 pt->devs = devs = make_dev(&pts_cdevsw, n, 148 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32); 149 pt->devc = devc; 150
| 112 dev_t devs, devc; 113 struct prison *pt_prison; 114}; 115 116#define PF_PKT 0x08 /* packet mode */ 117#define PF_STOPPED 0x10 /* user told stopped */ 118#define PF_REMOTE 0x20 /* remote and flow controlled input */ 119#define PF_NOSTOP 0x40 120#define PF_UCNTL 0x80 /* user control mode */ 121 122static char *names = "pqrsPQRS"; 123/* 124 * This function creates and initializes a pts/ptc pair 125 * 126 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 127 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 128 * 129 * XXX: define and add mapping of upper minor bits to allow more 130 * than 256 ptys. 131 */ 132static dev_t 133ptyinit(dev_t devc) 134{ 135 dev_t devs; 136 struct pt_ioctl *pt; 137 int n; 138 139 n = minor(devc); 140 /* For now we only map the lower 8 bits of the minor */ 141 if (n & ~0xff) 142 return (NODEV); 143 144 devc->si_flags &= ~SI_CHEAPCLONE; 145 146 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); 147 pt->devs = devs = make_dev(&pts_cdevsw, n, 148 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32); 149 pt->devc = devc; 150
|
| 151 pt->pt_tty = ttymalloc(pt->pt_tty);
|
151 devs->si_drv1 = devc->si_drv1 = pt;
| 152 devs->si_drv1 = devc->si_drv1 = pt;
|
152 devs->si_tty = devc->si_tty = &pt->pt_tty; 153 pt->pt_tty.t_dev = devs; 154 ttyregister(&pt->pt_tty);
| 153 devs->si_tty = devc->si_tty = pt->pt_tty; 154 pt->pt_tty->t_dev = devs;
|
155 return (devc); 156} 157 158/*ARGSUSED*/ 159static int 160ptsopen(dev, flag, devtype, td) 161 dev_t dev; 162 int flag, devtype; 163 struct thread *td; 164{ 165 struct tty *tp; 166 int error; 167 struct pt_ioctl *pti; 168 169 if (!dev->si_drv1) 170 return(ENXIO); 171 pti = dev->si_drv1; 172 tp = dev->si_tty; 173 if ((tp->t_state & TS_ISOPEN) == 0) { 174 ttychars(tp); /* Set up default chars */ 175 tp->t_iflag = TTYDEF_IFLAG; 176 tp->t_oflag = TTYDEF_OFLAG; 177 tp->t_lflag = TTYDEF_LFLAG; 178 tp->t_cflag = TTYDEF_CFLAG; 179 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 180 } else if (tp->t_state & TS_XCLUDE && suser(td)) 181 return (EBUSY); 182 else if (pti->pt_prison != td->td_ucred->cr_prison) 183 return (EBUSY); 184 if (tp->t_oproc) /* Ctrlr still around. */ 185 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 186 while ((tp->t_state & TS_CARR_ON) == 0) { 187 if (flag&FNONBLOCK) 188 break; 189 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 190 "ptsopn", 0); 191 if (error) 192 return (error); 193 } 194 error = (*linesw[tp->t_line].l_open)(dev, tp); 195 if (error == 0) 196 ptcwakeup(tp, FREAD|FWRITE); 197 return (error); 198} 199 200static int 201ptsclose(dev, flag, mode, td) 202 dev_t dev; 203 int flag, mode; 204 struct thread *td; 205{ 206 struct tty *tp; 207 int err; 208 209 tp = dev->si_tty; 210 err = (*linesw[tp->t_line].l_close)(tp, flag); 211 (void) ttyclose(tp); 212 return (err); 213} 214 215static int 216ptsread(dev, uio, flag) 217 dev_t dev; 218 struct uio *uio; 219 int flag; 220{ 221 struct thread *td = curthread; 222 struct proc *p = td->td_proc; 223 struct tty *tp = dev->si_tty; 224 struct pt_ioctl *pti = dev->si_drv1; 225 struct pgrp *pg; 226 int error = 0; 227 228again: 229 if (pti->pt_flags & PF_REMOTE) { 230 while (isbackground(p, tp)) { 231 sx_slock(&proctree_lock); 232 PROC_LOCK(p); 233 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) || 234 SIGISMEMBER(td->td_sigmask, SIGTTIN) || 235 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) { 236 PROC_UNLOCK(p); 237 sx_sunlock(&proctree_lock); 238 return (EIO); 239 } 240 pg = p->p_pgrp; 241 PROC_UNLOCK(p); 242 PGRP_LOCK(pg); 243 sx_sunlock(&proctree_lock); 244 pgsignal(pg, SIGTTIN, 1); 245 PGRP_UNLOCK(pg); 246 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg", 247 0); 248 if (error) 249 return (error); 250 } 251 if (tp->t_canq.c_cc == 0) { 252 if (flag & IO_NDELAY) 253 return (EWOULDBLOCK); 254 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH, 255 "ptsin", 0); 256 if (error) 257 return (error); 258 goto again; 259 } 260 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 261 if (ureadc(getc(&tp->t_canq), uio) < 0) { 262 error = EFAULT; 263 break; 264 } 265 if (tp->t_canq.c_cc == 1) 266 (void) getc(&tp->t_canq); 267 if (tp->t_canq.c_cc) 268 return (error); 269 } else 270 if (tp->t_oproc) 271 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 272 ptcwakeup(tp, FWRITE); 273 return (error); 274} 275 276/* 277 * Write to pseudo-tty. 278 * Wakeups of controlling tty will happen 279 * indirectly, when tty driver calls ptsstart. 280 */ 281static int 282ptswrite(dev, uio, flag) 283 dev_t dev; 284 struct uio *uio; 285 int flag; 286{ 287 struct tty *tp; 288 289 tp = dev->si_tty; 290 if (tp->t_oproc == 0) 291 return (EIO); 292 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 293} 294 295/* 296 * Start output on pseudo-tty. 297 * Wake up process selecting or sleeping for input from controlling tty. 298 */ 299static void 300ptsstart(tp) 301 struct tty *tp; 302{ 303 struct pt_ioctl *pti = tp->t_dev->si_drv1; 304 305 if (tp->t_state & TS_TTSTOP) 306 return; 307 if (pti->pt_flags & PF_STOPPED) { 308 pti->pt_flags &= ~PF_STOPPED; 309 pti->pt_send = TIOCPKT_START; 310 } 311 ptcwakeup(tp, FREAD); 312} 313 314static void 315ptcwakeup(tp, flag) 316 struct tty *tp; 317 int flag; 318{ 319 struct pt_ioctl *pti = tp->t_dev->si_drv1; 320 321 if (flag & FREAD) { 322 selwakeuppri(&pti->pt_selr, TTIPRI); 323 wakeup(TSA_PTC_READ(tp)); 324 } 325 if (flag & FWRITE) { 326 selwakeuppri(&pti->pt_selw, TTOPRI); 327 wakeup(TSA_PTC_WRITE(tp)); 328 } 329} 330 331static int 332ptcopen(dev, flag, devtype, td) 333 dev_t dev; 334 int flag, devtype; 335 struct thread *td; 336{ 337 struct tty *tp; 338 struct pt_ioctl *pti; 339 340 if (!dev->si_drv1) 341 ptyinit(dev); 342 if (!dev->si_drv1) 343 return(ENXIO); 344 tp = dev->si_tty; 345 if (tp->t_oproc) 346 return (EIO); 347 tp->t_timeout = -1; 348 tp->t_oproc = ptsstart; 349 tp->t_stop = ptsstop; 350 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 351 tp->t_lflag &= ~EXTPROC; 352 pti = dev->si_drv1; 353 pti->pt_prison = td->td_ucred->cr_prison; 354 pti->pt_flags = 0; 355 pti->pt_send = 0; 356 pti->pt_ucntl = 0; 357 return (0); 358} 359 360static int 361ptcclose(dev, flags, fmt, td) 362 dev_t dev; 363 int flags; 364 int fmt; 365 struct thread *td; 366{ 367 struct tty *tp; 368 369 tp = dev->si_tty; 370 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 371 372 /* 373 * XXX MDMBUF makes no sense for ptys but would inhibit the above 374 * l_modem(). CLOCAL makes sense but isn't supported. Special 375 * l_modem()s that ignore carrier drop make no sense for ptys but 376 * may be in use because other parts of the line discipline make 377 * sense for ptys. Recover by doing everything that a normal 378 * ttymodem() would have done except for sending a SIGHUP. 379 */ 380 if (tp->t_state & TS_ISOPEN) { 381 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 382 tp->t_state |= TS_ZOMBIE; 383 ttyflush(tp, FREAD | FWRITE); 384 } 385 386 tp->t_oproc = 0; /* mark closed */ 387 return (0); 388} 389 390static int 391ptcread(dev, uio, flag) 392 dev_t dev; 393 struct uio *uio; 394 int flag; 395{ 396 struct tty *tp = dev->si_tty; 397 struct pt_ioctl *pti = dev->si_drv1; 398 char buf[BUFSIZ]; 399 int error = 0, cc; 400 401 /* 402 * We want to block until the slave 403 * is open, and there's something to read; 404 * but if we lost the slave or we're NBIO, 405 * then return the appropriate error instead. 406 */ 407 for (;;) { 408 if (tp->t_state&TS_ISOPEN) { 409 if (pti->pt_flags&PF_PKT && pti->pt_send) { 410 error = ureadc((int)pti->pt_send, uio); 411 if (error) 412 return (error); 413 if (pti->pt_send & TIOCPKT_IOCTL) { 414 cc = min(uio->uio_resid, 415 sizeof(tp->t_termios)); 416 uiomove(&tp->t_termios, cc, uio); 417 } 418 pti->pt_send = 0; 419 return (0); 420 } 421 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 422 error = ureadc((int)pti->pt_ucntl, uio); 423 if (error) 424 return (error); 425 pti->pt_ucntl = 0; 426 return (0); 427 } 428 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 429 break; 430 } 431 if ((tp->t_state & TS_CONNECTED) == 0) 432 return (0); /* EOF */ 433 if (flag & IO_NDELAY) 434 return (EWOULDBLOCK); 435 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0); 436 if (error) 437 return (error); 438 } 439 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 440 error = ureadc(0, uio); 441 while (uio->uio_resid > 0 && error == 0) { 442 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 443 if (cc <= 0) 444 break; 445 error = uiomove(buf, cc, uio); 446 } 447 ttwwakeup(tp); 448 return (error); 449} 450 451static void 452ptsstop(tp, flush) 453 struct tty *tp; 454 int flush; 455{ 456 struct pt_ioctl *pti = tp->t_dev->si_drv1; 457 int flag; 458 459 /* note: FLUSHREAD and FLUSHWRITE already ok */ 460 if (flush == 0) { 461 flush = TIOCPKT_STOP; 462 pti->pt_flags |= PF_STOPPED; 463 } else 464 pti->pt_flags &= ~PF_STOPPED; 465 pti->pt_send |= flush; 466 /* change of perspective */ 467 flag = 0; 468 if (flush & FREAD) 469 flag |= FWRITE; 470 if (flush & FWRITE) 471 flag |= FREAD; 472 ptcwakeup(tp, flag); 473} 474 475static int 476ptcpoll(dev, events, td) 477 dev_t dev; 478 int events; 479 struct thread *td; 480{ 481 struct tty *tp = dev->si_tty; 482 struct pt_ioctl *pti = dev->si_drv1; 483 int revents = 0; 484 int s; 485 486 if ((tp->t_state & TS_CONNECTED) == 0) 487 return (events & 488 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)); 489 490 /* 491 * Need to block timeouts (ttrstart). 492 */ 493 s = spltty(); 494 495 if (events & (POLLIN | POLLRDNORM)) 496 if ((tp->t_state & TS_ISOPEN) && 497 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 498 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 499 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 500 revents |= events & (POLLIN | POLLRDNORM); 501 502 if (events & (POLLOUT | POLLWRNORM)) 503 if (tp->t_state & TS_ISOPEN && 504 ((pti->pt_flags & PF_REMOTE) ? 505 (tp->t_canq.c_cc == 0) : 506 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 507 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON))))) 508 revents |= events & (POLLOUT | POLLWRNORM); 509 510 if (events & POLLHUP) 511 if ((tp->t_state & TS_CARR_ON) == 0) 512 revents |= POLLHUP; 513 514 if (revents == 0) { 515 if (events & (POLLIN | POLLRDNORM)) 516 selrecord(td, &pti->pt_selr); 517 518 if (events & (POLLOUT | POLLWRNORM)) 519 selrecord(td, &pti->pt_selw); 520 } 521 splx(s); 522 523 return (revents); 524} 525 526static int 527ptcwrite(dev, uio, flag) 528 dev_t dev; 529 struct uio *uio; 530 int flag; 531{ 532 struct tty *tp = dev->si_tty; 533 u_char *cp = 0; 534 int cc = 0; 535 u_char locbuf[BUFSIZ]; 536 int cnt = 0; 537 struct pt_ioctl *pti = dev->si_drv1; 538 int error = 0; 539 540again: 541 if ((tp->t_state&TS_ISOPEN) == 0) 542 goto block; 543 if (pti->pt_flags & PF_REMOTE) { 544 if (tp->t_canq.c_cc) 545 goto block; 546 while ((uio->uio_resid > 0 || cc > 0) && 547 tp->t_canq.c_cc < TTYHOG - 1) { 548 if (cc == 0) { 549 cc = min(uio->uio_resid, BUFSIZ); 550 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 551 cp = locbuf; 552 error = uiomove(cp, cc, uio); 553 if (error) 554 return (error); 555 /* check again for safety */ 556 if ((tp->t_state & TS_ISOPEN) == 0) { 557 /* adjust as usual */ 558 uio->uio_resid += cc; 559 return (EIO); 560 } 561 } 562 if (cc > 0) { 563 cc = b_to_q((char *)cp, cc, &tp->t_canq); 564 /* 565 * XXX we don't guarantee that the canq size 566 * is >= TTYHOG, so the above b_to_q() may 567 * leave some bytes uncopied. However, space 568 * is guaranteed for the null terminator if 569 * we don't fail here since (TTYHOG - 1) is 570 * not a multiple of CBSIZE. 571 */ 572 if (cc > 0) 573 break; 574 } 575 } 576 /* adjust for data copied in but not written */ 577 uio->uio_resid += cc; 578 (void) putc(0, &tp->t_canq); 579 ttwakeup(tp); 580 wakeup(TSA_PTS_READ(tp)); 581 return (0); 582 } 583 while (uio->uio_resid > 0 || cc > 0) { 584 if (cc == 0) { 585 cc = min(uio->uio_resid, BUFSIZ); 586 cp = locbuf; 587 error = uiomove(cp, cc, uio); 588 if (error) 589 return (error); 590 /* check again for safety */ 591 if ((tp->t_state & TS_ISOPEN) == 0) { 592 /* adjust for data copied in but not written */ 593 uio->uio_resid += cc; 594 return (EIO); 595 } 596 } 597 while (cc > 0) { 598 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 599 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { 600 wakeup(TSA_HUP_OR_INPUT(tp)); 601 goto block; 602 } 603 (*linesw[tp->t_line].l_rint)(*cp++, tp); 604 cnt++; 605 cc--; 606 } 607 cc = 0; 608 } 609 return (0); 610block: 611 /* 612 * Come here to wait for slave to open, for space 613 * in outq, or space in rawq, or an empty canq. 614 */ 615 if ((tp->t_state & TS_CONNECTED) == 0) { 616 /* adjust for data copied in but not written */ 617 uio->uio_resid += cc; 618 return (EIO); 619 } 620 if (flag & IO_NDELAY) { 621 /* adjust for data copied in but not written */ 622 uio->uio_resid += cc; 623 if (cnt == 0) 624 return (EWOULDBLOCK); 625 return (0); 626 } 627 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 628 if (error) { 629 /* adjust for data copied in but not written */ 630 uio->uio_resid += cc; 631 return (error); 632 } 633 goto again; 634} 635 636/*ARGSUSED*/ 637static int 638ptyioctl(dev, cmd, data, flag, td) 639 dev_t dev; 640 u_long cmd; 641 caddr_t data; 642 int flag; 643 struct thread *td; 644{ 645 struct tty *tp = dev->si_tty; 646 struct pt_ioctl *pti = dev->si_drv1; 647 u_char *cc = tp->t_cc; 648 int stop, error; 649 650 if (devsw(dev)->d_open == ptcopen) { 651 switch (cmd) { 652 653 case TIOCGPGRP: 654 /* 655 * We avoid calling ttioctl on the controller since, 656 * in that case, tp must be the controlling terminal. 657 */ 658 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 659 return (0); 660 661 case TIOCPKT: 662 if (*(int *)data) { 663 if (pti->pt_flags & PF_UCNTL) 664 return (EINVAL); 665 pti->pt_flags |= PF_PKT; 666 } else 667 pti->pt_flags &= ~PF_PKT; 668 return (0); 669 670 case TIOCUCNTL: 671 if (*(int *)data) { 672 if (pti->pt_flags & PF_PKT) 673 return (EINVAL); 674 pti->pt_flags |= PF_UCNTL; 675 } else 676 pti->pt_flags &= ~PF_UCNTL; 677 return (0); 678 679 case TIOCREMOTE: 680 if (*(int *)data) 681 pti->pt_flags |= PF_REMOTE; 682 else 683 pti->pt_flags &= ~PF_REMOTE; 684 ttyflush(tp, FREAD|FWRITE); 685 return (0); 686 } 687 688 /* 689 * The rest of the ioctls shouldn't be called until 690 * the slave is open. 691 */ 692 if ((tp->t_state & TS_ISOPEN) == 0) 693 return (EAGAIN); 694 695 switch (cmd) { 696#ifdef COMPAT_43 697 case TIOCSETP: 698 case TIOCSETN: 699#endif 700 case TIOCSETD: 701 case TIOCSETA: 702 case TIOCSETAW: 703 case TIOCSETAF: 704 /* 705 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 706 * ttywflush(tp) will hang if there are characters in 707 * the outq. 708 */ 709 ndflush(&tp->t_outq, tp->t_outq.c_cc); 710 break; 711 712 case TIOCSIG: 713 if (*(unsigned int *)data >= NSIG || 714 *(unsigned int *)data == 0) 715 return(EINVAL); 716 if ((tp->t_lflag&NOFLSH) == 0) 717 ttyflush(tp, FREAD|FWRITE); 718 if (tp->t_pgrp != NULL) { 719 PGRP_LOCK(tp->t_pgrp); 720 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 721 PGRP_UNLOCK(tp->t_pgrp); 722 } 723 if ((*(unsigned int *)data == SIGINFO) && 724 ((tp->t_lflag&NOKERNINFO) == 0)) 725 ttyinfo(tp); 726 return(0); 727 } 728 } 729 if (cmd == TIOCEXT) { 730 /* 731 * When the EXTPROC bit is being toggled, we need 732 * to send an TIOCPKT_IOCTL if the packet driver 733 * is turned on. 734 */ 735 if (*(int *)data) { 736 if (pti->pt_flags & PF_PKT) { 737 pti->pt_send |= TIOCPKT_IOCTL; 738 ptcwakeup(tp, FREAD); 739 } 740 tp->t_lflag |= EXTPROC; 741 } else { 742 if ((tp->t_lflag & EXTPROC) && 743 (pti->pt_flags & PF_PKT)) { 744 pti->pt_send |= TIOCPKT_IOCTL; 745 ptcwakeup(tp, FREAD); 746 } 747 tp->t_lflag &= ~EXTPROC; 748 } 749 return(0); 750 }
| 155 return (devc); 156} 157 158/*ARGSUSED*/ 159static int 160ptsopen(dev, flag, devtype, td) 161 dev_t dev; 162 int flag, devtype; 163 struct thread *td; 164{ 165 struct tty *tp; 166 int error; 167 struct pt_ioctl *pti; 168 169 if (!dev->si_drv1) 170 return(ENXIO); 171 pti = dev->si_drv1; 172 tp = dev->si_tty; 173 if ((tp->t_state & TS_ISOPEN) == 0) { 174 ttychars(tp); /* Set up default chars */ 175 tp->t_iflag = TTYDEF_IFLAG; 176 tp->t_oflag = TTYDEF_OFLAG; 177 tp->t_lflag = TTYDEF_LFLAG; 178 tp->t_cflag = TTYDEF_CFLAG; 179 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 180 } else if (tp->t_state & TS_XCLUDE && suser(td)) 181 return (EBUSY); 182 else if (pti->pt_prison != td->td_ucred->cr_prison) 183 return (EBUSY); 184 if (tp->t_oproc) /* Ctrlr still around. */ 185 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 186 while ((tp->t_state & TS_CARR_ON) == 0) { 187 if (flag&FNONBLOCK) 188 break; 189 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 190 "ptsopn", 0); 191 if (error) 192 return (error); 193 } 194 error = (*linesw[tp->t_line].l_open)(dev, tp); 195 if (error == 0) 196 ptcwakeup(tp, FREAD|FWRITE); 197 return (error); 198} 199 200static int 201ptsclose(dev, flag, mode, td) 202 dev_t dev; 203 int flag, mode; 204 struct thread *td; 205{ 206 struct tty *tp; 207 int err; 208 209 tp = dev->si_tty; 210 err = (*linesw[tp->t_line].l_close)(tp, flag); 211 (void) ttyclose(tp); 212 return (err); 213} 214 215static int 216ptsread(dev, uio, flag) 217 dev_t dev; 218 struct uio *uio; 219 int flag; 220{ 221 struct thread *td = curthread; 222 struct proc *p = td->td_proc; 223 struct tty *tp = dev->si_tty; 224 struct pt_ioctl *pti = dev->si_drv1; 225 struct pgrp *pg; 226 int error = 0; 227 228again: 229 if (pti->pt_flags & PF_REMOTE) { 230 while (isbackground(p, tp)) { 231 sx_slock(&proctree_lock); 232 PROC_LOCK(p); 233 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) || 234 SIGISMEMBER(td->td_sigmask, SIGTTIN) || 235 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) { 236 PROC_UNLOCK(p); 237 sx_sunlock(&proctree_lock); 238 return (EIO); 239 } 240 pg = p->p_pgrp; 241 PROC_UNLOCK(p); 242 PGRP_LOCK(pg); 243 sx_sunlock(&proctree_lock); 244 pgsignal(pg, SIGTTIN, 1); 245 PGRP_UNLOCK(pg); 246 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg", 247 0); 248 if (error) 249 return (error); 250 } 251 if (tp->t_canq.c_cc == 0) { 252 if (flag & IO_NDELAY) 253 return (EWOULDBLOCK); 254 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH, 255 "ptsin", 0); 256 if (error) 257 return (error); 258 goto again; 259 } 260 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 261 if (ureadc(getc(&tp->t_canq), uio) < 0) { 262 error = EFAULT; 263 break; 264 } 265 if (tp->t_canq.c_cc == 1) 266 (void) getc(&tp->t_canq); 267 if (tp->t_canq.c_cc) 268 return (error); 269 } else 270 if (tp->t_oproc) 271 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 272 ptcwakeup(tp, FWRITE); 273 return (error); 274} 275 276/* 277 * Write to pseudo-tty. 278 * Wakeups of controlling tty will happen 279 * indirectly, when tty driver calls ptsstart. 280 */ 281static int 282ptswrite(dev, uio, flag) 283 dev_t dev; 284 struct uio *uio; 285 int flag; 286{ 287 struct tty *tp; 288 289 tp = dev->si_tty; 290 if (tp->t_oproc == 0) 291 return (EIO); 292 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 293} 294 295/* 296 * Start output on pseudo-tty. 297 * Wake up process selecting or sleeping for input from controlling tty. 298 */ 299static void 300ptsstart(tp) 301 struct tty *tp; 302{ 303 struct pt_ioctl *pti = tp->t_dev->si_drv1; 304 305 if (tp->t_state & TS_TTSTOP) 306 return; 307 if (pti->pt_flags & PF_STOPPED) { 308 pti->pt_flags &= ~PF_STOPPED; 309 pti->pt_send = TIOCPKT_START; 310 } 311 ptcwakeup(tp, FREAD); 312} 313 314static void 315ptcwakeup(tp, flag) 316 struct tty *tp; 317 int flag; 318{ 319 struct pt_ioctl *pti = tp->t_dev->si_drv1; 320 321 if (flag & FREAD) { 322 selwakeuppri(&pti->pt_selr, TTIPRI); 323 wakeup(TSA_PTC_READ(tp)); 324 } 325 if (flag & FWRITE) { 326 selwakeuppri(&pti->pt_selw, TTOPRI); 327 wakeup(TSA_PTC_WRITE(tp)); 328 } 329} 330 331static int 332ptcopen(dev, flag, devtype, td) 333 dev_t dev; 334 int flag, devtype; 335 struct thread *td; 336{ 337 struct tty *tp; 338 struct pt_ioctl *pti; 339 340 if (!dev->si_drv1) 341 ptyinit(dev); 342 if (!dev->si_drv1) 343 return(ENXIO); 344 tp = dev->si_tty; 345 if (tp->t_oproc) 346 return (EIO); 347 tp->t_timeout = -1; 348 tp->t_oproc = ptsstart; 349 tp->t_stop = ptsstop; 350 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 351 tp->t_lflag &= ~EXTPROC; 352 pti = dev->si_drv1; 353 pti->pt_prison = td->td_ucred->cr_prison; 354 pti->pt_flags = 0; 355 pti->pt_send = 0; 356 pti->pt_ucntl = 0; 357 return (0); 358} 359 360static int 361ptcclose(dev, flags, fmt, td) 362 dev_t dev; 363 int flags; 364 int fmt; 365 struct thread *td; 366{ 367 struct tty *tp; 368 369 tp = dev->si_tty; 370 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 371 372 /* 373 * XXX MDMBUF makes no sense for ptys but would inhibit the above 374 * l_modem(). CLOCAL makes sense but isn't supported. Special 375 * l_modem()s that ignore carrier drop make no sense for ptys but 376 * may be in use because other parts of the line discipline make 377 * sense for ptys. Recover by doing everything that a normal 378 * ttymodem() would have done except for sending a SIGHUP. 379 */ 380 if (tp->t_state & TS_ISOPEN) { 381 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 382 tp->t_state |= TS_ZOMBIE; 383 ttyflush(tp, FREAD | FWRITE); 384 } 385 386 tp->t_oproc = 0; /* mark closed */ 387 return (0); 388} 389 390static int 391ptcread(dev, uio, flag) 392 dev_t dev; 393 struct uio *uio; 394 int flag; 395{ 396 struct tty *tp = dev->si_tty; 397 struct pt_ioctl *pti = dev->si_drv1; 398 char buf[BUFSIZ]; 399 int error = 0, cc; 400 401 /* 402 * We want to block until the slave 403 * is open, and there's something to read; 404 * but if we lost the slave or we're NBIO, 405 * then return the appropriate error instead. 406 */ 407 for (;;) { 408 if (tp->t_state&TS_ISOPEN) { 409 if (pti->pt_flags&PF_PKT && pti->pt_send) { 410 error = ureadc((int)pti->pt_send, uio); 411 if (error) 412 return (error); 413 if (pti->pt_send & TIOCPKT_IOCTL) { 414 cc = min(uio->uio_resid, 415 sizeof(tp->t_termios)); 416 uiomove(&tp->t_termios, cc, uio); 417 } 418 pti->pt_send = 0; 419 return (0); 420 } 421 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 422 error = ureadc((int)pti->pt_ucntl, uio); 423 if (error) 424 return (error); 425 pti->pt_ucntl = 0; 426 return (0); 427 } 428 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 429 break; 430 } 431 if ((tp->t_state & TS_CONNECTED) == 0) 432 return (0); /* EOF */ 433 if (flag & IO_NDELAY) 434 return (EWOULDBLOCK); 435 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0); 436 if (error) 437 return (error); 438 } 439 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 440 error = ureadc(0, uio); 441 while (uio->uio_resid > 0 && error == 0) { 442 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 443 if (cc <= 0) 444 break; 445 error = uiomove(buf, cc, uio); 446 } 447 ttwwakeup(tp); 448 return (error); 449} 450 451static void 452ptsstop(tp, flush) 453 struct tty *tp; 454 int flush; 455{ 456 struct pt_ioctl *pti = tp->t_dev->si_drv1; 457 int flag; 458 459 /* note: FLUSHREAD and FLUSHWRITE already ok */ 460 if (flush == 0) { 461 flush = TIOCPKT_STOP; 462 pti->pt_flags |= PF_STOPPED; 463 } else 464 pti->pt_flags &= ~PF_STOPPED; 465 pti->pt_send |= flush; 466 /* change of perspective */ 467 flag = 0; 468 if (flush & FREAD) 469 flag |= FWRITE; 470 if (flush & FWRITE) 471 flag |= FREAD; 472 ptcwakeup(tp, flag); 473} 474 475static int 476ptcpoll(dev, events, td) 477 dev_t dev; 478 int events; 479 struct thread *td; 480{ 481 struct tty *tp = dev->si_tty; 482 struct pt_ioctl *pti = dev->si_drv1; 483 int revents = 0; 484 int s; 485 486 if ((tp->t_state & TS_CONNECTED) == 0) 487 return (events & 488 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)); 489 490 /* 491 * Need to block timeouts (ttrstart). 492 */ 493 s = spltty(); 494 495 if (events & (POLLIN | POLLRDNORM)) 496 if ((tp->t_state & TS_ISOPEN) && 497 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 498 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 499 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 500 revents |= events & (POLLIN | POLLRDNORM); 501 502 if (events & (POLLOUT | POLLWRNORM)) 503 if (tp->t_state & TS_ISOPEN && 504 ((pti->pt_flags & PF_REMOTE) ? 505 (tp->t_canq.c_cc == 0) : 506 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 507 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON))))) 508 revents |= events & (POLLOUT | POLLWRNORM); 509 510 if (events & POLLHUP) 511 if ((tp->t_state & TS_CARR_ON) == 0) 512 revents |= POLLHUP; 513 514 if (revents == 0) { 515 if (events & (POLLIN | POLLRDNORM)) 516 selrecord(td, &pti->pt_selr); 517 518 if (events & (POLLOUT | POLLWRNORM)) 519 selrecord(td, &pti->pt_selw); 520 } 521 splx(s); 522 523 return (revents); 524} 525 526static int 527ptcwrite(dev, uio, flag) 528 dev_t dev; 529 struct uio *uio; 530 int flag; 531{ 532 struct tty *tp = dev->si_tty; 533 u_char *cp = 0; 534 int cc = 0; 535 u_char locbuf[BUFSIZ]; 536 int cnt = 0; 537 struct pt_ioctl *pti = dev->si_drv1; 538 int error = 0; 539 540again: 541 if ((tp->t_state&TS_ISOPEN) == 0) 542 goto block; 543 if (pti->pt_flags & PF_REMOTE) { 544 if (tp->t_canq.c_cc) 545 goto block; 546 while ((uio->uio_resid > 0 || cc > 0) && 547 tp->t_canq.c_cc < TTYHOG - 1) { 548 if (cc == 0) { 549 cc = min(uio->uio_resid, BUFSIZ); 550 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 551 cp = locbuf; 552 error = uiomove(cp, cc, uio); 553 if (error) 554 return (error); 555 /* check again for safety */ 556 if ((tp->t_state & TS_ISOPEN) == 0) { 557 /* adjust as usual */ 558 uio->uio_resid += cc; 559 return (EIO); 560 } 561 } 562 if (cc > 0) { 563 cc = b_to_q((char *)cp, cc, &tp->t_canq); 564 /* 565 * XXX we don't guarantee that the canq size 566 * is >= TTYHOG, so the above b_to_q() may 567 * leave some bytes uncopied. However, space 568 * is guaranteed for the null terminator if 569 * we don't fail here since (TTYHOG - 1) is 570 * not a multiple of CBSIZE. 571 */ 572 if (cc > 0) 573 break; 574 } 575 } 576 /* adjust for data copied in but not written */ 577 uio->uio_resid += cc; 578 (void) putc(0, &tp->t_canq); 579 ttwakeup(tp); 580 wakeup(TSA_PTS_READ(tp)); 581 return (0); 582 } 583 while (uio->uio_resid > 0 || cc > 0) { 584 if (cc == 0) { 585 cc = min(uio->uio_resid, BUFSIZ); 586 cp = locbuf; 587 error = uiomove(cp, cc, uio); 588 if (error) 589 return (error); 590 /* check again for safety */ 591 if ((tp->t_state & TS_ISOPEN) == 0) { 592 /* adjust for data copied in but not written */ 593 uio->uio_resid += cc; 594 return (EIO); 595 } 596 } 597 while (cc > 0) { 598 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 599 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { 600 wakeup(TSA_HUP_OR_INPUT(tp)); 601 goto block; 602 } 603 (*linesw[tp->t_line].l_rint)(*cp++, tp); 604 cnt++; 605 cc--; 606 } 607 cc = 0; 608 } 609 return (0); 610block: 611 /* 612 * Come here to wait for slave to open, for space 613 * in outq, or space in rawq, or an empty canq. 614 */ 615 if ((tp->t_state & TS_CONNECTED) == 0) { 616 /* adjust for data copied in but not written */ 617 uio->uio_resid += cc; 618 return (EIO); 619 } 620 if (flag & IO_NDELAY) { 621 /* adjust for data copied in but not written */ 622 uio->uio_resid += cc; 623 if (cnt == 0) 624 return (EWOULDBLOCK); 625 return (0); 626 } 627 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 628 if (error) { 629 /* adjust for data copied in but not written */ 630 uio->uio_resid += cc; 631 return (error); 632 } 633 goto again; 634} 635 636/*ARGSUSED*/ 637static int 638ptyioctl(dev, cmd, data, flag, td) 639 dev_t dev; 640 u_long cmd; 641 caddr_t data; 642 int flag; 643 struct thread *td; 644{ 645 struct tty *tp = dev->si_tty; 646 struct pt_ioctl *pti = dev->si_drv1; 647 u_char *cc = tp->t_cc; 648 int stop, error; 649 650 if (devsw(dev)->d_open == ptcopen) { 651 switch (cmd) { 652 653 case TIOCGPGRP: 654 /* 655 * We avoid calling ttioctl on the controller since, 656 * in that case, tp must be the controlling terminal. 657 */ 658 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 659 return (0); 660 661 case TIOCPKT: 662 if (*(int *)data) { 663 if (pti->pt_flags & PF_UCNTL) 664 return (EINVAL); 665 pti->pt_flags |= PF_PKT; 666 } else 667 pti->pt_flags &= ~PF_PKT; 668 return (0); 669 670 case TIOCUCNTL: 671 if (*(int *)data) { 672 if (pti->pt_flags & PF_PKT) 673 return (EINVAL); 674 pti->pt_flags |= PF_UCNTL; 675 } else 676 pti->pt_flags &= ~PF_UCNTL; 677 return (0); 678 679 case TIOCREMOTE: 680 if (*(int *)data) 681 pti->pt_flags |= PF_REMOTE; 682 else 683 pti->pt_flags &= ~PF_REMOTE; 684 ttyflush(tp, FREAD|FWRITE); 685 return (0); 686 } 687 688 /* 689 * The rest of the ioctls shouldn't be called until 690 * the slave is open. 691 */ 692 if ((tp->t_state & TS_ISOPEN) == 0) 693 return (EAGAIN); 694 695 switch (cmd) { 696#ifdef COMPAT_43 697 case TIOCSETP: 698 case TIOCSETN: 699#endif 700 case TIOCSETD: 701 case TIOCSETA: 702 case TIOCSETAW: 703 case TIOCSETAF: 704 /* 705 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 706 * ttywflush(tp) will hang if there are characters in 707 * the outq. 708 */ 709 ndflush(&tp->t_outq, tp->t_outq.c_cc); 710 break; 711 712 case TIOCSIG: 713 if (*(unsigned int *)data >= NSIG || 714 *(unsigned int *)data == 0) 715 return(EINVAL); 716 if ((tp->t_lflag&NOFLSH) == 0) 717 ttyflush(tp, FREAD|FWRITE); 718 if (tp->t_pgrp != NULL) { 719 PGRP_LOCK(tp->t_pgrp); 720 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 721 PGRP_UNLOCK(tp->t_pgrp); 722 } 723 if ((*(unsigned int *)data == SIGINFO) && 724 ((tp->t_lflag&NOKERNINFO) == 0)) 725 ttyinfo(tp); 726 return(0); 727 } 728 } 729 if (cmd == TIOCEXT) { 730 /* 731 * When the EXTPROC bit is being toggled, we need 732 * to send an TIOCPKT_IOCTL if the packet driver 733 * is turned on. 734 */ 735 if (*(int *)data) { 736 if (pti->pt_flags & PF_PKT) { 737 pti->pt_send |= TIOCPKT_IOCTL; 738 ptcwakeup(tp, FREAD); 739 } 740 tp->t_lflag |= EXTPROC; 741 } else { 742 if ((tp->t_lflag & EXTPROC) && 743 (pti->pt_flags & PF_PKT)) { 744 pti->pt_send |= TIOCPKT_IOCTL; 745 ptcwakeup(tp, FREAD); 746 } 747 tp->t_lflag &= ~EXTPROC; 748 } 749 return(0); 750 }
|
751 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 752 if (error == ENOIOCTL) 753 error = ttioctl(tp, cmd, data, flag); 754 if (error == ENOIOCTL) {
| 751 error = ttyioctl(dev, cmd, data, flag, td); 752 if (error == ENOTTY) {
|
755 if (pti->pt_flags & PF_UCNTL && 756 (cmd & ~0xff) == UIOCCMD(0)) { 757 if (cmd & 0xff) { 758 pti->pt_ucntl = (u_char)cmd; 759 ptcwakeup(tp, FREAD); 760 } 761 return (0); 762 } 763 error = ENOTTY; 764 } 765 /* 766 * If external processing and packet mode send ioctl packet. 767 */ 768 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 769 switch(cmd) { 770 case TIOCSETA: 771 case TIOCSETAW: 772 case TIOCSETAF: 773#ifdef COMPAT_43 774 case TIOCSETP: 775 case TIOCSETN: 776#endif 777#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 778 case TIOCSETC: 779 case TIOCSLTC: 780 case TIOCLBIS: 781 case TIOCLBIC: 782 case TIOCLSET: 783#endif 784 pti->pt_send |= TIOCPKT_IOCTL; 785 ptcwakeup(tp, FREAD); 786 break; 787 default: 788 break; 789 } 790 } 791 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 792 && CCEQ(cc[VSTART], CTRL('q')); 793 if (pti->pt_flags & PF_NOSTOP) { 794 if (stop) { 795 pti->pt_send &= ~TIOCPKT_NOSTOP; 796 pti->pt_send |= TIOCPKT_DOSTOP; 797 pti->pt_flags &= ~PF_NOSTOP; 798 ptcwakeup(tp, FREAD); 799 } 800 } else { 801 if (!stop) { 802 pti->pt_send &= ~TIOCPKT_DOSTOP; 803 pti->pt_send |= TIOCPKT_NOSTOP; 804 pti->pt_flags |= PF_NOSTOP; 805 ptcwakeup(tp, FREAD); 806 } 807 } 808 return (error); 809} 810 811 812static void ptc_drvinit(void *unused); 813 814static void pty_clone(void *arg, char *name, int namelen, dev_t *dev); 815 816static void 817pty_clone(arg, name, namelen, dev) 818 void *arg; 819 char *name; 820 int namelen; 821 dev_t *dev; 822{ 823 int u; 824 825 if (*dev != NODEV) 826 return; 827 if (bcmp(name, "pty", 3) != 0) 828 return; 829 if (name[5] != '\0') 830 return; 831 switch (name[3]) { 832 case 'p': u = 0; break; 833 case 'q': u = 32; break; 834 case 'r': u = 64; break; 835 case 's': u = 96; break; 836 case 'P': u = 128; break; 837 case 'Q': u = 160; break; 838 case 'R': u = 192; break; 839 case 'S': u = 224; break; 840 default: return; 841 } 842 if (name[4] >= '0' && name[4] <= '9') 843 u += name[4] - '0'; 844 else if (name[4] >= 'a' && name[4] <= 'v') 845 u += name[4] - 'a' + 10; 846 else 847 return; 848 *dev = make_dev(&ptc_cdevsw, u, 849 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32); 850 (*dev)->si_flags |= SI_CHEAPCLONE; 851 return; 852} 853 854static void 855ptc_drvinit(unused) 856 void *unused; 857{ 858 859 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); 860} 861 862SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
| 753 if (pti->pt_flags & PF_UCNTL && 754 (cmd & ~0xff) == UIOCCMD(0)) { 755 if (cmd & 0xff) { 756 pti->pt_ucntl = (u_char)cmd; 757 ptcwakeup(tp, FREAD); 758 } 759 return (0); 760 } 761 error = ENOTTY; 762 } 763 /* 764 * If external processing and packet mode send ioctl packet. 765 */ 766 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 767 switch(cmd) { 768 case TIOCSETA: 769 case TIOCSETAW: 770 case TIOCSETAF: 771#ifdef COMPAT_43 772 case TIOCSETP: 773 case TIOCSETN: 774#endif 775#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 776 case TIOCSETC: 777 case TIOCSLTC: 778 case TIOCLBIS: 779 case TIOCLBIC: 780 case TIOCLSET: 781#endif 782 pti->pt_send |= TIOCPKT_IOCTL; 783 ptcwakeup(tp, FREAD); 784 break; 785 default: 786 break; 787 } 788 } 789 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 790 && CCEQ(cc[VSTART], CTRL('q')); 791 if (pti->pt_flags & PF_NOSTOP) { 792 if (stop) { 793 pti->pt_send &= ~TIOCPKT_NOSTOP; 794 pti->pt_send |= TIOCPKT_DOSTOP; 795 pti->pt_flags &= ~PF_NOSTOP; 796 ptcwakeup(tp, FREAD); 797 } 798 } else { 799 if (!stop) { 800 pti->pt_send &= ~TIOCPKT_DOSTOP; 801 pti->pt_send |= TIOCPKT_NOSTOP; 802 pti->pt_flags |= PF_NOSTOP; 803 ptcwakeup(tp, FREAD); 804 } 805 } 806 return (error); 807} 808 809 810static void ptc_drvinit(void *unused); 811 812static void pty_clone(void *arg, char *name, int namelen, dev_t *dev); 813 814static void 815pty_clone(arg, name, namelen, dev) 816 void *arg; 817 char *name; 818 int namelen; 819 dev_t *dev; 820{ 821 int u; 822 823 if (*dev != NODEV) 824 return; 825 if (bcmp(name, "pty", 3) != 0) 826 return; 827 if (name[5] != '\0') 828 return; 829 switch (name[3]) { 830 case 'p': u = 0; break; 831 case 'q': u = 32; break; 832 case 'r': u = 64; break; 833 case 's': u = 96; break; 834 case 'P': u = 128; break; 835 case 'Q': u = 160; break; 836 case 'R': u = 192; break; 837 case 'S': u = 224; break; 838 default: return; 839 } 840 if (name[4] >= '0' && name[4] <= '9') 841 u += name[4] - '0'; 842 else if (name[4] >= 'a' && name[4] <= 'v') 843 u += name[4] - 'a' + 10; 844 else 845 return; 846 *dev = make_dev(&ptc_cdevsw, u, 847 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32); 848 (*dev)->si_flags |= SI_CHEAPCLONE; 849 return; 850} 851 852static void 853ptc_drvinit(unused) 854 void *unused; 855{ 856 857 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); 858} 859 860SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
|