FreeBSD/Linux Kernel Cross Reference
sys/kern/tty_pty.c
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: releng/6.2/sys/kern/tty_pty.c 164286 2006-11-14 20:42:41Z cvs2svn $");
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
61 static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
62
63 static void ptsstart(struct tty *tp);
64 static void ptsstop(struct tty *tp, int rw);
65 static void ptcwakeup(struct tty *tp, int flag);
66 static struct cdev *ptyinit(struct cdev *cdev, struct thread *td);
67
68 static d_open_t ptsopen;
69 static d_close_t ptsclose;
70 static d_read_t ptsread;
71 static d_write_t ptswrite;
72 static d_ioctl_t ptsioctl;
73 static d_open_t ptcopen;
74 static d_close_t ptcclose;
75 static d_read_t ptcread;
76 static d_ioctl_t ptcioctl;
77 static d_write_t ptcwrite;
78 static d_poll_t ptcpoll;
79
80 static 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
91 static 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
105 struct 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
124 static 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 */
134 static struct cdev *
135 ptyinit(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
153 pt->pt_tty = ttymalloc(pt->pt_tty);
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*/
162 static int
163 ptsopen(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 && suser(td))
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
195 static int
196 ptsclose(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
207 static int
208 ptsread(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 */
224 static int
225 ptswrite(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 */
239 static void
240 ptsstart(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
253 static void
254 ptcwakeup(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
268 static int
269 ptcopen(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
280 if (tp->t_oproc)
281 return (EIO);
282 tp->t_timeout = -1;
283 tp->t_oproc = ptsstart;
284 tp->t_stop = ptsstop;
285 (void)ttyld_modem(tp, 1);
286 tp->t_lflag &= ~EXTPROC;
287 pt = dev->si_drv1;
288 pt->pt_prison = td->td_ucred->cr_prison;
289 pt->pt_flags = 0;
290 pt->pt_send = 0;
291 pt->pt_ucntl = 0;
292 return (0);
293 }
294
295 static int
296 ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td)
297 {
298 struct tty *tp;
299
300 tp = dev->si_tty;
301 (void)ttyld_modem(tp, 0);
302
303 /*
304 * XXX MDMBUF makes no sense for ptys but would inhibit the above
305 * l_modem(). CLOCAL makes sense but isn't supported. Special
306 * l_modem()s that ignore carrier drop make no sense for ptys but
307 * may be in use because other parts of the line discipline make
308 * sense for ptys. Recover by doing everything that a normal
309 * ttymodem() would have done except for sending a SIGHUP.
310 */
311 if (tp->t_state & TS_ISOPEN) {
312 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
313 tp->t_state |= TS_ZOMBIE;
314 ttyflush(tp, FREAD | FWRITE);
315 }
316
317 tp->t_oproc = 0; /* mark closed */
318 return (0);
319 }
320
321 static int
322 ptcread(struct cdev *dev, struct uio *uio, int flag)
323 {
324 struct tty *tp = dev->si_tty;
325 struct ptsc *pt = dev->si_drv1;
326 char buf[BUFSIZ];
327 int error = 0, cc;
328
329 /*
330 * We want to block until the slave
331 * is open, and there's something to read;
332 * but if we lost the slave or we're NBIO,
333 * then return the appropriate error instead.
334 */
335 for (;;) {
336 if (tp->t_state&TS_ISOPEN) {
337 if (pt->pt_flags&PF_PKT && pt->pt_send) {
338 error = ureadc((int)pt->pt_send, uio);
339 if (error)
340 return (error);
341 if (pt->pt_send & TIOCPKT_IOCTL) {
342 cc = min(uio->uio_resid,
343 sizeof(tp->t_termios));
344 uiomove(&tp->t_termios, cc, uio);
345 }
346 pt->pt_send = 0;
347 return (0);
348 }
349 if (pt->pt_flags&PF_UCNTL && pt->pt_ucntl) {
350 error = ureadc((int)pt->pt_ucntl, uio);
351 if (error)
352 return (error);
353 pt->pt_ucntl = 0;
354 return (0);
355 }
356 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
357 break;
358 }
359 if ((tp->t_state & TS_CONNECTED) == 0)
360 return (0); /* EOF */
361 if (flag & O_NONBLOCK)
362 return (EWOULDBLOCK);
363 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
364 if (error)
365 return (error);
366 }
367 if (pt->pt_flags & (PF_PKT|PF_UCNTL))
368 error = ureadc(0, uio);
369 while (uio->uio_resid > 0 && error == 0) {
370 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
371 if (cc <= 0)
372 break;
373 error = uiomove(buf, cc, uio);
374 }
375 ttwwakeup(tp);
376 return (error);
377 }
378
379 static void
380 ptsstop(struct tty *tp, int flush)
381 {
382 struct ptsc *pt = tp->t_sc;
383 int flag;
384
385 /* note: FLUSHREAD and FLUSHWRITE already ok */
386 if (flush == 0) {
387 flush = TIOCPKT_STOP;
388 pt->pt_flags |= PF_STOPPED;
389 } else
390 pt->pt_flags &= ~PF_STOPPED;
391 pt->pt_send |= flush;
392 /* change of perspective */
393 flag = 0;
394 if (flush & FREAD)
395 flag |= FWRITE;
396 if (flush & FWRITE)
397 flag |= FREAD;
398 ptcwakeup(tp, flag);
399 }
400
401 static int
402 ptcpoll(struct cdev *dev, int events, struct thread *td)
403 {
404 struct tty *tp = dev->si_tty;
405 struct ptsc *pt = dev->si_drv1;
406 int revents = 0;
407 int s;
408
409 if ((tp->t_state & TS_CONNECTED) == 0)
410 return (events &
411 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM));
412
413 /*
414 * Need to block timeouts (ttrstart).
415 */
416 s = spltty();
417
418 if (events & (POLLIN | POLLRDNORM))
419 if ((tp->t_state & TS_ISOPEN) &&
420 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
421 ((pt->pt_flags & PF_PKT) && pt->pt_send) ||
422 ((pt->pt_flags & PF_UCNTL) && pt->pt_ucntl)))
423 revents |= events & (POLLIN | POLLRDNORM);
424
425 if (events & (POLLOUT | POLLWRNORM))
426 if (tp->t_state & TS_ISOPEN &&
427 (((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
428 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)))))
429 revents |= events & (POLLOUT | POLLWRNORM);
430
431 if (events & POLLHUP)
432 if ((tp->t_state & TS_CARR_ON) == 0)
433 revents |= POLLHUP;
434
435 if (revents == 0) {
436 if (events & (POLLIN | POLLRDNORM))
437 selrecord(td, &pt->pt_selr);
438
439 if (events & (POLLOUT | POLLWRNORM))
440 selrecord(td, &pt->pt_selw);
441 }
442 splx(s);
443
444 return (revents);
445 }
446
447 static int
448 ptcwrite(struct cdev *dev, struct uio *uio, int flag)
449 {
450 struct tty *tp = dev->si_tty;
451 u_char *cp = 0;
452 int cc = 0;
453 u_char locbuf[BUFSIZ];
454 int cnt = 0;
455 int error = 0;
456
457 again:
458 if ((tp->t_state&TS_ISOPEN) == 0)
459 goto block;
460 while (uio->uio_resid > 0 || cc > 0) {
461 if (cc == 0) {
462 cc = min(uio->uio_resid, BUFSIZ);
463 cp = locbuf;
464 error = uiomove(cp, cc, uio);
465 if (error)
466 return (error);
467 /* check again for safety */
468 if ((tp->t_state & TS_ISOPEN) == 0) {
469 /* adjust for data copied in but not written */
470 uio->uio_resid += cc;
471 return (EIO);
472 }
473 }
474 while (cc > 0) {
475 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
476 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) {
477 wakeup(TSA_HUP_OR_INPUT(tp));
478 goto block;
479 }
480 ttyld_rint(tp, *cp++);
481 cnt++;
482 cc--;
483 }
484 cc = 0;
485 }
486 return (0);
487 block:
488 /*
489 * Come here to wait for slave to open, for space
490 * in outq, or space in rawq, or an empty canq.
491 */
492 if ((tp->t_state & TS_CONNECTED) == 0) {
493 /* adjust for data copied in but not written */
494 uio->uio_resid += cc;
495 return (EIO);
496 }
497 if (flag & O_NONBLOCK) {
498 /* adjust for data copied in but not written */
499 uio->uio_resid += cc;
500 if (cnt == 0)
501 return (EWOULDBLOCK);
502 return (0);
503 }
504 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
505 if (error) {
506 /* adjust for data copied in but not written */
507 uio->uio_resid += cc;
508 return (error);
509 }
510 goto again;
511 }
512
513 /*ARGSUSED*/
514 static int
515 ptcioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
516 {
517 struct tty *tp = dev->si_tty;
518 struct ptsc *pt = dev->si_drv1;
519 int ival;
520
521 switch (cmd) {
522
523 case TIOCGPGRP:
524 /*
525 * We avoid calling ttioctl on the controller since,
526 * in that case, tp must be the controlling terminal.
527 */
528 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
529 return (0);
530
531 case TIOCPKT:
532 if (*(int *)data) {
533 if (pt->pt_flags & PF_UCNTL)
534 return (EINVAL);
535 pt->pt_flags |= PF_PKT;
536 } else
537 pt->pt_flags &= ~PF_PKT;
538 return (0);
539
540 case TIOCUCNTL:
541 if (*(int *)data) {
542 if (pt->pt_flags & PF_PKT)
543 return (EINVAL);
544 pt->pt_flags |= PF_UCNTL;
545 } else
546 pt->pt_flags &= ~PF_UCNTL;
547 return (0);
548 }
549
550 /*
551 * The rest of the ioctls shouldn't be called until
552 * the slave is open.
553 */
554 if ((tp->t_state & TS_ISOPEN) == 0)
555 return (EAGAIN);
556
557 switch (cmd) {
558 #ifndef BURN_BRIDGES
559 #ifdef COMPAT_43
560 case TIOCSETP:
561 case TIOCSETN:
562 #endif
563 #endif
564 case TIOCSETD:
565 case TIOCSETA:
566 case TIOCSETAW:
567 case TIOCSETAF:
568 /*
569 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
570 * ttywflush(tp) will hang if there are characters in
571 * the outq.
572 */
573 ndflush(&tp->t_outq, tp->t_outq.c_cc);
574 break;
575
576 case _IO('t', 95):
577 ival = IOCPARM_IVAL(data);
578 data = (caddr_t)&ival;
579 /* FALLTHROUGH */
580 case TIOCSIG:
581 if (*(unsigned int *)data >= NSIG ||
582 *(unsigned int *)data == 0)
583 return(EINVAL);
584 if ((tp->t_lflag&NOFLSH) == 0)
585 ttyflush(tp, FREAD|FWRITE);
586 if (tp->t_pgrp != NULL) {
587 PGRP_LOCK(tp->t_pgrp);
588 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
589 PGRP_UNLOCK(tp->t_pgrp);
590 }
591 if ((*(unsigned int *)data == SIGINFO) &&
592 ((tp->t_lflag&NOKERNINFO) == 0))
593 ttyinfo(tp);
594 return(0);
595 }
596
597 return (ptsioctl(dev, cmd, data, flag, td));
598 }
599
600 /*ARGSUSED*/
601 static int
602 ptsioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
603 {
604 struct tty *tp = dev->si_tty;
605 struct ptsc *pt = dev->si_drv1;
606 u_char *cc = tp->t_cc;
607 int stop, error;
608
609 if (cmd == TIOCEXT) {
610 /*
611 * When the EXTPROC bit is being toggled, we need
612 * to send an TIOCPKT_IOCTL if the packet driver
613 * is turned on.
614 */
615 if (*(int *)data) {
616 if (pt->pt_flags & PF_PKT) {
617 pt->pt_send |= TIOCPKT_IOCTL;
618 ptcwakeup(tp, FREAD);
619 }
620 tp->t_lflag |= EXTPROC;
621 } else {
622 if ((tp->t_lflag & EXTPROC) &&
623 (pt->pt_flags & PF_PKT)) {
624 pt->pt_send |= TIOCPKT_IOCTL;
625 ptcwakeup(tp, FREAD);
626 }
627 tp->t_lflag &= ~EXTPROC;
628 }
629 return(0);
630 }
631 error = ttyioctl(dev, cmd, data, flag, td);
632 if (error == ENOTTY) {
633 if (pt->pt_flags & PF_UCNTL &&
634 (cmd & ~0xff) == UIOCCMD(0)) {
635 if (cmd & 0xff) {
636 pt->pt_ucntl = (u_char)cmd;
637 ptcwakeup(tp, FREAD);
638 }
639 return (0);
640 }
641 error = ENOTTY;
642 }
643 /*
644 * If external processing and packet mode send ioctl packet.
645 */
646 if ((tp->t_lflag&EXTPROC) && (pt->pt_flags & PF_PKT)) {
647 switch(cmd) {
648 case TIOCSETA:
649 case TIOCSETAW:
650 case TIOCSETAF:
651 #ifndef BURN_BRIDGES
652 #ifdef COMPAT_43
653 case TIOCSETP:
654 case TIOCSETN:
655 case TIOCSETC:
656 case TIOCSLTC:
657 case TIOCLBIS:
658 case TIOCLBIC:
659 case TIOCLSET:
660 #endif
661 #endif
662 pt->pt_send |= TIOCPKT_IOCTL;
663 ptcwakeup(tp, FREAD);
664 break;
665 default:
666 break;
667 }
668 }
669 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
670 && CCEQ(cc[VSTART], CTRL('q'));
671 if (pt->pt_flags & PF_NOSTOP) {
672 if (stop) {
673 pt->pt_send &= ~TIOCPKT_NOSTOP;
674 pt->pt_send |= TIOCPKT_DOSTOP;
675 pt->pt_flags &= ~PF_NOSTOP;
676 ptcwakeup(tp, FREAD);
677 }
678 } else {
679 if (!stop) {
680 pt->pt_send &= ~TIOCPKT_DOSTOP;
681 pt->pt_send |= TIOCPKT_NOSTOP;
682 pt->pt_flags |= PF_NOSTOP;
683 ptcwakeup(tp, FREAD);
684 }
685 }
686 return (error);
687 }
688
689 static void
690 pty_clone(void *arg, struct ucred *cr, char *name, int namelen,
691 struct cdev **dev)
692 {
693 int u;
694
695 if (*dev != NULL)
696 return;
697 if (bcmp(name, "pty", 3) != 0)
698 return;
699 if (name[5] != '\0')
700 return;
701 switch (name[3]) {
702 case 'p': u = 0; break;
703 case 'q': u = 32; break;
704 case 'r': u = 64; break;
705 case 's': u = 96; break;
706 case 'P': u = 128; break;
707 case 'Q': u = 160; break;
708 case 'R': u = 192; break;
709 case 'S': u = 224; break;
710 default: return;
711 }
712 if (name[4] >= '' && name[4] <= '9')
713 u += name[4] - '';
714 else if (name[4] >= 'a' && name[4] <= 'v')
715 u += name[4] - 'a' + 10;
716 else
717 return;
718 *dev = make_dev_cred(&ptc_cdevsw, u, cr,
719 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
720 dev_ref(*dev);
721 (*dev)->si_flags |= SI_CHEAPCLONE;
722 return;
723 }
724
725 static void
726 ptc_drvinit(void *unused)
727 {
728
729 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
730 }
731
732 SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,ptc_drvinit,NULL)
Cache object: 33426bc96728ed3c451ae0f0370c2ce5
|