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