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>
|
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#ifndef BURN_BRIDGES 47#if defined(COMPAT_43) 48#include <sys/ioctl_compat.h> 49#endif 50#endif 51#include <sys/proc.h> 52#include <sys/tty.h> 53#include <sys/conf.h> 54#include <sys/fcntl.h> 55#include <sys/poll.h> 56#include <sys/kernel.h> 57#include <sys/uio.h> 58#include <sys/signalvar.h> 59#include <sys/malloc.h> 60 61static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures"); 62 63static void ptsstart(struct tty *tp); 64static void ptsstop(struct tty *tp, int rw); 65static void ptcwakeup(struct tty *tp, int flag); 66static struct cdev *ptyinit(struct cdev *cdev, struct thread *td); 67 68static d_open_t ptsopen; 69static d_close_t ptsclose; 70static d_read_t ptsread; 71static d_write_t ptswrite; 72static d_ioctl_t ptsioctl; 73static d_open_t ptcopen; 74static d_close_t ptcclose; 75static d_read_t ptcread; 76static d_ioctl_t ptcioctl; 77static d_write_t ptcwrite; 78static d_poll_t ptcpoll; 79 80static struct cdevsw pts_cdevsw = { 81 .d_version = D_VERSION, 82 .d_open = ptsopen, 83 .d_close = ptsclose, 84 .d_read = ptsread, 85 .d_write = ptswrite, 86 .d_ioctl = ptsioctl, 87 .d_name = "pts", 88 .d_flags = D_TTY | D_NEEDGIANT, 89}; 90 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 = ptcioctl, 98 .d_poll = ptcpoll, 99 .d_name = "ptc", 100 .d_flags = D_TTY | D_NEEDGIANT, 101}; 102 103#define BUFSIZ 100 /* Chunk size iomoved to/from user */ 104 105struct ptsc { 106 int pt_flags; 107 struct selinfo pt_selr, pt_selw; 108 u_char pt_send; 109 u_char pt_ucntl; 110 struct tty *pt_tty; 111 struct cdev *devs, *devc; 112 struct prison *pt_prison; 113}; 114 115#define PF_PKT 0x08 /* packet mode */ 116#define PF_STOPPED 0x10 /* user told stopped */ 117#define PF_NOSTOP 0x40 118#define PF_UCNTL 0x80 /* user control mode */ 119 120#define TSA_PTC_READ(tp) ((void *)&(tp)->t_outq.c_cf) 121#define TSA_PTC_WRITE(tp) ((void *)&(tp)->t_rawq.c_cl) 122#define TSA_PTS_READ(tp) ((void *)&(tp)->t_canq) 123 124static char *names = "pqrsPQRS"; 125/* 126 * This function creates and initializes a pts/ptc pair 127 * 128 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 129 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 130 * 131 * XXX: define and add mapping of upper minor bits to allow more 132 * than 256 ptys. 133 */ 134static struct cdev * 135ptyinit(struct cdev *devc, struct thread *td) 136{ 137 struct cdev *devs; 138 struct ptsc *pt; 139 int n; 140 141 n = minor(devc); 142 /* For now we only map the lower 8 bits of the minor */ 143 if (n & ~0xff) 144 return (NULL); 145 146 devc->si_flags &= ~SI_CHEAPCLONE; 147 148 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); 149 pt->devs = devs = make_dev_cred(&pts_cdevsw, n, td->td_ucred, 150 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32); 151 pt->devc = devc; 152
| 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#ifndef BURN_BRIDGES 47#if defined(COMPAT_43) 48#include <sys/ioctl_compat.h> 49#endif 50#endif 51#include <sys/proc.h> 52#include <sys/tty.h> 53#include <sys/conf.h> 54#include <sys/fcntl.h> 55#include <sys/poll.h> 56#include <sys/kernel.h> 57#include <sys/uio.h> 58#include <sys/signalvar.h> 59#include <sys/malloc.h> 60 61static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures"); 62 63static void ptsstart(struct tty *tp); 64static void ptsstop(struct tty *tp, int rw); 65static void ptcwakeup(struct tty *tp, int flag); 66static struct cdev *ptyinit(struct cdev *cdev, struct thread *td); 67 68static d_open_t ptsopen; 69static d_close_t ptsclose; 70static d_read_t ptsread; 71static d_write_t ptswrite; 72static d_ioctl_t ptsioctl; 73static d_open_t ptcopen; 74static d_close_t ptcclose; 75static d_read_t ptcread; 76static d_ioctl_t ptcioctl; 77static d_write_t ptcwrite; 78static d_poll_t ptcpoll; 79 80static struct cdevsw pts_cdevsw = { 81 .d_version = D_VERSION, 82 .d_open = ptsopen, 83 .d_close = ptsclose, 84 .d_read = ptsread, 85 .d_write = ptswrite, 86 .d_ioctl = ptsioctl, 87 .d_name = "pts", 88 .d_flags = D_TTY | D_NEEDGIANT, 89}; 90 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 = ptcioctl, 98 .d_poll = ptcpoll, 99 .d_name = "ptc", 100 .d_flags = D_TTY | D_NEEDGIANT, 101}; 102 103#define BUFSIZ 100 /* Chunk size iomoved to/from user */ 104 105struct ptsc { 106 int pt_flags; 107 struct selinfo pt_selr, pt_selw; 108 u_char pt_send; 109 u_char pt_ucntl; 110 struct tty *pt_tty; 111 struct cdev *devs, *devc; 112 struct prison *pt_prison; 113}; 114 115#define PF_PKT 0x08 /* packet mode */ 116#define PF_STOPPED 0x10 /* user told stopped */ 117#define PF_NOSTOP 0x40 118#define PF_UCNTL 0x80 /* user control mode */ 119 120#define TSA_PTC_READ(tp) ((void *)&(tp)->t_outq.c_cf) 121#define TSA_PTC_WRITE(tp) ((void *)&(tp)->t_rawq.c_cl) 122#define TSA_PTS_READ(tp) ((void *)&(tp)->t_canq) 123 124static char *names = "pqrsPQRS"; 125/* 126 * This function creates and initializes a pts/ptc pair 127 * 128 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 129 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 130 * 131 * XXX: define and add mapping of upper minor bits to allow more 132 * than 256 ptys. 133 */ 134static struct cdev * 135ptyinit(struct cdev *devc, struct thread *td) 136{ 137 struct cdev *devs; 138 struct ptsc *pt; 139 int n; 140 141 n = minor(devc); 142 /* For now we only map the lower 8 bits of the minor */ 143 if (n & ~0xff) 144 return (NULL); 145 146 devc->si_flags &= ~SI_CHEAPCLONE; 147 148 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); 149 pt->devs = devs = make_dev_cred(&pts_cdevsw, n, td->td_ucred, 150 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32); 151 pt->devc = devc; 152
|
154 pt->pt_tty->t_sc = pt; 155 devs->si_drv1 = devc->si_drv1 = pt; 156 devs->si_tty = devc->si_tty = pt->pt_tty; 157 pt->pt_tty->t_dev = devs; 158 return (devc); 159} 160 161/*ARGSUSED*/ 162static int 163ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td) 164{ 165 struct tty *tp; 166 int error; 167 struct ptsc *pt; 168 169 if (!dev->si_drv1) 170 return(ENXIO); 171 pt = dev->si_drv1; 172 tp = dev->si_tty; 173 if ((tp->t_state & TS_ISOPEN) == 0) { 174 ttyinitmode(tp, 1, 0); 175 } else if (tp->t_state & TS_XCLUDE && suser(td)) 176 return (EBUSY); 177 else if (pt->pt_prison != td->td_ucred->cr_prison) 178 return (EBUSY); 179 if (tp->t_oproc) /* Ctrlr still around. */ 180 (void)ttyld_modem(tp, 1); 181 while ((tp->t_state & TS_CARR_ON) == 0) { 182 if (flag&FNONBLOCK) 183 break; 184 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 185 "ptsopn", 0); 186 if (error) 187 return (error); 188 } 189 error = ttyld_open(tp, dev); 190 if (error == 0) 191 ptcwakeup(tp, FREAD|FWRITE); 192 return (error); 193} 194 195static int 196ptsclose(struct cdev *dev, int flag, int mode, struct thread *td) 197{ 198 struct tty *tp; 199 int err; 200 201 tp = dev->si_tty; 202 err = ttyld_close(tp, flag); 203 (void) tty_close(tp); 204 return (err); 205} 206 207static int 208ptsread(struct cdev *dev, struct uio *uio, int flag) 209{ 210 struct tty *tp = dev->si_tty; 211 int error = 0; 212 213 if (tp->t_oproc) 214 error = ttyld_read(tp, uio, flag); 215 ptcwakeup(tp, FWRITE); 216 return (error); 217} 218 219/* 220 * Write to pseudo-tty. 221 * Wakeups of controlling tty will happen 222 * indirectly, when tty driver calls ptsstart. 223 */ 224static int 225ptswrite(struct cdev *dev, struct uio *uio, int flag) 226{ 227 struct tty *tp; 228 229 tp = dev->si_tty; 230 if (tp->t_oproc == 0) 231 return (EIO); 232 return (ttyld_write(tp, uio, flag)); 233} 234 235/* 236 * Start output on pseudo-tty. 237 * Wake up process selecting or sleeping for input from controlling tty. 238 */ 239static void 240ptsstart(struct tty *tp) 241{ 242 struct ptsc *pt = tp->t_sc; 243 244 if (tp->t_state & TS_TTSTOP) 245 return; 246 if (pt->pt_flags & PF_STOPPED) { 247 pt->pt_flags &= ~PF_STOPPED; 248 pt->pt_send = TIOCPKT_START; 249 } 250 ptcwakeup(tp, FREAD); 251} 252 253static void 254ptcwakeup(struct tty *tp, int flag) 255{ 256 struct ptsc *pt = tp->t_sc; 257 258 if (flag & FREAD) { 259 selwakeuppri(&pt->pt_selr, TTIPRI); 260 wakeup(TSA_PTC_READ(tp)); 261 } 262 if (flag & FWRITE) { 263 selwakeuppri(&pt->pt_selw, TTOPRI); 264 wakeup(TSA_PTC_WRITE(tp)); 265 } 266} 267 268static int 269ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td) 270{ 271 struct tty *tp; 272 struct ptsc *pt; 273 274 if (!dev->si_drv1) 275 ptyinit(dev, td); 276 if (!dev->si_drv1) 277 return(ENXIO); 278 tp = dev->si_tty; 279 if (tp->t_oproc) 280 return (EIO); 281 tp->t_timeout = -1; 282 tp->t_oproc = ptsstart; 283 tp->t_stop = ptsstop; 284 (void)ttyld_modem(tp, 1); 285 tp->t_lflag &= ~EXTPROC; 286 pt = dev->si_drv1; 287 pt->pt_prison = td->td_ucred->cr_prison; 288 pt->pt_flags = 0; 289 pt->pt_send = 0; 290 pt->pt_ucntl = 0; 291 return (0); 292} 293 294static int 295ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td) 296{ 297 struct tty *tp; 298 299 tp = dev->si_tty; 300 (void)ttyld_modem(tp, 0); 301 302 /* 303 * XXX MDMBUF makes no sense for ptys but would inhibit the above 304 * l_modem(). CLOCAL makes sense but isn't supported. Special 305 * l_modem()s that ignore carrier drop make no sense for ptys but 306 * may be in use because other parts of the line discipline make 307 * sense for ptys. Recover by doing everything that a normal 308 * ttymodem() would have done except for sending a SIGHUP. 309 */ 310 if (tp->t_state & TS_ISOPEN) { 311 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 312 tp->t_state |= TS_ZOMBIE; 313 ttyflush(tp, FREAD | FWRITE); 314 } 315 316 tp->t_oproc = 0; /* mark closed */ 317 return (0); 318} 319 320static int 321ptcread(struct cdev *dev, struct uio *uio, int flag) 322{ 323 struct tty *tp = dev->si_tty; 324 struct ptsc *pt = dev->si_drv1; 325 char buf[BUFSIZ]; 326 int error = 0, cc; 327 328 /* 329 * We want to block until the slave 330 * is open, and there's something to read; 331 * but if we lost the slave or we're NBIO, 332 * then return the appropriate error instead. 333 */ 334 for (;;) { 335 if (tp->t_state&TS_ISOPEN) { 336 if (pt->pt_flags&PF_PKT && pt->pt_send) { 337 error = ureadc((int)pt->pt_send, uio); 338 if (error) 339 return (error); 340 if (pt->pt_send & TIOCPKT_IOCTL) { 341 cc = min(uio->uio_resid, 342 sizeof(tp->t_termios)); 343 uiomove(&tp->t_termios, cc, uio); 344 } 345 pt->pt_send = 0; 346 return (0); 347 } 348 if (pt->pt_flags&PF_UCNTL && pt->pt_ucntl) { 349 error = ureadc((int)pt->pt_ucntl, uio); 350 if (error) 351 return (error); 352 pt->pt_ucntl = 0; 353 return (0); 354 } 355 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 356 break; 357 } 358 if ((tp->t_state & TS_CONNECTED) == 0) 359 return (0); /* EOF */ 360 if (flag & O_NONBLOCK) 361 return (EWOULDBLOCK); 362 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0); 363 if (error) 364 return (error); 365 } 366 if (pt->pt_flags & (PF_PKT|PF_UCNTL)) 367 error = ureadc(0, uio); 368 while (uio->uio_resid > 0 && error == 0) { 369 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 370 if (cc <= 0) 371 break; 372 error = uiomove(buf, cc, uio); 373 } 374 ttwwakeup(tp); 375 return (error); 376} 377 378static void 379ptsstop(struct tty *tp, int flush) 380{ 381 struct ptsc *pt = tp->t_sc; 382 int flag; 383 384 /* note: FLUSHREAD and FLUSHWRITE already ok */ 385 if (flush == 0) { 386 flush = TIOCPKT_STOP; 387 pt->pt_flags |= PF_STOPPED; 388 } else 389 pt->pt_flags &= ~PF_STOPPED; 390 pt->pt_send |= flush; 391 /* change of perspective */ 392 flag = 0; 393 if (flush & FREAD) 394 flag |= FWRITE; 395 if (flush & FWRITE) 396 flag |= FREAD; 397 ptcwakeup(tp, flag); 398} 399 400static int 401ptcpoll(struct cdev *dev, int events, struct thread *td) 402{ 403 struct tty *tp = dev->si_tty; 404 struct ptsc *pt = dev->si_drv1; 405 int revents = 0; 406 int s; 407 408 if ((tp->t_state & TS_CONNECTED) == 0) 409 return (events & 410 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)); 411 412 /* 413 * Need to block timeouts (ttrstart). 414 */ 415 s = spltty(); 416 417 if (events & (POLLIN | POLLRDNORM)) 418 if ((tp->t_state & TS_ISOPEN) && 419 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 420 ((pt->pt_flags & PF_PKT) && pt->pt_send) || 421 ((pt->pt_flags & PF_UCNTL) && pt->pt_ucntl))) 422 revents |= events & (POLLIN | POLLRDNORM); 423 424 if (events & (POLLOUT | POLLWRNORM)) 425 if (tp->t_state & TS_ISOPEN && 426 (((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 427 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON))))) 428 revents |= events & (POLLOUT | POLLWRNORM); 429 430 if (events & POLLHUP) 431 if ((tp->t_state & TS_CARR_ON) == 0) 432 revents |= POLLHUP; 433 434 if (revents == 0) { 435 if (events & (POLLIN | POLLRDNORM)) 436 selrecord(td, &pt->pt_selr); 437 438 if (events & (POLLOUT | POLLWRNORM)) 439 selrecord(td, &pt->pt_selw); 440 } 441 splx(s); 442 443 return (revents); 444} 445 446static int 447ptcwrite(struct cdev *dev, struct uio *uio, int flag) 448{ 449 struct tty *tp = dev->si_tty; 450 u_char *cp = 0; 451 int cc = 0; 452 u_char locbuf[BUFSIZ]; 453 int cnt = 0; 454 int error = 0; 455 456again: 457 if ((tp->t_state&TS_ISOPEN) == 0) 458 goto block; 459 while (uio->uio_resid > 0 || cc > 0) { 460 if (cc == 0) { 461 cc = min(uio->uio_resid, BUFSIZ); 462 cp = locbuf; 463 error = uiomove(cp, cc, uio); 464 if (error) 465 return (error); 466 /* check again for safety */ 467 if ((tp->t_state & TS_ISOPEN) == 0) { 468 /* adjust for data copied in but not written */ 469 uio->uio_resid += cc; 470 return (EIO); 471 } 472 } 473 while (cc > 0) { 474 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 475 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { 476 wakeup(TSA_HUP_OR_INPUT(tp)); 477 goto block; 478 } 479 ttyld_rint(tp, *cp++); 480 cnt++; 481 cc--; 482 } 483 cc = 0; 484 } 485 return (0); 486block: 487 /* 488 * Come here to wait for slave to open, for space 489 * in outq, or space in rawq, or an empty canq. 490 */ 491 if ((tp->t_state & TS_CONNECTED) == 0) { 492 /* adjust for data copied in but not written */ 493 uio->uio_resid += cc; 494 return (EIO); 495 } 496 if (flag & O_NONBLOCK) { 497 /* adjust for data copied in but not written */ 498 uio->uio_resid += cc; 499 if (cnt == 0) 500 return (EWOULDBLOCK); 501 return (0); 502 } 503 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 504 if (error) { 505 /* adjust for data copied in but not written */ 506 uio->uio_resid += cc; 507 return (error); 508 } 509 goto again; 510} 511 512/*ARGSUSED*/ 513static int 514ptcioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 515{ 516 struct tty *tp = dev->si_tty; 517 struct ptsc *pt = dev->si_drv1; 518 519 switch (cmd) { 520 521 case TIOCGPGRP: 522 /* 523 * We avoid calling ttioctl on the controller since, 524 * in that case, tp must be the controlling terminal. 525 */ 526 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 527 return (0); 528 529 case TIOCPKT: 530 if (*(int *)data) { 531 if (pt->pt_flags & PF_UCNTL) 532 return (EINVAL); 533 pt->pt_flags |= PF_PKT; 534 } else 535 pt->pt_flags &= ~PF_PKT; 536 return (0); 537 538 case TIOCUCNTL: 539 if (*(int *)data) { 540 if (pt->pt_flags & PF_PKT) 541 return (EINVAL); 542 pt->pt_flags |= PF_UCNTL; 543 } else 544 pt->pt_flags &= ~PF_UCNTL; 545 return (0); 546 } 547 548 /* 549 * The rest of the ioctls shouldn't be called until 550 * the slave is open. 551 */ 552 if ((tp->t_state & TS_ISOPEN) == 0) 553 return (EAGAIN); 554 555 switch (cmd) { 556#ifndef BURN_BRIDGES 557#ifdef COMPAT_43 558 case TIOCSETP: 559 case TIOCSETN: 560#endif 561#endif 562 case TIOCSETD: 563 case TIOCSETA: 564 case TIOCSETAW: 565 case TIOCSETAF: 566 /* 567 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 568 * ttywflush(tp) will hang if there are characters in 569 * the outq. 570 */ 571 ndflush(&tp->t_outq, tp->t_outq.c_cc); 572 break; 573 574 case TIOCSIG: 575 if (*(unsigned int *)data >= NSIG || 576 *(unsigned int *)data == 0) 577 return(EINVAL); 578 if ((tp->t_lflag&NOFLSH) == 0) 579 ttyflush(tp, FREAD|FWRITE); 580 if (tp->t_pgrp != NULL) { 581 PGRP_LOCK(tp->t_pgrp); 582 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 583 PGRP_UNLOCK(tp->t_pgrp); 584 } 585 if ((*(unsigned int *)data == SIGINFO) && 586 ((tp->t_lflag&NOKERNINFO) == 0)) 587 ttyinfo(tp); 588 return(0); 589 } 590 591 return (ptsioctl(dev, cmd, data, flag, td)); 592} 593 594/*ARGSUSED*/ 595static int 596ptsioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 597{ 598 struct tty *tp = dev->si_tty; 599 struct ptsc *pt = dev->si_drv1; 600 u_char *cc = tp->t_cc; 601 int stop, error; 602 603 if (cmd == TIOCEXT) { 604 /* 605 * When the EXTPROC bit is being toggled, we need 606 * to send an TIOCPKT_IOCTL if the packet driver 607 * is turned on. 608 */ 609 if (*(int *)data) { 610 if (pt->pt_flags & PF_PKT) { 611 pt->pt_send |= TIOCPKT_IOCTL; 612 ptcwakeup(tp, FREAD); 613 } 614 tp->t_lflag |= EXTPROC; 615 } else { 616 if ((tp->t_lflag & EXTPROC) && 617 (pt->pt_flags & PF_PKT)) { 618 pt->pt_send |= TIOCPKT_IOCTL; 619 ptcwakeup(tp, FREAD); 620 } 621 tp->t_lflag &= ~EXTPROC; 622 } 623 return(0); 624 } 625 error = ttyioctl(dev, cmd, data, flag, td); 626 if (error == ENOTTY) { 627 if (pt->pt_flags & PF_UCNTL && 628 (cmd & ~0xff) == UIOCCMD(0)) { 629 if (cmd & 0xff) { 630 pt->pt_ucntl = (u_char)cmd; 631 ptcwakeup(tp, FREAD); 632 } 633 return (0); 634 } 635 error = ENOTTY; 636 } 637 /* 638 * If external processing and packet mode send ioctl packet. 639 */ 640 if ((tp->t_lflag&EXTPROC) && (pt->pt_flags & PF_PKT)) { 641 switch(cmd) { 642 case TIOCSETA: 643 case TIOCSETAW: 644 case TIOCSETAF: 645#ifndef BURN_BRIDGES 646#ifdef COMPAT_43 647 case TIOCSETP: 648 case TIOCSETN: 649 case TIOCSETC: 650 case TIOCSLTC: 651 case TIOCLBIS: 652 case TIOCLBIC: 653 case TIOCLSET: 654#endif 655#endif 656 pt->pt_send |= TIOCPKT_IOCTL; 657 ptcwakeup(tp, FREAD); 658 break; 659 default: 660 break; 661 } 662 } 663 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 664 && CCEQ(cc[VSTART], CTRL('q')); 665 if (pt->pt_flags & PF_NOSTOP) { 666 if (stop) { 667 pt->pt_send &= ~TIOCPKT_NOSTOP; 668 pt->pt_send |= TIOCPKT_DOSTOP; 669 pt->pt_flags &= ~PF_NOSTOP; 670 ptcwakeup(tp, FREAD); 671 } 672 } else { 673 if (!stop) { 674 pt->pt_send &= ~TIOCPKT_DOSTOP; 675 pt->pt_send |= TIOCPKT_NOSTOP; 676 pt->pt_flags |= PF_NOSTOP; 677 ptcwakeup(tp, FREAD); 678 } 679 } 680 return (error); 681} 682 683static void 684pty_clone(void *arg, struct ucred *cr, char *name, int namelen, 685 struct cdev **dev) 686{ 687 int u; 688 689 if (*dev != NULL) 690 return; 691 if (bcmp(name, "pty", 3) != 0) 692 return; 693 if (name[5] != '\0') 694 return; 695 switch (name[3]) { 696 case 'p': u = 0; break; 697 case 'q': u = 32; break; 698 case 'r': u = 64; break; 699 case 's': u = 96; break; 700 case 'P': u = 128; break; 701 case 'Q': u = 160; break; 702 case 'R': u = 192; break; 703 case 'S': u = 224; break; 704 default: return; 705 } 706 if (name[4] >= '0' && name[4] <= '9') 707 u += name[4] - '0'; 708 else if (name[4] >= 'a' && name[4] <= 'v') 709 u += name[4] - 'a' + 10; 710 else 711 return; 712 *dev = make_dev_cred(&ptc_cdevsw, u, cr, 713 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32); 714 dev_ref(*dev); 715 (*dev)->si_flags |= SI_CHEAPCLONE; 716 return; 717} 718 719static void 720ptc_drvinit(void *unused) 721{ 722 723 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); 724} 725 726SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,ptc_drvinit,NULL)
| 154 pt->pt_tty->t_sc = pt; 155 devs->si_drv1 = devc->si_drv1 = pt; 156 devs->si_tty = devc->si_tty = pt->pt_tty; 157 pt->pt_tty->t_dev = devs; 158 return (devc); 159} 160 161/*ARGSUSED*/ 162static int 163ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td) 164{ 165 struct tty *tp; 166 int error; 167 struct ptsc *pt; 168 169 if (!dev->si_drv1) 170 return(ENXIO); 171 pt = dev->si_drv1; 172 tp = dev->si_tty; 173 if ((tp->t_state & TS_ISOPEN) == 0) { 174 ttyinitmode(tp, 1, 0); 175 } else if (tp->t_state & TS_XCLUDE && suser(td)) 176 return (EBUSY); 177 else if (pt->pt_prison != td->td_ucred->cr_prison) 178 return (EBUSY); 179 if (tp->t_oproc) /* Ctrlr still around. */ 180 (void)ttyld_modem(tp, 1); 181 while ((tp->t_state & TS_CARR_ON) == 0) { 182 if (flag&FNONBLOCK) 183 break; 184 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 185 "ptsopn", 0); 186 if (error) 187 return (error); 188 } 189 error = ttyld_open(tp, dev); 190 if (error == 0) 191 ptcwakeup(tp, FREAD|FWRITE); 192 return (error); 193} 194 195static int 196ptsclose(struct cdev *dev, int flag, int mode, struct thread *td) 197{ 198 struct tty *tp; 199 int err; 200 201 tp = dev->si_tty; 202 err = ttyld_close(tp, flag); 203 (void) tty_close(tp); 204 return (err); 205} 206 207static int 208ptsread(struct cdev *dev, struct uio *uio, int flag) 209{ 210 struct tty *tp = dev->si_tty; 211 int error = 0; 212 213 if (tp->t_oproc) 214 error = ttyld_read(tp, uio, flag); 215 ptcwakeup(tp, FWRITE); 216 return (error); 217} 218 219/* 220 * Write to pseudo-tty. 221 * Wakeups of controlling tty will happen 222 * indirectly, when tty driver calls ptsstart. 223 */ 224static int 225ptswrite(struct cdev *dev, struct uio *uio, int flag) 226{ 227 struct tty *tp; 228 229 tp = dev->si_tty; 230 if (tp->t_oproc == 0) 231 return (EIO); 232 return (ttyld_write(tp, uio, flag)); 233} 234 235/* 236 * Start output on pseudo-tty. 237 * Wake up process selecting or sleeping for input from controlling tty. 238 */ 239static void 240ptsstart(struct tty *tp) 241{ 242 struct ptsc *pt = tp->t_sc; 243 244 if (tp->t_state & TS_TTSTOP) 245 return; 246 if (pt->pt_flags & PF_STOPPED) { 247 pt->pt_flags &= ~PF_STOPPED; 248 pt->pt_send = TIOCPKT_START; 249 } 250 ptcwakeup(tp, FREAD); 251} 252 253static void 254ptcwakeup(struct tty *tp, int flag) 255{ 256 struct ptsc *pt = tp->t_sc; 257 258 if (flag & FREAD) { 259 selwakeuppri(&pt->pt_selr, TTIPRI); 260 wakeup(TSA_PTC_READ(tp)); 261 } 262 if (flag & FWRITE) { 263 selwakeuppri(&pt->pt_selw, TTOPRI); 264 wakeup(TSA_PTC_WRITE(tp)); 265 } 266} 267 268static int 269ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td) 270{ 271 struct tty *tp; 272 struct ptsc *pt; 273 274 if (!dev->si_drv1) 275 ptyinit(dev, td); 276 if (!dev->si_drv1) 277 return(ENXIO); 278 tp = dev->si_tty; 279 if (tp->t_oproc) 280 return (EIO); 281 tp->t_timeout = -1; 282 tp->t_oproc = ptsstart; 283 tp->t_stop = ptsstop; 284 (void)ttyld_modem(tp, 1); 285 tp->t_lflag &= ~EXTPROC; 286 pt = dev->si_drv1; 287 pt->pt_prison = td->td_ucred->cr_prison; 288 pt->pt_flags = 0; 289 pt->pt_send = 0; 290 pt->pt_ucntl = 0; 291 return (0); 292} 293 294static int 295ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td) 296{ 297 struct tty *tp; 298 299 tp = dev->si_tty; 300 (void)ttyld_modem(tp, 0); 301 302 /* 303 * XXX MDMBUF makes no sense for ptys but would inhibit the above 304 * l_modem(). CLOCAL makes sense but isn't supported. Special 305 * l_modem()s that ignore carrier drop make no sense for ptys but 306 * may be in use because other parts of the line discipline make 307 * sense for ptys. Recover by doing everything that a normal 308 * ttymodem() would have done except for sending a SIGHUP. 309 */ 310 if (tp->t_state & TS_ISOPEN) { 311 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 312 tp->t_state |= TS_ZOMBIE; 313 ttyflush(tp, FREAD | FWRITE); 314 } 315 316 tp->t_oproc = 0; /* mark closed */ 317 return (0); 318} 319 320static int 321ptcread(struct cdev *dev, struct uio *uio, int flag) 322{ 323 struct tty *tp = dev->si_tty; 324 struct ptsc *pt = dev->si_drv1; 325 char buf[BUFSIZ]; 326 int error = 0, cc; 327 328 /* 329 * We want to block until the slave 330 * is open, and there's something to read; 331 * but if we lost the slave or we're NBIO, 332 * then return the appropriate error instead. 333 */ 334 for (;;) { 335 if (tp->t_state&TS_ISOPEN) { 336 if (pt->pt_flags&PF_PKT && pt->pt_send) { 337 error = ureadc((int)pt->pt_send, uio); 338 if (error) 339 return (error); 340 if (pt->pt_send & TIOCPKT_IOCTL) { 341 cc = min(uio->uio_resid, 342 sizeof(tp->t_termios)); 343 uiomove(&tp->t_termios, cc, uio); 344 } 345 pt->pt_send = 0; 346 return (0); 347 } 348 if (pt->pt_flags&PF_UCNTL && pt->pt_ucntl) { 349 error = ureadc((int)pt->pt_ucntl, uio); 350 if (error) 351 return (error); 352 pt->pt_ucntl = 0; 353 return (0); 354 } 355 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 356 break; 357 } 358 if ((tp->t_state & TS_CONNECTED) == 0) 359 return (0); /* EOF */ 360 if (flag & O_NONBLOCK) 361 return (EWOULDBLOCK); 362 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0); 363 if (error) 364 return (error); 365 } 366 if (pt->pt_flags & (PF_PKT|PF_UCNTL)) 367 error = ureadc(0, uio); 368 while (uio->uio_resid > 0 && error == 0) { 369 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 370 if (cc <= 0) 371 break; 372 error = uiomove(buf, cc, uio); 373 } 374 ttwwakeup(tp); 375 return (error); 376} 377 378static void 379ptsstop(struct tty *tp, int flush) 380{ 381 struct ptsc *pt = tp->t_sc; 382 int flag; 383 384 /* note: FLUSHREAD and FLUSHWRITE already ok */ 385 if (flush == 0) { 386 flush = TIOCPKT_STOP; 387 pt->pt_flags |= PF_STOPPED; 388 } else 389 pt->pt_flags &= ~PF_STOPPED; 390 pt->pt_send |= flush; 391 /* change of perspective */ 392 flag = 0; 393 if (flush & FREAD) 394 flag |= FWRITE; 395 if (flush & FWRITE) 396 flag |= FREAD; 397 ptcwakeup(tp, flag); 398} 399 400static int 401ptcpoll(struct cdev *dev, int events, struct thread *td) 402{ 403 struct tty *tp = dev->si_tty; 404 struct ptsc *pt = dev->si_drv1; 405 int revents = 0; 406 int s; 407 408 if ((tp->t_state & TS_CONNECTED) == 0) 409 return (events & 410 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)); 411 412 /* 413 * Need to block timeouts (ttrstart). 414 */ 415 s = spltty(); 416 417 if (events & (POLLIN | POLLRDNORM)) 418 if ((tp->t_state & TS_ISOPEN) && 419 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 420 ((pt->pt_flags & PF_PKT) && pt->pt_send) || 421 ((pt->pt_flags & PF_UCNTL) && pt->pt_ucntl))) 422 revents |= events & (POLLIN | POLLRDNORM); 423 424 if (events & (POLLOUT | POLLWRNORM)) 425 if (tp->t_state & TS_ISOPEN && 426 (((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 427 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON))))) 428 revents |= events & (POLLOUT | POLLWRNORM); 429 430 if (events & POLLHUP) 431 if ((tp->t_state & TS_CARR_ON) == 0) 432 revents |= POLLHUP; 433 434 if (revents == 0) { 435 if (events & (POLLIN | POLLRDNORM)) 436 selrecord(td, &pt->pt_selr); 437 438 if (events & (POLLOUT | POLLWRNORM)) 439 selrecord(td, &pt->pt_selw); 440 } 441 splx(s); 442 443 return (revents); 444} 445 446static int 447ptcwrite(struct cdev *dev, struct uio *uio, int flag) 448{ 449 struct tty *tp = dev->si_tty; 450 u_char *cp = 0; 451 int cc = 0; 452 u_char locbuf[BUFSIZ]; 453 int cnt = 0; 454 int error = 0; 455 456again: 457 if ((tp->t_state&TS_ISOPEN) == 0) 458 goto block; 459 while (uio->uio_resid > 0 || cc > 0) { 460 if (cc == 0) { 461 cc = min(uio->uio_resid, BUFSIZ); 462 cp = locbuf; 463 error = uiomove(cp, cc, uio); 464 if (error) 465 return (error); 466 /* check again for safety */ 467 if ((tp->t_state & TS_ISOPEN) == 0) { 468 /* adjust for data copied in but not written */ 469 uio->uio_resid += cc; 470 return (EIO); 471 } 472 } 473 while (cc > 0) { 474 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 475 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { 476 wakeup(TSA_HUP_OR_INPUT(tp)); 477 goto block; 478 } 479 ttyld_rint(tp, *cp++); 480 cnt++; 481 cc--; 482 } 483 cc = 0; 484 } 485 return (0); 486block: 487 /* 488 * Come here to wait for slave to open, for space 489 * in outq, or space in rawq, or an empty canq. 490 */ 491 if ((tp->t_state & TS_CONNECTED) == 0) { 492 /* adjust for data copied in but not written */ 493 uio->uio_resid += cc; 494 return (EIO); 495 } 496 if (flag & O_NONBLOCK) { 497 /* adjust for data copied in but not written */ 498 uio->uio_resid += cc; 499 if (cnt == 0) 500 return (EWOULDBLOCK); 501 return (0); 502 } 503 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 504 if (error) { 505 /* adjust for data copied in but not written */ 506 uio->uio_resid += cc; 507 return (error); 508 } 509 goto again; 510} 511 512/*ARGSUSED*/ 513static int 514ptcioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 515{ 516 struct tty *tp = dev->si_tty; 517 struct ptsc *pt = dev->si_drv1; 518 519 switch (cmd) { 520 521 case TIOCGPGRP: 522 /* 523 * We avoid calling ttioctl on the controller since, 524 * in that case, tp must be the controlling terminal. 525 */ 526 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 527 return (0); 528 529 case TIOCPKT: 530 if (*(int *)data) { 531 if (pt->pt_flags & PF_UCNTL) 532 return (EINVAL); 533 pt->pt_flags |= PF_PKT; 534 } else 535 pt->pt_flags &= ~PF_PKT; 536 return (0); 537 538 case TIOCUCNTL: 539 if (*(int *)data) { 540 if (pt->pt_flags & PF_PKT) 541 return (EINVAL); 542 pt->pt_flags |= PF_UCNTL; 543 } else 544 pt->pt_flags &= ~PF_UCNTL; 545 return (0); 546 } 547 548 /* 549 * The rest of the ioctls shouldn't be called until 550 * the slave is open. 551 */ 552 if ((tp->t_state & TS_ISOPEN) == 0) 553 return (EAGAIN); 554 555 switch (cmd) { 556#ifndef BURN_BRIDGES 557#ifdef COMPAT_43 558 case TIOCSETP: 559 case TIOCSETN: 560#endif 561#endif 562 case TIOCSETD: 563 case TIOCSETA: 564 case TIOCSETAW: 565 case TIOCSETAF: 566 /* 567 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 568 * ttywflush(tp) will hang if there are characters in 569 * the outq. 570 */ 571 ndflush(&tp->t_outq, tp->t_outq.c_cc); 572 break; 573 574 case TIOCSIG: 575 if (*(unsigned int *)data >= NSIG || 576 *(unsigned int *)data == 0) 577 return(EINVAL); 578 if ((tp->t_lflag&NOFLSH) == 0) 579 ttyflush(tp, FREAD|FWRITE); 580 if (tp->t_pgrp != NULL) { 581 PGRP_LOCK(tp->t_pgrp); 582 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 583 PGRP_UNLOCK(tp->t_pgrp); 584 } 585 if ((*(unsigned int *)data == SIGINFO) && 586 ((tp->t_lflag&NOKERNINFO) == 0)) 587 ttyinfo(tp); 588 return(0); 589 } 590 591 return (ptsioctl(dev, cmd, data, flag, td)); 592} 593 594/*ARGSUSED*/ 595static int 596ptsioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 597{ 598 struct tty *tp = dev->si_tty; 599 struct ptsc *pt = dev->si_drv1; 600 u_char *cc = tp->t_cc; 601 int stop, error; 602 603 if (cmd == TIOCEXT) { 604 /* 605 * When the EXTPROC bit is being toggled, we need 606 * to send an TIOCPKT_IOCTL if the packet driver 607 * is turned on. 608 */ 609 if (*(int *)data) { 610 if (pt->pt_flags & PF_PKT) { 611 pt->pt_send |= TIOCPKT_IOCTL; 612 ptcwakeup(tp, FREAD); 613 } 614 tp->t_lflag |= EXTPROC; 615 } else { 616 if ((tp->t_lflag & EXTPROC) && 617 (pt->pt_flags & PF_PKT)) { 618 pt->pt_send |= TIOCPKT_IOCTL; 619 ptcwakeup(tp, FREAD); 620 } 621 tp->t_lflag &= ~EXTPROC; 622 } 623 return(0); 624 } 625 error = ttyioctl(dev, cmd, data, flag, td); 626 if (error == ENOTTY) { 627 if (pt->pt_flags & PF_UCNTL && 628 (cmd & ~0xff) == UIOCCMD(0)) { 629 if (cmd & 0xff) { 630 pt->pt_ucntl = (u_char)cmd; 631 ptcwakeup(tp, FREAD); 632 } 633 return (0); 634 } 635 error = ENOTTY; 636 } 637 /* 638 * If external processing and packet mode send ioctl packet. 639 */ 640 if ((tp->t_lflag&EXTPROC) && (pt->pt_flags & PF_PKT)) { 641 switch(cmd) { 642 case TIOCSETA: 643 case TIOCSETAW: 644 case TIOCSETAF: 645#ifndef BURN_BRIDGES 646#ifdef COMPAT_43 647 case TIOCSETP: 648 case TIOCSETN: 649 case TIOCSETC: 650 case TIOCSLTC: 651 case TIOCLBIS: 652 case TIOCLBIC: 653 case TIOCLSET: 654#endif 655#endif 656 pt->pt_send |= TIOCPKT_IOCTL; 657 ptcwakeup(tp, FREAD); 658 break; 659 default: 660 break; 661 } 662 } 663 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 664 && CCEQ(cc[VSTART], CTRL('q')); 665 if (pt->pt_flags & PF_NOSTOP) { 666 if (stop) { 667 pt->pt_send &= ~TIOCPKT_NOSTOP; 668 pt->pt_send |= TIOCPKT_DOSTOP; 669 pt->pt_flags &= ~PF_NOSTOP; 670 ptcwakeup(tp, FREAD); 671 } 672 } else { 673 if (!stop) { 674 pt->pt_send &= ~TIOCPKT_DOSTOP; 675 pt->pt_send |= TIOCPKT_NOSTOP; 676 pt->pt_flags |= PF_NOSTOP; 677 ptcwakeup(tp, FREAD); 678 } 679 } 680 return (error); 681} 682 683static void 684pty_clone(void *arg, struct ucred *cr, char *name, int namelen, 685 struct cdev **dev) 686{ 687 int u; 688 689 if (*dev != NULL) 690 return; 691 if (bcmp(name, "pty", 3) != 0) 692 return; 693 if (name[5] != '\0') 694 return; 695 switch (name[3]) { 696 case 'p': u = 0; break; 697 case 'q': u = 32; break; 698 case 'r': u = 64; break; 699 case 's': u = 96; break; 700 case 'P': u = 128; break; 701 case 'Q': u = 160; break; 702 case 'R': u = 192; break; 703 case 'S': u = 224; break; 704 default: return; 705 } 706 if (name[4] >= '0' && name[4] <= '9') 707 u += name[4] - '0'; 708 else if (name[4] >= 'a' && name[4] <= 'v') 709 u += name[4] - 'a' + 10; 710 else 711 return; 712 *dev = make_dev_cred(&ptc_cdevsw, u, cr, 713 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32); 714 dev_ref(*dev); 715 (*dev)->si_flags |= SI_CHEAPCLONE; 716 return; 717} 718 719static void 720ptc_drvinit(void *unused) 721{ 722 723 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); 724} 725 726SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,ptc_drvinit,NULL)
|