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