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