Deleted Added
full compact
pty.c (130585) pty.c (130640)
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 130585 2004-06-16 09:47:26Z phk $");
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 130640 2004-06-17 17:16:53Z 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)
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 struct cdev *ptyinit(struct cdev *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 ptsc {
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 struct cdev *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
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 struct cdev *
137ptyinit(struct cdev *devc)
138{
139 struct cdev *devs;
140 struct ptsc *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)
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)
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 struct cdev *ptyinit(struct cdev *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 ptsc {
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 struct cdev *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
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 struct cdev *
137ptyinit(struct cdev *devc)
138{
139 struct cdev *devs;
140 struct ptsc *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);
146 return (NULL);
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(struct cdev *dev, int flag, int devtype, struct thread *td)
165{
166 struct tty *tp;
167 int error;
168 struct ptsc *pt;
169
170 if (!dev->si_drv1)
171 return(ENXIO);
172 pt = dev->si_drv1;
173 tp = dev->si_tty;
174 if ((tp->t_state & TS_ISOPEN) == 0) {
175 ttychars(tp); /* Set up default chars */
176 tp->t_iflag = TTYDEF_IFLAG;
177 tp->t_oflag = TTYDEF_OFLAG;
178 tp->t_lflag = TTYDEF_LFLAG;
179 tp->t_cflag = TTYDEF_CFLAG;
180 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
181 } else if (tp->t_state & TS_XCLUDE && suser(td))
182 return (EBUSY);
183 else if (pt->pt_prison != td->td_ucred->cr_prison)
184 return (EBUSY);
185 if (tp->t_oproc) /* Ctrlr still around. */
186 (void)ttyld_modem(tp, 1);
187 while ((tp->t_state & TS_CARR_ON) == 0) {
188 if (flag&FNONBLOCK)
189 break;
190 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
191 "ptsopn", 0);
192 if (error)
193 return (error);
194 }
195 error = ttyld_open(tp, dev);
196 if (error == 0)
197 ptcwakeup(tp, FREAD|FWRITE);
198 return (error);
199}
200
201static int
202ptsclose(struct cdev *dev, int flag, int mode, struct thread *td)
203{
204 struct tty *tp;
205 int err;
206
207 tp = dev->si_tty;
208 err = ttyld_close(tp, flag);
209 (void) ttyclose(tp);
210 return (err);
211}
212
213static int
214ptsread(struct cdev *dev, struct uio *uio, int flag)
215{
216 struct thread *td = curthread;
217 struct proc *p = td->td_proc;
218 struct tty *tp = dev->si_tty;
219 struct ptsc *pt = dev->si_drv1;
220 struct pgrp *pg;
221 int error = 0;
222
223again:
224 if (pt->pt_flags & PF_REMOTE) {
225 while (isbackground(p, tp)) {
226 sx_slock(&proctree_lock);
227 PROC_LOCK(p);
228 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) ||
229 SIGISMEMBER(td->td_sigmask, SIGTTIN) ||
230 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
231 PROC_UNLOCK(p);
232 sx_sunlock(&proctree_lock);
233 return (EIO);
234 }
235 pg = p->p_pgrp;
236 PROC_UNLOCK(p);
237 PGRP_LOCK(pg);
238 sx_sunlock(&proctree_lock);
239 pgsignal(pg, SIGTTIN, 1);
240 PGRP_UNLOCK(pg);
241 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
242 0);
243 if (error)
244 return (error);
245 }
246 if (tp->t_canq.c_cc == 0) {
247 if (flag & IO_NDELAY)
248 return (EWOULDBLOCK);
249 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
250 "ptsin", 0);
251 if (error)
252 return (error);
253 goto again;
254 }
255 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
256 if (ureadc(getc(&tp->t_canq), uio) < 0) {
257 error = EFAULT;
258 break;
259 }
260 if (tp->t_canq.c_cc == 1)
261 (void) getc(&tp->t_canq);
262 if (tp->t_canq.c_cc)
263 return (error);
264 } else
265 if (tp->t_oproc)
266 error = ttyld_read(tp, uio, flag);
267 ptcwakeup(tp, FWRITE);
268 return (error);
269}
270
271/*
272 * Write to pseudo-tty.
273 * Wakeups of controlling tty will happen
274 * indirectly, when tty driver calls ptsstart.
275 */
276static int
277ptswrite(struct cdev *dev, struct uio *uio, int flag)
278{
279 struct tty *tp;
280
281 tp = dev->si_tty;
282 if (tp->t_oproc == 0)
283 return (EIO);
284 return (ttyld_write(tp, uio, flag));
285}
286
287/*
288 * Start output on pseudo-tty.
289 * Wake up process selecting or sleeping for input from controlling tty.
290 */
291static void
292ptsstart(struct tty *tp)
293{
294 struct ptsc *pt = tp->t_dev->si_drv1;
295
296 if (tp->t_state & TS_TTSTOP)
297 return;
298 if (pt->pt_flags & PF_STOPPED) {
299 pt->pt_flags &= ~PF_STOPPED;
300 pt->pt_send = TIOCPKT_START;
301 }
302 ptcwakeup(tp, FREAD);
303}
304
305static void
306ptcwakeup(struct tty *tp, int flag)
307{
308 struct ptsc *pt = tp->t_dev->si_drv1;
309
310 if (flag & FREAD) {
311 selwakeuppri(&pt->pt_selr, TTIPRI);
312 wakeup(TSA_PTC_READ(tp));
313 }
314 if (flag & FWRITE) {
315 selwakeuppri(&pt->pt_selw, TTOPRI);
316 wakeup(TSA_PTC_WRITE(tp));
317 }
318}
319
320static int
321ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td)
322{
323 struct tty *tp;
324 struct ptsc *pt;
325
326 if (!dev->si_drv1)
327 ptyinit(dev);
328 if (!dev->si_drv1)
329 return(ENXIO);
330 tp = dev->si_tty;
331 if (tp->t_oproc)
332 return (EIO);
333 tp->t_timeout = -1;
334 tp->t_oproc = ptsstart;
335 tp->t_stop = ptsstop;
336 (void)ttyld_modem(tp, 1);
337 tp->t_lflag &= ~EXTPROC;
338 pt = dev->si_drv1;
339 pt->pt_prison = td->td_ucred->cr_prison;
340 pt->pt_flags = 0;
341 pt->pt_send = 0;
342 pt->pt_ucntl = 0;
343 return (0);
344}
345
346static int
347ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td)
348{
349 struct tty *tp;
350
351 tp = dev->si_tty;
352 (void)ttyld_modem(tp, 0);
353
354 /*
355 * XXX MDMBUF makes no sense for ptys but would inhibit the above
356 * l_modem(). CLOCAL makes sense but isn't supported. Special
357 * l_modem()s that ignore carrier drop make no sense for ptys but
358 * may be in use because other parts of the line discipline make
359 * sense for ptys. Recover by doing everything that a normal
360 * ttymodem() would have done except for sending a SIGHUP.
361 */
362 if (tp->t_state & TS_ISOPEN) {
363 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
364 tp->t_state |= TS_ZOMBIE;
365 ttyflush(tp, FREAD | FWRITE);
366 }
367
368 tp->t_oproc = 0; /* mark closed */
369 return (0);
370}
371
372static int
373ptcread(struct cdev *dev, struct uio *uio, int flag)
374{
375 struct tty *tp = dev->si_tty;
376 struct ptsc *pt = dev->si_drv1;
377 char buf[BUFSIZ];
378 int error = 0, cc;
379
380 /*
381 * We want to block until the slave
382 * is open, and there's something to read;
383 * but if we lost the slave or we're NBIO,
384 * then return the appropriate error instead.
385 */
386 for (;;) {
387 if (tp->t_state&TS_ISOPEN) {
388 if (pt->pt_flags&PF_PKT && pt->pt_send) {
389 error = ureadc((int)pt->pt_send, uio);
390 if (error)
391 return (error);
392 if (pt->pt_send & TIOCPKT_IOCTL) {
393 cc = min(uio->uio_resid,
394 sizeof(tp->t_termios));
395 uiomove(&tp->t_termios, cc, uio);
396 }
397 pt->pt_send = 0;
398 return (0);
399 }
400 if (pt->pt_flags&PF_UCNTL && pt->pt_ucntl) {
401 error = ureadc((int)pt->pt_ucntl, uio);
402 if (error)
403 return (error);
404 pt->pt_ucntl = 0;
405 return (0);
406 }
407 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
408 break;
409 }
410 if ((tp->t_state & TS_CONNECTED) == 0)
411 return (0); /* EOF */
412 if (flag & IO_NDELAY)
413 return (EWOULDBLOCK);
414 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
415 if (error)
416 return (error);
417 }
418 if (pt->pt_flags & (PF_PKT|PF_UCNTL))
419 error = ureadc(0, uio);
420 while (uio->uio_resid > 0 && error == 0) {
421 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
422 if (cc <= 0)
423 break;
424 error = uiomove(buf, cc, uio);
425 }
426 ttwwakeup(tp);
427 return (error);
428}
429
430static void
431ptsstop(struct tty *tp, int flush)
432{
433 struct ptsc *pt = tp->t_dev->si_drv1;
434 int flag;
435
436 /* note: FLUSHREAD and FLUSHWRITE already ok */
437 if (flush == 0) {
438 flush = TIOCPKT_STOP;
439 pt->pt_flags |= PF_STOPPED;
440 } else
441 pt->pt_flags &= ~PF_STOPPED;
442 pt->pt_send |= flush;
443 /* change of perspective */
444 flag = 0;
445 if (flush & FREAD)
446 flag |= FWRITE;
447 if (flush & FWRITE)
448 flag |= FREAD;
449 ptcwakeup(tp, flag);
450}
451
452static int
453ptcpoll(struct cdev *dev, int events, struct thread *td)
454{
455 struct tty *tp = dev->si_tty;
456 struct ptsc *pt = dev->si_drv1;
457 int revents = 0;
458 int s;
459
460 if ((tp->t_state & TS_CONNECTED) == 0)
461 return (events &
462 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM));
463
464 /*
465 * Need to block timeouts (ttrstart).
466 */
467 s = spltty();
468
469 if (events & (POLLIN | POLLRDNORM))
470 if ((tp->t_state & TS_ISOPEN) &&
471 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
472 ((pt->pt_flags & PF_PKT) && pt->pt_send) ||
473 ((pt->pt_flags & PF_UCNTL) && pt->pt_ucntl)))
474 revents |= events & (POLLIN | POLLRDNORM);
475
476 if (events & (POLLOUT | POLLWRNORM))
477 if (tp->t_state & TS_ISOPEN &&
478 ((pt->pt_flags & PF_REMOTE) ?
479 (tp->t_canq.c_cc == 0) :
480 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
481 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)))))
482 revents |= events & (POLLOUT | POLLWRNORM);
483
484 if (events & POLLHUP)
485 if ((tp->t_state & TS_CARR_ON) == 0)
486 revents |= POLLHUP;
487
488 if (revents == 0) {
489 if (events & (POLLIN | POLLRDNORM))
490 selrecord(td, &pt->pt_selr);
491
492 if (events & (POLLOUT | POLLWRNORM))
493 selrecord(td, &pt->pt_selw);
494 }
495 splx(s);
496
497 return (revents);
498}
499
500static int
501ptcwrite(struct cdev *dev, struct uio *uio, int flag)
502{
503 struct tty *tp = dev->si_tty;
504 u_char *cp = 0;
505 int cc = 0;
506 u_char locbuf[BUFSIZ];
507 int cnt = 0;
508 struct ptsc *pt = dev->si_drv1;
509 int error = 0;
510
511again:
512 if ((tp->t_state&TS_ISOPEN) == 0)
513 goto block;
514 if (pt->pt_flags & PF_REMOTE) {
515 if (tp->t_canq.c_cc)
516 goto block;
517 while ((uio->uio_resid > 0 || cc > 0) &&
518 tp->t_canq.c_cc < TTYHOG - 1) {
519 if (cc == 0) {
520 cc = min(uio->uio_resid, BUFSIZ);
521 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
522 cp = locbuf;
523 error = uiomove(cp, cc, uio);
524 if (error)
525 return (error);
526 /* check again for safety */
527 if ((tp->t_state & TS_ISOPEN) == 0) {
528 /* adjust as usual */
529 uio->uio_resid += cc;
530 return (EIO);
531 }
532 }
533 if (cc > 0) {
534 cc = b_to_q((char *)cp, cc, &tp->t_canq);
535 /*
536 * XXX we don't guarantee that the canq size
537 * is >= TTYHOG, so the above b_to_q() may
538 * leave some bytes uncopied. However, space
539 * is guaranteed for the null terminator if
540 * we don't fail here since (TTYHOG - 1) is
541 * not a multiple of CBSIZE.
542 */
543 if (cc > 0)
544 break;
545 }
546 }
547 /* adjust for data copied in but not written */
548 uio->uio_resid += cc;
549 (void) putc(0, &tp->t_canq);
550 ttwakeup(tp);
551 wakeup(TSA_PTS_READ(tp));
552 return (0);
553 }
554 while (uio->uio_resid > 0 || cc > 0) {
555 if (cc == 0) {
556 cc = min(uio->uio_resid, BUFSIZ);
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 for data copied in but not written */
564 uio->uio_resid += cc;
565 return (EIO);
566 }
567 }
568 while (cc > 0) {
569 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
570 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) {
571 wakeup(TSA_HUP_OR_INPUT(tp));
572 goto block;
573 }
574 ttyld_rint(tp, *cp++);
575 cnt++;
576 cc--;
577 }
578 cc = 0;
579 }
580 return (0);
581block:
582 /*
583 * Come here to wait for slave to open, for space
584 * in outq, or space in rawq, or an empty canq.
585 */
586 if ((tp->t_state & TS_CONNECTED) == 0) {
587 /* adjust for data copied in but not written */
588 uio->uio_resid += cc;
589 return (EIO);
590 }
591 if (flag & IO_NDELAY) {
592 /* adjust for data copied in but not written */
593 uio->uio_resid += cc;
594 if (cnt == 0)
595 return (EWOULDBLOCK);
596 return (0);
597 }
598 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
599 if (error) {
600 /* adjust for data copied in but not written */
601 uio->uio_resid += cc;
602 return (error);
603 }
604 goto again;
605}
606
607/*ARGSUSED*/
608static int
609ptyioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
610{
611 struct tty *tp = dev->si_tty;
612 struct ptsc *pt = dev->si_drv1;
613 u_char *cc = tp->t_cc;
614 int stop, error;
615
616 if (devsw(dev)->d_open == ptcopen) {
617 switch (cmd) {
618
619 case TIOCGPGRP:
620 /*
621 * We avoid calling ttioctl on the controller since,
622 * in that case, tp must be the controlling terminal.
623 */
624 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
625 return (0);
626
627 case TIOCPKT:
628 if (*(int *)data) {
629 if (pt->pt_flags & PF_UCNTL)
630 return (EINVAL);
631 pt->pt_flags |= PF_PKT;
632 } else
633 pt->pt_flags &= ~PF_PKT;
634 return (0);
635
636 case TIOCUCNTL:
637 if (*(int *)data) {
638 if (pt->pt_flags & PF_PKT)
639 return (EINVAL);
640 pt->pt_flags |= PF_UCNTL;
641 } else
642 pt->pt_flags &= ~PF_UCNTL;
643 return (0);
644
645 case TIOCREMOTE:
646 if (*(int *)data)
647 pt->pt_flags |= PF_REMOTE;
648 else
649 pt->pt_flags &= ~PF_REMOTE;
650 ttyflush(tp, FREAD|FWRITE);
651 return (0);
652 }
653
654 /*
655 * The rest of the ioctls shouldn't be called until
656 * the slave is open.
657 */
658 if ((tp->t_state & TS_ISOPEN) == 0)
659 return (EAGAIN);
660
661 switch (cmd) {
662#ifdef COMPAT_43
663 case TIOCSETP:
664 case TIOCSETN:
665#endif
666 case TIOCSETD:
667 case TIOCSETA:
668 case TIOCSETAW:
669 case TIOCSETAF:
670 /*
671 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
672 * ttywflush(tp) will hang if there are characters in
673 * the outq.
674 */
675 ndflush(&tp->t_outq, tp->t_outq.c_cc);
676 break;
677
678 case TIOCSIG:
679 if (*(unsigned int *)data >= NSIG ||
680 *(unsigned int *)data == 0)
681 return(EINVAL);
682 if ((tp->t_lflag&NOFLSH) == 0)
683 ttyflush(tp, FREAD|FWRITE);
684 if (tp->t_pgrp != NULL) {
685 PGRP_LOCK(tp->t_pgrp);
686 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
687 PGRP_UNLOCK(tp->t_pgrp);
688 }
689 if ((*(unsigned int *)data == SIGINFO) &&
690 ((tp->t_lflag&NOKERNINFO) == 0))
691 ttyinfo(tp);
692 return(0);
693 }
694 }
695 if (cmd == TIOCEXT) {
696 /*
697 * When the EXTPROC bit is being toggled, we need
698 * to send an TIOCPKT_IOCTL if the packet driver
699 * is turned on.
700 */
701 if (*(int *)data) {
702 if (pt->pt_flags & PF_PKT) {
703 pt->pt_send |= TIOCPKT_IOCTL;
704 ptcwakeup(tp, FREAD);
705 }
706 tp->t_lflag |= EXTPROC;
707 } else {
708 if ((tp->t_lflag & EXTPROC) &&
709 (pt->pt_flags & PF_PKT)) {
710 pt->pt_send |= TIOCPKT_IOCTL;
711 ptcwakeup(tp, FREAD);
712 }
713 tp->t_lflag &= ~EXTPROC;
714 }
715 return(0);
716 }
717 error = ttyioctl(dev, cmd, data, flag, td);
718 if (error == ENOTTY) {
719 if (pt->pt_flags & PF_UCNTL &&
720 (cmd & ~0xff) == UIOCCMD(0)) {
721 if (cmd & 0xff) {
722 pt->pt_ucntl = (u_char)cmd;
723 ptcwakeup(tp, FREAD);
724 }
725 return (0);
726 }
727 error = ENOTTY;
728 }
729 /*
730 * If external processing and packet mode send ioctl packet.
731 */
732 if ((tp->t_lflag&EXTPROC) && (pt->pt_flags & PF_PKT)) {
733 switch(cmd) {
734 case TIOCSETA:
735 case TIOCSETAW:
736 case TIOCSETAF:
737#ifdef COMPAT_43
738 case TIOCSETP:
739 case TIOCSETN:
740#endif
741#if defined(COMPAT_43)
742 case TIOCSETC:
743 case TIOCSLTC:
744 case TIOCLBIS:
745 case TIOCLBIC:
746 case TIOCLSET:
747#endif
748 pt->pt_send |= TIOCPKT_IOCTL;
749 ptcwakeup(tp, FREAD);
750 break;
751 default:
752 break;
753 }
754 }
755 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
756 && CCEQ(cc[VSTART], CTRL('q'));
757 if (pt->pt_flags & PF_NOSTOP) {
758 if (stop) {
759 pt->pt_send &= ~TIOCPKT_NOSTOP;
760 pt->pt_send |= TIOCPKT_DOSTOP;
761 pt->pt_flags &= ~PF_NOSTOP;
762 ptcwakeup(tp, FREAD);
763 }
764 } else {
765 if (!stop) {
766 pt->pt_send &= ~TIOCPKT_DOSTOP;
767 pt->pt_send |= TIOCPKT_NOSTOP;
768 pt->pt_flags |= PF_NOSTOP;
769 ptcwakeup(tp, FREAD);
770 }
771 }
772 return (error);
773}
774
775static void
776pty_clone(void *arg, char *name, int namelen, struct cdev **dev)
777{
778 int u;
779
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(struct cdev *dev, int flag, int devtype, struct thread *td)
165{
166 struct tty *tp;
167 int error;
168 struct ptsc *pt;
169
170 if (!dev->si_drv1)
171 return(ENXIO);
172 pt = dev->si_drv1;
173 tp = dev->si_tty;
174 if ((tp->t_state & TS_ISOPEN) == 0) {
175 ttychars(tp); /* Set up default chars */
176 tp->t_iflag = TTYDEF_IFLAG;
177 tp->t_oflag = TTYDEF_OFLAG;
178 tp->t_lflag = TTYDEF_LFLAG;
179 tp->t_cflag = TTYDEF_CFLAG;
180 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
181 } else if (tp->t_state & TS_XCLUDE && suser(td))
182 return (EBUSY);
183 else if (pt->pt_prison != td->td_ucred->cr_prison)
184 return (EBUSY);
185 if (tp->t_oproc) /* Ctrlr still around. */
186 (void)ttyld_modem(tp, 1);
187 while ((tp->t_state & TS_CARR_ON) == 0) {
188 if (flag&FNONBLOCK)
189 break;
190 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
191 "ptsopn", 0);
192 if (error)
193 return (error);
194 }
195 error = ttyld_open(tp, dev);
196 if (error == 0)
197 ptcwakeup(tp, FREAD|FWRITE);
198 return (error);
199}
200
201static int
202ptsclose(struct cdev *dev, int flag, int mode, struct thread *td)
203{
204 struct tty *tp;
205 int err;
206
207 tp = dev->si_tty;
208 err = ttyld_close(tp, flag);
209 (void) ttyclose(tp);
210 return (err);
211}
212
213static int
214ptsread(struct cdev *dev, struct uio *uio, int flag)
215{
216 struct thread *td = curthread;
217 struct proc *p = td->td_proc;
218 struct tty *tp = dev->si_tty;
219 struct ptsc *pt = dev->si_drv1;
220 struct pgrp *pg;
221 int error = 0;
222
223again:
224 if (pt->pt_flags & PF_REMOTE) {
225 while (isbackground(p, tp)) {
226 sx_slock(&proctree_lock);
227 PROC_LOCK(p);
228 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) ||
229 SIGISMEMBER(td->td_sigmask, SIGTTIN) ||
230 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
231 PROC_UNLOCK(p);
232 sx_sunlock(&proctree_lock);
233 return (EIO);
234 }
235 pg = p->p_pgrp;
236 PROC_UNLOCK(p);
237 PGRP_LOCK(pg);
238 sx_sunlock(&proctree_lock);
239 pgsignal(pg, SIGTTIN, 1);
240 PGRP_UNLOCK(pg);
241 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
242 0);
243 if (error)
244 return (error);
245 }
246 if (tp->t_canq.c_cc == 0) {
247 if (flag & IO_NDELAY)
248 return (EWOULDBLOCK);
249 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
250 "ptsin", 0);
251 if (error)
252 return (error);
253 goto again;
254 }
255 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
256 if (ureadc(getc(&tp->t_canq), uio) < 0) {
257 error = EFAULT;
258 break;
259 }
260 if (tp->t_canq.c_cc == 1)
261 (void) getc(&tp->t_canq);
262 if (tp->t_canq.c_cc)
263 return (error);
264 } else
265 if (tp->t_oproc)
266 error = ttyld_read(tp, uio, flag);
267 ptcwakeup(tp, FWRITE);
268 return (error);
269}
270
271/*
272 * Write to pseudo-tty.
273 * Wakeups of controlling tty will happen
274 * indirectly, when tty driver calls ptsstart.
275 */
276static int
277ptswrite(struct cdev *dev, struct uio *uio, int flag)
278{
279 struct tty *tp;
280
281 tp = dev->si_tty;
282 if (tp->t_oproc == 0)
283 return (EIO);
284 return (ttyld_write(tp, uio, flag));
285}
286
287/*
288 * Start output on pseudo-tty.
289 * Wake up process selecting or sleeping for input from controlling tty.
290 */
291static void
292ptsstart(struct tty *tp)
293{
294 struct ptsc *pt = tp->t_dev->si_drv1;
295
296 if (tp->t_state & TS_TTSTOP)
297 return;
298 if (pt->pt_flags & PF_STOPPED) {
299 pt->pt_flags &= ~PF_STOPPED;
300 pt->pt_send = TIOCPKT_START;
301 }
302 ptcwakeup(tp, FREAD);
303}
304
305static void
306ptcwakeup(struct tty *tp, int flag)
307{
308 struct ptsc *pt = tp->t_dev->si_drv1;
309
310 if (flag & FREAD) {
311 selwakeuppri(&pt->pt_selr, TTIPRI);
312 wakeup(TSA_PTC_READ(tp));
313 }
314 if (flag & FWRITE) {
315 selwakeuppri(&pt->pt_selw, TTOPRI);
316 wakeup(TSA_PTC_WRITE(tp));
317 }
318}
319
320static int
321ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td)
322{
323 struct tty *tp;
324 struct ptsc *pt;
325
326 if (!dev->si_drv1)
327 ptyinit(dev);
328 if (!dev->si_drv1)
329 return(ENXIO);
330 tp = dev->si_tty;
331 if (tp->t_oproc)
332 return (EIO);
333 tp->t_timeout = -1;
334 tp->t_oproc = ptsstart;
335 tp->t_stop = ptsstop;
336 (void)ttyld_modem(tp, 1);
337 tp->t_lflag &= ~EXTPROC;
338 pt = dev->si_drv1;
339 pt->pt_prison = td->td_ucred->cr_prison;
340 pt->pt_flags = 0;
341 pt->pt_send = 0;
342 pt->pt_ucntl = 0;
343 return (0);
344}
345
346static int
347ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td)
348{
349 struct tty *tp;
350
351 tp = dev->si_tty;
352 (void)ttyld_modem(tp, 0);
353
354 /*
355 * XXX MDMBUF makes no sense for ptys but would inhibit the above
356 * l_modem(). CLOCAL makes sense but isn't supported. Special
357 * l_modem()s that ignore carrier drop make no sense for ptys but
358 * may be in use because other parts of the line discipline make
359 * sense for ptys. Recover by doing everything that a normal
360 * ttymodem() would have done except for sending a SIGHUP.
361 */
362 if (tp->t_state & TS_ISOPEN) {
363 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
364 tp->t_state |= TS_ZOMBIE;
365 ttyflush(tp, FREAD | FWRITE);
366 }
367
368 tp->t_oproc = 0; /* mark closed */
369 return (0);
370}
371
372static int
373ptcread(struct cdev *dev, struct uio *uio, int flag)
374{
375 struct tty *tp = dev->si_tty;
376 struct ptsc *pt = dev->si_drv1;
377 char buf[BUFSIZ];
378 int error = 0, cc;
379
380 /*
381 * We want to block until the slave
382 * is open, and there's something to read;
383 * but if we lost the slave or we're NBIO,
384 * then return the appropriate error instead.
385 */
386 for (;;) {
387 if (tp->t_state&TS_ISOPEN) {
388 if (pt->pt_flags&PF_PKT && pt->pt_send) {
389 error = ureadc((int)pt->pt_send, uio);
390 if (error)
391 return (error);
392 if (pt->pt_send & TIOCPKT_IOCTL) {
393 cc = min(uio->uio_resid,
394 sizeof(tp->t_termios));
395 uiomove(&tp->t_termios, cc, uio);
396 }
397 pt->pt_send = 0;
398 return (0);
399 }
400 if (pt->pt_flags&PF_UCNTL && pt->pt_ucntl) {
401 error = ureadc((int)pt->pt_ucntl, uio);
402 if (error)
403 return (error);
404 pt->pt_ucntl = 0;
405 return (0);
406 }
407 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
408 break;
409 }
410 if ((tp->t_state & TS_CONNECTED) == 0)
411 return (0); /* EOF */
412 if (flag & IO_NDELAY)
413 return (EWOULDBLOCK);
414 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
415 if (error)
416 return (error);
417 }
418 if (pt->pt_flags & (PF_PKT|PF_UCNTL))
419 error = ureadc(0, uio);
420 while (uio->uio_resid > 0 && error == 0) {
421 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
422 if (cc <= 0)
423 break;
424 error = uiomove(buf, cc, uio);
425 }
426 ttwwakeup(tp);
427 return (error);
428}
429
430static void
431ptsstop(struct tty *tp, int flush)
432{
433 struct ptsc *pt = tp->t_dev->si_drv1;
434 int flag;
435
436 /* note: FLUSHREAD and FLUSHWRITE already ok */
437 if (flush == 0) {
438 flush = TIOCPKT_STOP;
439 pt->pt_flags |= PF_STOPPED;
440 } else
441 pt->pt_flags &= ~PF_STOPPED;
442 pt->pt_send |= flush;
443 /* change of perspective */
444 flag = 0;
445 if (flush & FREAD)
446 flag |= FWRITE;
447 if (flush & FWRITE)
448 flag |= FREAD;
449 ptcwakeup(tp, flag);
450}
451
452static int
453ptcpoll(struct cdev *dev, int events, struct thread *td)
454{
455 struct tty *tp = dev->si_tty;
456 struct ptsc *pt = dev->si_drv1;
457 int revents = 0;
458 int s;
459
460 if ((tp->t_state & TS_CONNECTED) == 0)
461 return (events &
462 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM));
463
464 /*
465 * Need to block timeouts (ttrstart).
466 */
467 s = spltty();
468
469 if (events & (POLLIN | POLLRDNORM))
470 if ((tp->t_state & TS_ISOPEN) &&
471 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
472 ((pt->pt_flags & PF_PKT) && pt->pt_send) ||
473 ((pt->pt_flags & PF_UCNTL) && pt->pt_ucntl)))
474 revents |= events & (POLLIN | POLLRDNORM);
475
476 if (events & (POLLOUT | POLLWRNORM))
477 if (tp->t_state & TS_ISOPEN &&
478 ((pt->pt_flags & PF_REMOTE) ?
479 (tp->t_canq.c_cc == 0) :
480 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
481 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)))))
482 revents |= events & (POLLOUT | POLLWRNORM);
483
484 if (events & POLLHUP)
485 if ((tp->t_state & TS_CARR_ON) == 0)
486 revents |= POLLHUP;
487
488 if (revents == 0) {
489 if (events & (POLLIN | POLLRDNORM))
490 selrecord(td, &pt->pt_selr);
491
492 if (events & (POLLOUT | POLLWRNORM))
493 selrecord(td, &pt->pt_selw);
494 }
495 splx(s);
496
497 return (revents);
498}
499
500static int
501ptcwrite(struct cdev *dev, struct uio *uio, int flag)
502{
503 struct tty *tp = dev->si_tty;
504 u_char *cp = 0;
505 int cc = 0;
506 u_char locbuf[BUFSIZ];
507 int cnt = 0;
508 struct ptsc *pt = dev->si_drv1;
509 int error = 0;
510
511again:
512 if ((tp->t_state&TS_ISOPEN) == 0)
513 goto block;
514 if (pt->pt_flags & PF_REMOTE) {
515 if (tp->t_canq.c_cc)
516 goto block;
517 while ((uio->uio_resid > 0 || cc > 0) &&
518 tp->t_canq.c_cc < TTYHOG - 1) {
519 if (cc == 0) {
520 cc = min(uio->uio_resid, BUFSIZ);
521 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
522 cp = locbuf;
523 error = uiomove(cp, cc, uio);
524 if (error)
525 return (error);
526 /* check again for safety */
527 if ((tp->t_state & TS_ISOPEN) == 0) {
528 /* adjust as usual */
529 uio->uio_resid += cc;
530 return (EIO);
531 }
532 }
533 if (cc > 0) {
534 cc = b_to_q((char *)cp, cc, &tp->t_canq);
535 /*
536 * XXX we don't guarantee that the canq size
537 * is >= TTYHOG, so the above b_to_q() may
538 * leave some bytes uncopied. However, space
539 * is guaranteed for the null terminator if
540 * we don't fail here since (TTYHOG - 1) is
541 * not a multiple of CBSIZE.
542 */
543 if (cc > 0)
544 break;
545 }
546 }
547 /* adjust for data copied in but not written */
548 uio->uio_resid += cc;
549 (void) putc(0, &tp->t_canq);
550 ttwakeup(tp);
551 wakeup(TSA_PTS_READ(tp));
552 return (0);
553 }
554 while (uio->uio_resid > 0 || cc > 0) {
555 if (cc == 0) {
556 cc = min(uio->uio_resid, BUFSIZ);
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 for data copied in but not written */
564 uio->uio_resid += cc;
565 return (EIO);
566 }
567 }
568 while (cc > 0) {
569 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
570 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) {
571 wakeup(TSA_HUP_OR_INPUT(tp));
572 goto block;
573 }
574 ttyld_rint(tp, *cp++);
575 cnt++;
576 cc--;
577 }
578 cc = 0;
579 }
580 return (0);
581block:
582 /*
583 * Come here to wait for slave to open, for space
584 * in outq, or space in rawq, or an empty canq.
585 */
586 if ((tp->t_state & TS_CONNECTED) == 0) {
587 /* adjust for data copied in but not written */
588 uio->uio_resid += cc;
589 return (EIO);
590 }
591 if (flag & IO_NDELAY) {
592 /* adjust for data copied in but not written */
593 uio->uio_resid += cc;
594 if (cnt == 0)
595 return (EWOULDBLOCK);
596 return (0);
597 }
598 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
599 if (error) {
600 /* adjust for data copied in but not written */
601 uio->uio_resid += cc;
602 return (error);
603 }
604 goto again;
605}
606
607/*ARGSUSED*/
608static int
609ptyioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
610{
611 struct tty *tp = dev->si_tty;
612 struct ptsc *pt = dev->si_drv1;
613 u_char *cc = tp->t_cc;
614 int stop, error;
615
616 if (devsw(dev)->d_open == ptcopen) {
617 switch (cmd) {
618
619 case TIOCGPGRP:
620 /*
621 * We avoid calling ttioctl on the controller since,
622 * in that case, tp must be the controlling terminal.
623 */
624 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
625 return (0);
626
627 case TIOCPKT:
628 if (*(int *)data) {
629 if (pt->pt_flags & PF_UCNTL)
630 return (EINVAL);
631 pt->pt_flags |= PF_PKT;
632 } else
633 pt->pt_flags &= ~PF_PKT;
634 return (0);
635
636 case TIOCUCNTL:
637 if (*(int *)data) {
638 if (pt->pt_flags & PF_PKT)
639 return (EINVAL);
640 pt->pt_flags |= PF_UCNTL;
641 } else
642 pt->pt_flags &= ~PF_UCNTL;
643 return (0);
644
645 case TIOCREMOTE:
646 if (*(int *)data)
647 pt->pt_flags |= PF_REMOTE;
648 else
649 pt->pt_flags &= ~PF_REMOTE;
650 ttyflush(tp, FREAD|FWRITE);
651 return (0);
652 }
653
654 /*
655 * The rest of the ioctls shouldn't be called until
656 * the slave is open.
657 */
658 if ((tp->t_state & TS_ISOPEN) == 0)
659 return (EAGAIN);
660
661 switch (cmd) {
662#ifdef COMPAT_43
663 case TIOCSETP:
664 case TIOCSETN:
665#endif
666 case TIOCSETD:
667 case TIOCSETA:
668 case TIOCSETAW:
669 case TIOCSETAF:
670 /*
671 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
672 * ttywflush(tp) will hang if there are characters in
673 * the outq.
674 */
675 ndflush(&tp->t_outq, tp->t_outq.c_cc);
676 break;
677
678 case TIOCSIG:
679 if (*(unsigned int *)data >= NSIG ||
680 *(unsigned int *)data == 0)
681 return(EINVAL);
682 if ((tp->t_lflag&NOFLSH) == 0)
683 ttyflush(tp, FREAD|FWRITE);
684 if (tp->t_pgrp != NULL) {
685 PGRP_LOCK(tp->t_pgrp);
686 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
687 PGRP_UNLOCK(tp->t_pgrp);
688 }
689 if ((*(unsigned int *)data == SIGINFO) &&
690 ((tp->t_lflag&NOKERNINFO) == 0))
691 ttyinfo(tp);
692 return(0);
693 }
694 }
695 if (cmd == TIOCEXT) {
696 /*
697 * When the EXTPROC bit is being toggled, we need
698 * to send an TIOCPKT_IOCTL if the packet driver
699 * is turned on.
700 */
701 if (*(int *)data) {
702 if (pt->pt_flags & PF_PKT) {
703 pt->pt_send |= TIOCPKT_IOCTL;
704 ptcwakeup(tp, FREAD);
705 }
706 tp->t_lflag |= EXTPROC;
707 } else {
708 if ((tp->t_lflag & EXTPROC) &&
709 (pt->pt_flags & PF_PKT)) {
710 pt->pt_send |= TIOCPKT_IOCTL;
711 ptcwakeup(tp, FREAD);
712 }
713 tp->t_lflag &= ~EXTPROC;
714 }
715 return(0);
716 }
717 error = ttyioctl(dev, cmd, data, flag, td);
718 if (error == ENOTTY) {
719 if (pt->pt_flags & PF_UCNTL &&
720 (cmd & ~0xff) == UIOCCMD(0)) {
721 if (cmd & 0xff) {
722 pt->pt_ucntl = (u_char)cmd;
723 ptcwakeup(tp, FREAD);
724 }
725 return (0);
726 }
727 error = ENOTTY;
728 }
729 /*
730 * If external processing and packet mode send ioctl packet.
731 */
732 if ((tp->t_lflag&EXTPROC) && (pt->pt_flags & PF_PKT)) {
733 switch(cmd) {
734 case TIOCSETA:
735 case TIOCSETAW:
736 case TIOCSETAF:
737#ifdef COMPAT_43
738 case TIOCSETP:
739 case TIOCSETN:
740#endif
741#if defined(COMPAT_43)
742 case TIOCSETC:
743 case TIOCSLTC:
744 case TIOCLBIS:
745 case TIOCLBIC:
746 case TIOCLSET:
747#endif
748 pt->pt_send |= TIOCPKT_IOCTL;
749 ptcwakeup(tp, FREAD);
750 break;
751 default:
752 break;
753 }
754 }
755 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
756 && CCEQ(cc[VSTART], CTRL('q'));
757 if (pt->pt_flags & PF_NOSTOP) {
758 if (stop) {
759 pt->pt_send &= ~TIOCPKT_NOSTOP;
760 pt->pt_send |= TIOCPKT_DOSTOP;
761 pt->pt_flags &= ~PF_NOSTOP;
762 ptcwakeup(tp, FREAD);
763 }
764 } else {
765 if (!stop) {
766 pt->pt_send &= ~TIOCPKT_DOSTOP;
767 pt->pt_send |= TIOCPKT_NOSTOP;
768 pt->pt_flags |= PF_NOSTOP;
769 ptcwakeup(tp, FREAD);
770 }
771 }
772 return (error);
773}
774
775static void
776pty_clone(void *arg, char *name, int namelen, struct cdev **dev)
777{
778 int u;
779
780 if (*dev != NODEV)
780 if (*dev != NULL)
781 return;
782 if (bcmp(name, "pty", 3) != 0)
783 return;
784 if (name[5] != '\0')
785 return;
786 switch (name[3]) {
787 case 'p': u = 0; break;
788 case 'q': u = 32; break;
789 case 'r': u = 64; break;
790 case 's': u = 96; break;
791 case 'P': u = 128; break;
792 case 'Q': u = 160; break;
793 case 'R': u = 192; break;
794 case 'S': u = 224; break;
795 default: return;
796 }
797 if (name[4] >= '0' && name[4] <= '9')
798 u += name[4] - '0';
799 else if (name[4] >= 'a' && name[4] <= 'v')
800 u += name[4] - 'a' + 10;
801 else
802 return;
803 *dev = make_dev(&ptc_cdevsw, u,
804 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
805 (*dev)->si_flags |= SI_CHEAPCLONE;
806 return;
807}
808
809static void
810ptc_drvinit(void *unused)
811{
812
813 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
814}
815
816SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
781 return;
782 if (bcmp(name, "pty", 3) != 0)
783 return;
784 if (name[5] != '\0')
785 return;
786 switch (name[3]) {
787 case 'p': u = 0; break;
788 case 'q': u = 32; break;
789 case 'r': u = 64; break;
790 case 's': u = 96; break;
791 case 'P': u = 128; break;
792 case 'Q': u = 160; break;
793 case 'R': u = 192; break;
794 case 'S': u = 224; break;
795 default: return;
796 }
797 if (name[4] >= '0' && name[4] <= '9')
798 u += name[4] - '0';
799 else if (name[4] >= 'a' && name[4] <= 'v')
800 u += name[4] - 'a' + 10;
801 else
802 return;
803 *dev = make_dev(&ptc_cdevsw, u,
804 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
805 (*dev)->si_flags |= SI_CHEAPCLONE;
806 return;
807}
808
809static void
810ptc_drvinit(void *unused)
811{
812
813 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
814}
815
816SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)