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