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