Deleted Added
full compact
pty.c (129939) pty.c (130054)
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 129939 2004-06-01 11:57:15Z phk $");
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 130054 2004-06-04 06:50:35Z 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;
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;
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
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
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
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);
151 devs->si_drv1 = devc->si_drv1 = pt;
152 devs->si_drv1 = devc->si_drv1 = pt;
152 devs->si_tty = devc->si_tty = &pt->pt_tty;
153 pt->pt_tty.t_dev = devs;
154 ttyregister(&pt->pt_tty);
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)(*linesw[tp->t_line].l_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 = (*linesw[tp->t_line].l_open)(dev, tp);
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 = (*linesw[tp->t_line].l_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 = (*linesw[tp->t_line].l_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 ((*linesw[tp->t_line].l_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)(*linesw[tp->t_line].l_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)(*linesw[tp->t_line].l_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 (*linesw[tp->t_line].l_rint)(*cp++, tp);
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 }
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)(*linesw[tp->t_line].l_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 = (*linesw[tp->t_line].l_open)(dev, tp);
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 = (*linesw[tp->t_line].l_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 = (*linesw[tp->t_line].l_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 ((*linesw[tp->t_line].l_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)(*linesw[tp->t_line].l_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)(*linesw[tp->t_line].l_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 (*linesw[tp->t_line].l_rint)(*cp++, tp);
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 = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
752 if (error == ENOIOCTL)
753 error = ttioctl(tp, cmd, data, flag);
754 if (error == ENOIOCTL) {
751 error = ttyioctl(dev, cmd, data, flag, td);
752 if (error == ENOTTY) {
755 if (pti->pt_flags & PF_UCNTL &&
756 (cmd & ~0xff) == UIOCCMD(0)) {
757 if (cmd & 0xff) {
758 pti->pt_ucntl = (u_char)cmd;
759 ptcwakeup(tp, FREAD);
760 }
761 return (0);
762 }
763 error = ENOTTY;
764 }
765 /*
766 * If external processing and packet mode send ioctl packet.
767 */
768 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
769 switch(cmd) {
770 case TIOCSETA:
771 case TIOCSETAW:
772 case TIOCSETAF:
773#ifdef COMPAT_43
774 case TIOCSETP:
775 case TIOCSETN:
776#endif
777#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
778 case TIOCSETC:
779 case TIOCSLTC:
780 case TIOCLBIS:
781 case TIOCLBIC:
782 case TIOCLSET:
783#endif
784 pti->pt_send |= TIOCPKT_IOCTL;
785 ptcwakeup(tp, FREAD);
786 break;
787 default:
788 break;
789 }
790 }
791 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
792 && CCEQ(cc[VSTART], CTRL('q'));
793 if (pti->pt_flags & PF_NOSTOP) {
794 if (stop) {
795 pti->pt_send &= ~TIOCPKT_NOSTOP;
796 pti->pt_send |= TIOCPKT_DOSTOP;
797 pti->pt_flags &= ~PF_NOSTOP;
798 ptcwakeup(tp, FREAD);
799 }
800 } else {
801 if (!stop) {
802 pti->pt_send &= ~TIOCPKT_DOSTOP;
803 pti->pt_send |= TIOCPKT_NOSTOP;
804 pti->pt_flags |= PF_NOSTOP;
805 ptcwakeup(tp, FREAD);
806 }
807 }
808 return (error);
809}
810
811
812static void ptc_drvinit(void *unused);
813
814static void pty_clone(void *arg, char *name, int namelen, dev_t *dev);
815
816static void
817pty_clone(arg, name, namelen, dev)
818 void *arg;
819 char *name;
820 int namelen;
821 dev_t *dev;
822{
823 int u;
824
825 if (*dev != NODEV)
826 return;
827 if (bcmp(name, "pty", 3) != 0)
828 return;
829 if (name[5] != '\0')
830 return;
831 switch (name[3]) {
832 case 'p': u = 0; break;
833 case 'q': u = 32; break;
834 case 'r': u = 64; break;
835 case 's': u = 96; break;
836 case 'P': u = 128; break;
837 case 'Q': u = 160; break;
838 case 'R': u = 192; break;
839 case 'S': u = 224; break;
840 default: return;
841 }
842 if (name[4] >= '0' && name[4] <= '9')
843 u += name[4] - '0';
844 else if (name[4] >= 'a' && name[4] <= 'v')
845 u += name[4] - 'a' + 10;
846 else
847 return;
848 *dev = make_dev(&ptc_cdevsw, u,
849 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
850 (*dev)->si_flags |= SI_CHEAPCLONE;
851 return;
852}
853
854static void
855ptc_drvinit(unused)
856 void *unused;
857{
858
859 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
860}
861
862SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
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)