Deleted Added
full compact
pty.c (130077) pty.c (130259)
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 130077 2004-06-04 16:02:56Z phk $");
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 130259 2004-06-09 09:09:54Z 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;
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
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;
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
122#define TSA_PTC_READ(tp) ((void *)&(tp)->t_outq.c_cf)
123#define TSA_PTC_WRITE(tp) ((void *)&(tp)->t_rawq.c_cl)
124#define TSA_PTS_READ(tp) ((void *)&(tp)->t_canq)
125
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);
152 devs->si_drv1 = devc->si_drv1 = pt;
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)ttyld_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 = ttyld_open(tp, dev);
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 = ttyld_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 = ttyld_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 (ttyld_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)ttyld_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)ttyld_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 ttyld_rint(tp, *cp++);
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 = ttyioctl(dev, cmd, data, flag, td);
752 if (error == ENOTTY) {
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)
126static char *names = "pqrsPQRS";
127/*
128 * This function creates and initializes a pts/ptc pair
129 *
130 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
131 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
132 *
133 * XXX: define and add mapping of upper minor bits to allow more
134 * than 256 ptys.
135 */
136static dev_t
137ptyinit(dev_t devc)
138{
139 dev_t devs;
140 struct pt_ioctl *pt;
141 int n;
142
143 n = minor(devc);
144 /* For now we only map the lower 8 bits of the minor */
145 if (n & ~0xff)
146 return (NODEV);
147
148 devc->si_flags &= ~SI_CHEAPCLONE;
149
150 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
151 pt->devs = devs = make_dev(&pts_cdevsw, n,
152 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32);
153 pt->devc = devc;
154
155 pt->pt_tty = ttymalloc(pt->pt_tty);
156 devs->si_drv1 = devc->si_drv1 = pt;
157 devs->si_tty = devc->si_tty = pt->pt_tty;
158 pt->pt_tty->t_dev = devs;
159 return (devc);
160}
161
162/*ARGSUSED*/
163static int
164ptsopen(dev, flag, devtype, td)
165 dev_t dev;
166 int flag, devtype;
167 struct thread *td;
168{
169 struct tty *tp;
170 int error;
171 struct pt_ioctl *pti;
172
173 if (!dev->si_drv1)
174 return(ENXIO);
175 pti = dev->si_drv1;
176 tp = dev->si_tty;
177 if ((tp->t_state & TS_ISOPEN) == 0) {
178 ttychars(tp); /* Set up default chars */
179 tp->t_iflag = TTYDEF_IFLAG;
180 tp->t_oflag = TTYDEF_OFLAG;
181 tp->t_lflag = TTYDEF_LFLAG;
182 tp->t_cflag = TTYDEF_CFLAG;
183 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
184 } else if (tp->t_state & TS_XCLUDE && suser(td))
185 return (EBUSY);
186 else if (pti->pt_prison != td->td_ucred->cr_prison)
187 return (EBUSY);
188 if (tp->t_oproc) /* Ctrlr still around. */
189 (void)ttyld_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 = ttyld_open(tp, dev);
199 if (error == 0)
200 ptcwakeup(tp, FREAD|FWRITE);
201 return (error);
202}
203
204static int
205ptsclose(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 = ttyld_close(tp, flag);
215 (void) ttyclose(tp);
216 return (err);
217}
218
219static int
220ptsread(dev, uio, flag)
221 dev_t dev;
222 struct uio *uio;
223 int flag;
224{
225 struct thread *td = curthread;
226 struct proc *p = td->td_proc;
227 struct tty *tp = dev->si_tty;
228 struct pt_ioctl *pti = dev->si_drv1;
229 struct pgrp *pg;
230 int error = 0;
231
232again:
233 if (pti->pt_flags & PF_REMOTE) {
234 while (isbackground(p, tp)) {
235 sx_slock(&proctree_lock);
236 PROC_LOCK(p);
237 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) ||
238 SIGISMEMBER(td->td_sigmask, SIGTTIN) ||
239 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
240 PROC_UNLOCK(p);
241 sx_sunlock(&proctree_lock);
242 return (EIO);
243 }
244 pg = p->p_pgrp;
245 PROC_UNLOCK(p);
246 PGRP_LOCK(pg);
247 sx_sunlock(&proctree_lock);
248 pgsignal(pg, SIGTTIN, 1);
249 PGRP_UNLOCK(pg);
250 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
251 0);
252 if (error)
253 return (error);
254 }
255 if (tp->t_canq.c_cc == 0) {
256 if (flag & IO_NDELAY)
257 return (EWOULDBLOCK);
258 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
259 "ptsin", 0);
260 if (error)
261 return (error);
262 goto again;
263 }
264 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
265 if (ureadc(getc(&tp->t_canq), uio) < 0) {
266 error = EFAULT;
267 break;
268 }
269 if (tp->t_canq.c_cc == 1)
270 (void) getc(&tp->t_canq);
271 if (tp->t_canq.c_cc)
272 return (error);
273 } else
274 if (tp->t_oproc)
275 error = ttyld_read(tp, uio, flag);
276 ptcwakeup(tp, FWRITE);
277 return (error);
278}
279
280/*
281 * Write to pseudo-tty.
282 * Wakeups of controlling tty will happen
283 * indirectly, when tty driver calls ptsstart.
284 */
285static int
286ptswrite(dev, uio, flag)
287 dev_t dev;
288 struct uio *uio;
289 int flag;
290{
291 struct tty *tp;
292
293 tp = dev->si_tty;
294 if (tp->t_oproc == 0)
295 return (EIO);
296 return (ttyld_write(tp, uio, flag));
297}
298
299/*
300 * Start output on pseudo-tty.
301 * Wake up process selecting or sleeping for input from controlling tty.
302 */
303static void
304ptsstart(tp)
305 struct tty *tp;
306{
307 struct pt_ioctl *pti = tp->t_dev->si_drv1;
308
309 if (tp->t_state & TS_TTSTOP)
310 return;
311 if (pti->pt_flags & PF_STOPPED) {
312 pti->pt_flags &= ~PF_STOPPED;
313 pti->pt_send = TIOCPKT_START;
314 }
315 ptcwakeup(tp, FREAD);
316}
317
318static void
319ptcwakeup(tp, flag)
320 struct tty *tp;
321 int flag;
322{
323 struct pt_ioctl *pti = tp->t_dev->si_drv1;
324
325 if (flag & FREAD) {
326 selwakeuppri(&pti->pt_selr, TTIPRI);
327 wakeup(TSA_PTC_READ(tp));
328 }
329 if (flag & FWRITE) {
330 selwakeuppri(&pti->pt_selw, TTOPRI);
331 wakeup(TSA_PTC_WRITE(tp));
332 }
333}
334
335static int
336ptcopen(dev, flag, devtype, td)
337 dev_t dev;
338 int flag, devtype;
339 struct thread *td;
340{
341 struct tty *tp;
342 struct pt_ioctl *pti;
343
344 if (!dev->si_drv1)
345 ptyinit(dev);
346 if (!dev->si_drv1)
347 return(ENXIO);
348 tp = dev->si_tty;
349 if (tp->t_oproc)
350 return (EIO);
351 tp->t_timeout = -1;
352 tp->t_oproc = ptsstart;
353 tp->t_stop = ptsstop;
354 (void)ttyld_modem(tp, 1);
355 tp->t_lflag &= ~EXTPROC;
356 pti = dev->si_drv1;
357 pti->pt_prison = td->td_ucred->cr_prison;
358 pti->pt_flags = 0;
359 pti->pt_send = 0;
360 pti->pt_ucntl = 0;
361 return (0);
362}
363
364static int
365ptcclose(dev, flags, fmt, td)
366 dev_t dev;
367 int flags;
368 int fmt;
369 struct thread *td;
370{
371 struct tty *tp;
372
373 tp = dev->si_tty;
374 (void)ttyld_modem(tp, 0);
375
376 /*
377 * XXX MDMBUF makes no sense for ptys but would inhibit the above
378 * l_modem(). CLOCAL makes sense but isn't supported. Special
379 * l_modem()s that ignore carrier drop make no sense for ptys but
380 * may be in use because other parts of the line discipline make
381 * sense for ptys. Recover by doing everything that a normal
382 * ttymodem() would have done except for sending a SIGHUP.
383 */
384 if (tp->t_state & TS_ISOPEN) {
385 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
386 tp->t_state |= TS_ZOMBIE;
387 ttyflush(tp, FREAD | FWRITE);
388 }
389
390 tp->t_oproc = 0; /* mark closed */
391 return (0);
392}
393
394static int
395ptcread(dev, uio, flag)
396 dev_t dev;
397 struct uio *uio;
398 int flag;
399{
400 struct tty *tp = dev->si_tty;
401 struct pt_ioctl *pti = dev->si_drv1;
402 char buf[BUFSIZ];
403 int error = 0, cc;
404
405 /*
406 * We want to block until the slave
407 * is open, and there's something to read;
408 * but if we lost the slave or we're NBIO,
409 * then return the appropriate error instead.
410 */
411 for (;;) {
412 if (tp->t_state&TS_ISOPEN) {
413 if (pti->pt_flags&PF_PKT && pti->pt_send) {
414 error = ureadc((int)pti->pt_send, uio);
415 if (error)
416 return (error);
417 if (pti->pt_send & TIOCPKT_IOCTL) {
418 cc = min(uio->uio_resid,
419 sizeof(tp->t_termios));
420 uiomove(&tp->t_termios, cc, uio);
421 }
422 pti->pt_send = 0;
423 return (0);
424 }
425 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
426 error = ureadc((int)pti->pt_ucntl, uio);
427 if (error)
428 return (error);
429 pti->pt_ucntl = 0;
430 return (0);
431 }
432 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
433 break;
434 }
435 if ((tp->t_state & TS_CONNECTED) == 0)
436 return (0); /* EOF */
437 if (flag & IO_NDELAY)
438 return (EWOULDBLOCK);
439 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
440 if (error)
441 return (error);
442 }
443 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
444 error = ureadc(0, uio);
445 while (uio->uio_resid > 0 && error == 0) {
446 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
447 if (cc <= 0)
448 break;
449 error = uiomove(buf, cc, uio);
450 }
451 ttwwakeup(tp);
452 return (error);
453}
454
455static void
456ptsstop(tp, flush)
457 struct tty *tp;
458 int flush;
459{
460 struct pt_ioctl *pti = tp->t_dev->si_drv1;
461 int flag;
462
463 /* note: FLUSHREAD and FLUSHWRITE already ok */
464 if (flush == 0) {
465 flush = TIOCPKT_STOP;
466 pti->pt_flags |= PF_STOPPED;
467 } else
468 pti->pt_flags &= ~PF_STOPPED;
469 pti->pt_send |= flush;
470 /* change of perspective */
471 flag = 0;
472 if (flush & FREAD)
473 flag |= FWRITE;
474 if (flush & FWRITE)
475 flag |= FREAD;
476 ptcwakeup(tp, flag);
477}
478
479static int
480ptcpoll(dev, events, td)
481 dev_t dev;
482 int events;
483 struct thread *td;
484{
485 struct tty *tp = dev->si_tty;
486 struct pt_ioctl *pti = dev->si_drv1;
487 int revents = 0;
488 int s;
489
490 if ((tp->t_state & TS_CONNECTED) == 0)
491 return (events &
492 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM));
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
530static int
531ptcwrite(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
544again:
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 ttyld_rint(tp, *cp++);
608 cnt++;
609 cc--;
610 }
611 cc = 0;
612 }
613 return (0);
614block:
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*/
641static int
642ptyioctl(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 = ttyioctl(dev, cmd, data, flag, td);
756 if (error == ENOTTY) {
757 if (pti->pt_flags & PF_UCNTL &&
758 (cmd & ~0xff) == UIOCCMD(0)) {
759 if (cmd & 0xff) {
760 pti->pt_ucntl = (u_char)cmd;
761 ptcwakeup(tp, FREAD);
762 }
763 return (0);
764 }
765 error = ENOTTY;
766 }
767 /*
768 * If external processing and packet mode send ioctl packet.
769 */
770 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
771 switch(cmd) {
772 case TIOCSETA:
773 case TIOCSETAW:
774 case TIOCSETAF:
775#ifdef COMPAT_43
776 case TIOCSETP:
777 case TIOCSETN:
778#endif
779#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
780 case TIOCSETC:
781 case TIOCSLTC:
782 case TIOCLBIS:
783 case TIOCLBIC:
784 case TIOCLSET:
785#endif
786 pti->pt_send |= TIOCPKT_IOCTL;
787 ptcwakeup(tp, FREAD);
788 break;
789 default:
790 break;
791 }
792 }
793 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
794 && CCEQ(cc[VSTART], CTRL('q'));
795 if (pti->pt_flags & PF_NOSTOP) {
796 if (stop) {
797 pti->pt_send &= ~TIOCPKT_NOSTOP;
798 pti->pt_send |= TIOCPKT_DOSTOP;
799 pti->pt_flags &= ~PF_NOSTOP;
800 ptcwakeup(tp, FREAD);
801 }
802 } else {
803 if (!stop) {
804 pti->pt_send &= ~TIOCPKT_DOSTOP;
805 pti->pt_send |= TIOCPKT_NOSTOP;
806 pti->pt_flags |= PF_NOSTOP;
807 ptcwakeup(tp, FREAD);
808 }
809 }
810 return (error);
811}
812
813
814static void ptc_drvinit(void *unused);
815
816static void pty_clone(void *arg, char *name, int namelen, dev_t *dev);
817
818static void
819pty_clone(arg, name, namelen, dev)
820 void *arg;
821 char *name;
822 int namelen;
823 dev_t *dev;
824{
825 int u;
826
827 if (*dev != NODEV)
828 return;
829 if (bcmp(name, "pty", 3) != 0)
830 return;
831 if (name[5] != '\0')
832 return;
833 switch (name[3]) {
834 case 'p': u = 0; break;
835 case 'q': u = 32; break;
836 case 'r': u = 64; break;
837 case 's': u = 96; break;
838 case 'P': u = 128; break;
839 case 'Q': u = 160; break;
840 case 'R': u = 192; break;
841 case 'S': u = 224; break;
842 default: return;
843 }
844 if (name[4] >= '0' && name[4] <= '9')
845 u += name[4] - '0';
846 else if (name[4] >= 'a' && name[4] <= 'v')
847 u += name[4] - 'a' + 10;
848 else
849 return;
850 *dev = make_dev(&ptc_cdevsw, u,
851 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
852 (*dev)->si_flags |= SI_CHEAPCLONE;
853 return;
854}
855
856static void
857ptc_drvinit(unused)
858 void *unused;
859{
860
861 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
862}
863
864SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)