FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/tty_pty.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
26 /*
27 * Copyright (c) 1982, 1986, 1989, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95
59 */
60
61 /*
62 * Pseudo-teletype Driver
63 * (Actually two drivers, requiring two entries in 'cdevsw')
64 */
65 #include "pty.h" /* XXX */
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/ioctl.h>
70 #include <sys/proc.h>
71 #include <sys/tty.h>
72 #include <sys/conf.h>
73 #include <sys/file.h>
74 #include <sys/uio.h>
75 #include <sys/kernel.h>
76 #include <sys/vnode.h>
77 #include <sys/user.h>
78 #include <sys/signalvar.h>
79
80 #ifndef NeXT
81
82 #define FREE_BSDSTATIC static
83 #else
84 #include <machine/spl.h>
85
86 #define FREE_BSDSTATIC __private_extern__
87 #define d_devtotty_t struct tty **
88
89 #ifdef d_stop_t
90 #undef d_stop_t
91 #endif
92 typedef void d_stop_t __P((struct tty *tp, int rw));
93
94 #endif /* NeXT */
95
96 #ifdef notyet
97 static void ptyattach __P((int n));
98 #endif
99 static void ptsstart __P((struct tty *tp));
100 static void ptcwakeup __P((struct tty *tp, int flag));
101
102 FREE_BSDSTATIC d_open_t ptsopen;
103 FREE_BSDSTATIC d_close_t ptsclose;
104 FREE_BSDSTATIC d_read_t ptsread;
105 FREE_BSDSTATIC d_write_t ptswrite;
106 FREE_BSDSTATIC d_ioctl_t ptyioctl;
107 FREE_BSDSTATIC d_stop_t ptsstop;
108 FREE_BSDSTATIC d_devtotty_t ptydevtotty;
109 FREE_BSDSTATIC d_open_t ptcopen;
110 FREE_BSDSTATIC d_close_t ptcclose;
111 FREE_BSDSTATIC d_read_t ptcread;
112 FREE_BSDSTATIC d_write_t ptcwrite;
113 FREE_BSDSTATIC d_select_t ptcselect;
114
115 #ifndef NeXT
116 #define CDEV_MAJOR_S 5
117 #define CDEV_MAJOR_C 6
118 static struct cdevsw pts_cdevsw =
119 { ptsopen, ptsclose, ptsread, ptswrite, /*5*/
120 ptyioctl, ptsstop, nullreset, ptydevtotty,/* ttyp */
121 ttselect, nommap, NULL, "pts", NULL, -1 };
122
123 static struct cdevsw ptc_cdevsw =
124 { ptcopen, ptcclose, ptcread, ptcwrite, /*6*/
125 ptyioctl, nullstop, nullreset, ptydevtotty,/* ptyp */
126 ptcselect, nommap, NULL, "ptc", NULL, -1 };
127 #endif /* !NeXT */
128
129
130 #if NPTY == 1
131 #undef NPTY
132 #define NPTY 32 /* crude XXX */
133 #warning You have only one pty defined, redefining to 32.
134 #endif
135
136 #ifndef NeXT
137 #ifdef DEVFS
138 #define MAXUNITS (8 * 32)
139 static void *devfs_token_pts[MAXUNITS];
140 static void *devfs_token_ptc[MAXUNITS];
141 static const char jnames[] = "pqrsPQRS";
142 #if NPTY > MAXUNITS
143 #undef NPTY
144 #define NPTY MAXUNITS
145 #warning Can't have more than 256 pty's with DEVFS defined.
146 #endif /* NPTY > MAXUNITS */
147 #endif /* DEVFS */
148 #endif /* !NeXT */
149
150 #define BUFSIZ 100 /* Chunk size iomoved to/from user */
151
152 /*
153 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
154 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
155 */
156 #ifndef NeXT
157 FREE_BSDSTATIC struct tty pt_tty[NPTY]; /* XXX */
158 #else /* NeXT */
159 /* NeXT All references to have been changed to indirections in the file */
160 FREE_BSDSTATIC struct tty *pt_tty[NPTY] = { NULL };
161 #endif /* ! NeXT */
162
163 static struct pt_ioctl {
164 int pt_flags;
165 struct selinfo pt_selr, pt_selw;
166 u_char pt_send;
167 u_char pt_ucntl;
168 } pt_ioctl[NPTY]; /* XXX */
169 static int npty = NPTY; /* for pstat -t */
170
171 #define PF_PKT 0x08 /* packet mode */
172 #define PF_STOPPED 0x10 /* user told stopped */
173 #define PF_REMOTE 0x20 /* remote and flow controlled input */
174 #define PF_NOSTOP 0x40
175 #define PF_UCNTL 0x80 /* user control mode */
176
177 #ifdef notyet
178 /*
179 * Establish n (or default if n is 1) ptys in the system.
180 *
181 * XXX cdevsw & pstat require the array `pty[]' to be an array
182 */
183 FREEBSD_STATIC void
184 ptyattach(n)
185 int n;
186 {
187 char *mem;
188 register u_long ntb;
189 #define DEFAULT_NPTY 32
190
191 /* maybe should allow 0 => none? */
192 if (n <= 1)
193 n = DEFAULT_NPTY;
194 ntb = n * sizeof(struct tty);
195 #ifndef NeXT
196 mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
197 M_DEVBUF, M_WAITOK);
198 #else
199 MALLOC(mem, char *, ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
200 M_DEVBUF, M_WAITOK);
201 #endif /* !NeXT */
202 pt_tty = (struct tty *)mem;
203 mem = (char *)ALIGN(mem + ntb);
204 pt_ioctl = (struct pt_ioctl *)mem;
205 npty = n;
206 }
207 #endif
208
209 #ifndef DEVFS
210 int pty_init()
211 {
212 return 0;
213 }
214 #else
215 #include <miscfs/devfs/devfs.h>
216 #define START_CHAR 'p'
217 #define HEX_BASE 16
218 int pty_init(int n_ptys)
219 {
220 int i;
221 int j;
222
223 /* create the pseudo tty device nodes */
224 for (j = 0; j < 10; j++) {
225 for (i = 0; i < HEX_BASE; i++) {
226 int m = j * HEX_BASE + i;
227 if (m == n_ptys)
228 goto done;
229 (void)devfs_make_node(makedev(4, m),
230 DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666,
231 "tty%c%x", j + START_CHAR, i);
232 (void)devfs_make_node(makedev(5, m),
233 DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666,
234 "pty%c%x", j + START_CHAR, i);
235 }
236 }
237 done:
238 return (0);
239 }
240 #endif /* DEVFS */
241
242 /*ARGSUSED*/
243 FREE_BSDSTATIC int
244 ptsopen(dev, flag, devtype, p)
245 dev_t dev;
246 int flag, devtype;
247 struct proc *p;
248 {
249 register struct tty *tp;
250 int error;
251
252 #ifndef NeXT
253 tp = &pt_tty[minor(dev)];
254 #else
255 /*
256 * You will see this sourt of code coming up in diffs later both
257 * the ttymalloc and the tp indirection.
258 */
259 if (minor(dev) >= npty)
260 return (ENXIO);
261 if (!pt_tty[minor(dev)]) {
262 tp = pt_tty[minor(dev)] = ttymalloc();
263 } else
264 tp = pt_tty[minor(dev)];
265 #endif
266 if ((tp->t_state & TS_ISOPEN) == 0) {
267 ttychars(tp); /* Set up default chars */
268 tp->t_iflag = TTYDEF_IFLAG;
269 tp->t_oflag = TTYDEF_OFLAG;
270 tp->t_lflag = TTYDEF_LFLAG;
271 tp->t_cflag = TTYDEF_CFLAG;
272 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
273 ttsetwater(tp); /* would be done in xxparam() */
274 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
275 return (EBUSY);
276 if (tp->t_oproc) /* Ctrlr still around. */
277 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
278 while ((tp->t_state & TS_CARR_ON) == 0) {
279 if (flag&FNONBLOCK)
280 break;
281 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
282 "ptsopn", 0);
283 if (error)
284 return (error);
285 }
286 error = (*linesw[tp->t_line].l_open)(dev, tp);
287 if (error == 0)
288 ptcwakeup(tp, FREAD|FWRITE);
289 return (error);
290 }
291
292 FREE_BSDSTATIC int
293 ptsclose(dev, flag, mode, p)
294 dev_t dev;
295 int flag, mode;
296 struct proc *p;
297 {
298 register struct tty *tp;
299 int err;
300
301 tp = pt_tty[minor(dev)];
302 err = (*linesw[tp->t_line].l_close)(tp, flag);
303 ptsstop(tp, FREAD|FWRITE);
304 (void) ttyclose(tp);
305 return (err);
306 }
307
308 FREE_BSDSTATIC int
309 ptsread(dev, uio, flag)
310 dev_t dev;
311 struct uio *uio;
312 int flag;
313 {
314 #ifndef NeXT
315 struct proc *p = curproc;
316 #else
317 struct proc *p = current_proc();
318 #endif /* NeXT */
319 register struct tty *tp = pt_tty[minor(dev)];
320 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
321 int error = 0;
322 struct uthread *ut;
323
324 ut = (struct uthread *)get_bsdthread_info(current_act());
325 again:
326 if (pti->pt_flags & PF_REMOTE) {
327 while (isbackground(p, tp)) {
328 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
329 (ut->uu_sigmask & sigmask(SIGTTIN)) ||
330 p->p_pgrp->pg_jobc == 0 ||
331 p->p_flag & P_PPWAIT)
332 return (EIO);
333 pgsignal(p->p_pgrp, SIGTTIN, 1);
334 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ptsbg",
335 0);
336 if (error)
337 return (error);
338 }
339 if (tp->t_canq.c_cc == 0) {
340 if (flag & IO_NDELAY)
341 return (EWOULDBLOCK);
342 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
343 "ptsin", 0);
344 if (error)
345 return (error);
346 goto again;
347 }
348 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
349 if (ureadc(getc(&tp->t_canq), uio) < 0) {
350 error = EFAULT;
351 break;
352 }
353 if (tp->t_canq.c_cc == 1)
354 (void) getc(&tp->t_canq);
355 if (tp->t_canq.c_cc)
356 return (error);
357 } else
358 if (tp->t_oproc)
359 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
360 ptcwakeup(tp, FWRITE);
361 return (error);
362 }
363
364 /*
365 * Write to pseudo-tty.
366 * Wakeups of controlling tty will happen
367 * indirectly, when tty driver calls ptsstart.
368 */
369 FREE_BSDSTATIC int
370 ptswrite(dev, uio, flag)
371 dev_t dev;
372 struct uio *uio;
373 int flag;
374 {
375 register struct tty *tp;
376
377 tp = pt_tty[minor(dev)];
378 if (tp->t_oproc == 0)
379 return (EIO);
380 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
381 }
382
383 /*
384 * Start output on pseudo-tty.
385 * Wake up process selecting or sleeping for input from controlling tty.
386 */
387 static void
388 ptsstart(tp)
389 struct tty *tp;
390 {
391 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
392
393 if (tp->t_state & TS_TTSTOP)
394 return;
395 if (pti->pt_flags & PF_STOPPED) {
396 pti->pt_flags &= ~PF_STOPPED;
397 pti->pt_send = TIOCPKT_START;
398 }
399 ptcwakeup(tp, FREAD);
400 }
401
402 static void
403 ptcwakeup(tp, flag)
404 struct tty *tp;
405 int flag;
406 {
407 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
408
409 if (flag & FREAD) {
410 selwakeup(&pti->pt_selr);
411 wakeup(TSA_PTC_READ(tp));
412 }
413 if (flag & FWRITE) {
414 selwakeup(&pti->pt_selw);
415 wakeup(TSA_PTC_WRITE(tp));
416 }
417 }
418
419 FREE_BSDSTATIC int
420 ptcopen(dev, flag, devtype, p)
421 dev_t dev;
422 int flag, devtype;
423 struct proc *p;
424 {
425 register struct tty *tp;
426 struct pt_ioctl *pti;
427
428 if (minor(dev) >= npty)
429 return (ENXIO);
430 if(!pt_tty[minor(dev)]) {
431 tp = pt_tty[minor(dev)] = ttymalloc();
432 } else
433 tp = pt_tty[minor(dev)];
434 if (tp->t_oproc)
435 return (EIO);
436 tp->t_oproc = ptsstart;
437 #ifdef sun4c
438 tp->t_stop = ptsstop;
439 #endif
440 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
441 tp->t_lflag &= ~EXTPROC;
442 pti = &pt_ioctl[minor(dev)];
443 pti->pt_flags = 0;
444 pti->pt_send = 0;
445 pti->pt_ucntl = 0;
446 return (0);
447 }
448
449 FREE_BSDSTATIC int
450 ptcclose(dev, flags, fmt, p)
451 dev_t dev;
452 int flags;
453 int fmt;
454 struct proc *p;
455 {
456 register struct tty *tp;
457
458 tp = pt_tty[minor(dev)];
459 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
460
461 /*
462 * XXX MDMBUF makes no sense for ptys but would inhibit the above
463 * l_modem(). CLOCAL makes sense but isn't supported. Special
464 * l_modem()s that ignore carrier drop make no sense for ptys but
465 * may be in use because other parts of the line discipline make
466 * sense for ptys. Recover by doing everything that a normal
467 * ttymodem() would have done except for sending a SIGHUP.
468 */
469 if (tp->t_state & TS_ISOPEN) {
470 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
471 tp->t_state |= TS_ZOMBIE;
472 ttyflush(tp, FREAD | FWRITE);
473 }
474
475 tp->t_oproc = 0; /* mark closed */
476 return (0);
477 }
478
479 FREE_BSDSTATIC int
480 ptcread(dev, uio, flag)
481 dev_t dev;
482 struct uio *uio;
483 int flag;
484 {
485 register struct tty *tp = pt_tty[minor(dev)];
486 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
487 char buf[BUFSIZ];
488 int error = 0, cc;
489
490 /*
491 * We want to block until the slave
492 * is open, and there's something to read;
493 * but if we lost the slave or we're NBIO,
494 * then return the appropriate error instead.
495 */
496 for (;;) {
497 if (tp->t_state&TS_ISOPEN) {
498 if (pti->pt_flags&PF_PKT && pti->pt_send) {
499 error = ureadc((int)pti->pt_send, uio);
500 if (error)
501 return (error);
502 if (pti->pt_send & TIOCPKT_IOCTL) {
503 cc = min(uio->uio_resid,
504 sizeof(tp->t_termios));
505 uiomove((caddr_t)&tp->t_termios, cc,
506 uio);
507 }
508 pti->pt_send = 0;
509 return (0);
510 }
511 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
512 error = ureadc((int)pti->pt_ucntl, uio);
513 if (error)
514 return (error);
515 pti->pt_ucntl = 0;
516 return (0);
517 }
518 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
519 break;
520 }
521 if ((tp->t_state & TS_CONNECTED) == 0)
522 return (0); /* EOF */
523 if (flag & IO_NDELAY)
524 return (EWOULDBLOCK);
525 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
526 if (error)
527 return (error);
528 }
529 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
530 error = ureadc(0, uio);
531 while (uio->uio_resid > 0 && error == 0) {
532 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
533 if (cc <= 0)
534 break;
535 error = uiomove(buf, cc, uio);
536 }
537 ttwwakeup(tp);
538 return (error);
539 }
540
541 FREE_BSDSTATIC void
542 ptsstop(tp, flush)
543 register struct tty *tp;
544 int flush;
545 {
546 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
547 int flag;
548
549 /* note: FLUSHREAD and FLUSHWRITE already ok */
550 if (flush == 0) {
551 flush = TIOCPKT_STOP;
552 pti->pt_flags |= PF_STOPPED;
553 } else
554 pti->pt_flags &= ~PF_STOPPED;
555 pti->pt_send |= flush;
556 /* change of perspective */
557 flag = 0;
558 if (flush & FREAD)
559 flag |= FWRITE;
560 if (flush & FWRITE)
561 flag |= FREAD;
562 ptcwakeup(tp, flag);
563 }
564
565 FREE_BSDSTATIC int
566 ptcselect(dev, rw, wql, p)
567 dev_t dev;
568 int rw;
569 void * wql;
570 struct proc *p;
571 {
572 register struct tty *tp = pt_tty[minor(dev)];
573 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
574 int s;
575
576 if ((tp->t_state & TS_CONNECTED) == 0)
577 return (1);
578 switch (rw) {
579
580 case FREAD:
581 /*
582 * Need to block timeouts (ttrstart).
583 */
584 s = spltty();
585 if ((tp->t_state&TS_ISOPEN) &&
586 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
587 splx(s);
588 return (1);
589 }
590 splx(s);
591 /* FALLTHROUGH */
592
593 case 0: /* exceptional */
594 if ((tp->t_state&TS_ISOPEN) &&
595 ((pti->pt_flags&PF_PKT && pti->pt_send) ||
596 (pti->pt_flags&PF_UCNTL && pti->pt_ucntl)))
597 return (1);
598 selrecord(p, &pti->pt_selr, wql);
599 break;
600
601
602 case FWRITE:
603 if (tp->t_state&TS_ISOPEN) {
604 if (pti->pt_flags & PF_REMOTE) {
605 if (tp->t_canq.c_cc == 0)
606 return (1);
607 } else {
608 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
609 return (1);
610 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
611 return (1);
612 }
613 }
614 selrecord(p, &pti->pt_selw, wql);
615 break;
616
617 }
618 return (0);
619 }
620
621 FREE_BSDSTATIC int
622 ptcwrite(dev, uio, flag)
623 dev_t dev;
624 register struct uio *uio;
625 int flag;
626 {
627 register struct tty *tp = pt_tty[minor(dev)];
628 register u_char *cp = NULL;
629 register int cc = 0;
630 u_char locbuf[BUFSIZ];
631 int cnt = 0;
632 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
633 int error = 0;
634
635 again:
636 if ((tp->t_state&TS_ISOPEN) == 0)
637 goto block;
638 if (pti->pt_flags & PF_REMOTE) {
639 if (tp->t_canq.c_cc)
640 goto block;
641 while ((uio->uio_resid > 0 || cc > 0) &&
642 tp->t_canq.c_cc < TTYHOG - 1) {
643 if (cc == 0) {
644 cc = min(uio->uio_resid, BUFSIZ);
645 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
646 cp = locbuf;
647 error = uiomove((caddr_t)cp, cc, uio);
648 if (error)
649 return (error);
650 /* check again for safety */
651 if ((tp->t_state & TS_ISOPEN) == 0) {
652 /* adjust as usual */
653 uio->uio_resid += cc;
654 return (EIO);
655 }
656 }
657 if (cc > 0) {
658 cc = b_to_q((char *)cp, cc, &tp->t_canq);
659 /*
660 * XXX we don't guarantee that the canq size
661 * is >= TTYHOG, so the above b_to_q() may
662 * leave some bytes uncopied. However, space
663 * is guaranteed for the null terminator if
664 * we don't fail here since (TTYHOG - 1) is
665 * not a multiple of CBSIZE.
666 */
667 if (cc > 0)
668 break;
669 }
670 }
671 /* adjust for data copied in but not written */
672 uio->uio_resid += cc;
673 (void) putc(0, &tp->t_canq);
674 ttwakeup(tp);
675 wakeup(TSA_PTS_READ(tp));
676 return (0);
677 }
678 while (uio->uio_resid > 0 || cc > 0) {
679 if (cc == 0) {
680 cc = min(uio->uio_resid, BUFSIZ);
681 cp = locbuf;
682 error = uiomove((caddr_t)cp, cc, uio);
683 if (error)
684 return (error);
685 /* check again for safety */
686 if ((tp->t_state & TS_ISOPEN) == 0) {
687 /* adjust for data copied in but not written */
688 uio->uio_resid += cc;
689 return (EIO);
690 }
691 }
692 while (cc > 0) {
693 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
694 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
695 wakeup(TSA_HUP_OR_INPUT(tp));
696 goto block;
697 }
698 (*linesw[tp->t_line].l_rint)(*cp++, tp);
699 cnt++;
700 cc--;
701 }
702 cc = 0;
703 }
704 return (0);
705 block:
706 /*
707 * Come here to wait for slave to open, for space
708 * in outq, or space in rawq, or an empty canq.
709 */
710 if ((tp->t_state & TS_CONNECTED) == 0) {
711 /* adjust for data copied in but not written */
712 uio->uio_resid += cc;
713 return (EIO);
714 }
715 if (flag & IO_NDELAY) {
716 /* adjust for data copied in but not written */
717 uio->uio_resid += cc;
718 if (cnt == 0)
719 return (EWOULDBLOCK);
720 return (0);
721 }
722 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
723 if (error) {
724 /* adjust for data copied in but not written */
725 uio->uio_resid += cc;
726 return (error);
727 }
728 goto again;
729 }
730
731 #ifndef NeXT
732 /* XXX we eventually want to go to this model,
733 * but premier can't change the cdevsw */
734 static struct tty *
735 ptydevtotty(dev)
736 dev_t dev;
737 {
738 if (minor(dev) >= npty)
739 return (NULL);
740
741 return &pt_tty[minor(dev)];
742 }
743 #endif /* !NeXT */
744
745 /*ARGSUSED*/
746 FREE_BSDSTATIC int
747 #ifndef NeXT
748 ptyioctl(dev, cmd, data, flag)
749 dev_t dev;
750 int cmd;
751 caddr_t data;
752 int flag;
753 #else
754 ptyioctl(dev, cmd, data, flag, p)
755 dev_t dev;
756 u_long cmd;
757 caddr_t data;
758 int flag;
759 struct proc *p;
760 #endif
761 {
762 register struct tty *tp = pt_tty[minor(dev)];
763 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
764 register u_char *cc = tp->t_cc;
765 int stop, error;
766
767 /*
768 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
769 * ttywflush(tp) will hang if there are characters in the outq.
770 */
771 if (cmd == TIOCEXT) {
772 /*
773 * When the EXTPROC bit is being toggled, we need
774 * to send an TIOCPKT_IOCTL if the packet driver
775 * is turned on.
776 */
777 if (*(int *)data) {
778 if (pti->pt_flags & PF_PKT) {
779 pti->pt_send |= TIOCPKT_IOCTL;
780 ptcwakeup(tp, FREAD);
781 }
782 tp->t_lflag |= EXTPROC;
783 } else {
784 if ((tp->t_lflag & EXTPROC) &&
785 (pti->pt_flags & PF_PKT)) {
786 pti->pt_send |= TIOCPKT_IOCTL;
787 ptcwakeup(tp, FREAD);
788 }
789 tp->t_lflag &= ~EXTPROC;
790 }
791 return(0);
792 } else
793 #ifndef NeXT
794 if (cdevsw[major(dev)]->d_open == ptcopen)
795 #else
796 if (cdevsw[major(dev)].d_open == ptcopen)
797 #endif
798 switch (cmd) {
799
800 case TIOCGPGRP:
801 /*
802 * We aviod calling ttioctl on the controller since,
803 * in that case, tp must be the controlling terminal.
804 */
805 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
806 return (0);
807
808 case TIOCPKT:
809 if (*(int *)data) {
810 if (pti->pt_flags & PF_UCNTL)
811 return (EINVAL);
812 pti->pt_flags |= PF_PKT;
813 } else
814 pti->pt_flags &= ~PF_PKT;
815 return (0);
816
817 case TIOCUCNTL:
818 if (*(int *)data) {
819 if (pti->pt_flags & PF_PKT)
820 return (EINVAL);
821 pti->pt_flags |= PF_UCNTL;
822 } else
823 pti->pt_flags &= ~PF_UCNTL;
824 return (0);
825
826 case TIOCREMOTE:
827 if (*(int *)data)
828 pti->pt_flags |= PF_REMOTE;
829 else
830 pti->pt_flags &= ~PF_REMOTE;
831 ttyflush(tp, FREAD|FWRITE);
832 return (0);
833
834 #ifdef COMPAT_43
835 case TIOCSETP:
836 case TIOCSETN:
837 #endif
838 case TIOCSETD:
839 case TIOCSETA:
840 case TIOCSETAW:
841 case TIOCSETAF:
842 ndflush(&tp->t_outq, tp->t_outq.c_cc);
843 break;
844
845 case TIOCSIG:
846 if (*(unsigned int *)data >= NSIG ||
847 *(unsigned int *)data == 0)
848 return(EINVAL);
849 if ((tp->t_lflag&NOFLSH) == 0)
850 ttyflush(tp, FREAD|FWRITE);
851 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
852 if ((*(unsigned int *)data == SIGINFO) &&
853 ((tp->t_lflag&NOKERNINFO) == 0))
854 ttyinfo(tp);
855 return(0);
856 }
857 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
858 if (error < 0)
859 error = ttioctl(tp, cmd, data, flag, p);
860 if (error < 0) {
861 if (pti->pt_flags & PF_UCNTL &&
862 (cmd & ~0xff) == UIOCCMD(0)) {
863 if (cmd & 0xff) {
864 pti->pt_ucntl = (u_char)cmd;
865 ptcwakeup(tp, FREAD);
866 }
867 return (0);
868 }
869 error = ENOTTY;
870 }
871 /*
872 * If external processing and packet mode send ioctl packet.
873 */
874 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
875 switch(cmd) {
876 case TIOCSETA:
877 case TIOCSETAW:
878 case TIOCSETAF:
879 #ifdef COMPAT_43
880 case TIOCSETP:
881 case TIOCSETN:
882 #endif
883 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
884 case TIOCSETC:
885 case TIOCSLTC:
886 case TIOCLBIS:
887 case TIOCLBIC:
888 case TIOCLSET:
889 #endif
890 pti->pt_send |= TIOCPKT_IOCTL;
891 ptcwakeup(tp, FREAD);
892 default:
893 break;
894 }
895 }
896 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
897 && CCEQ(cc[VSTART], CTRL('q'));
898 if (pti->pt_flags & PF_NOSTOP) {
899 if (stop) {
900 pti->pt_send &= ~TIOCPKT_NOSTOP;
901 pti->pt_send |= TIOCPKT_DOSTOP;
902 pti->pt_flags &= ~PF_NOSTOP;
903 ptcwakeup(tp, FREAD);
904 }
905 } else {
906 if (!stop) {
907 pti->pt_send &= ~TIOCPKT_DOSTOP;
908 pti->pt_send |= TIOCPKT_NOSTOP;
909 pti->pt_flags |= PF_NOSTOP;
910 ptcwakeup(tp, FREAD);
911 }
912 }
913 return (error);
914 }
915
916 #ifndef NeXT
917 static ptc_devsw_installed = 0;
918
919 static void
920 ptc_drvinit(void *unused)
921 {
922 #ifdef DEVFS
923 int i,j,k;
924 #endif
925 dev_t dev;
926
927 if( ! ptc_devsw_installed ) {
928 dev = makedev(CDEV_MAJOR_S, 0);
929 cdevsw_add(&dev, &pts_cdevsw, NULL);
930 dev = makedev(CDEV_MAJOR_C, 0);
931 cdevsw_add(&dev, &ptc_cdevsw, NULL);
932 ptc_devsw_installed = 1;
933 #ifdef DEVFS
934 for ( i = 0 ; i<NPTY ; i++ ) {
935 j = i / 32;
936 k = i % 32;
937 devfs_token_pts[i] =
938 devfs_add_devswf(&pts_cdevsw,i,
939 DV_CHR,0,0,0666,
940 "tty%c%n",jnames[j],k);
941 devfs_token_ptc[i] =
942 devfs_add_devswf(&ptc_cdevsw,i,
943 DV_CHR,0,0,0666,
944 "pty%c%n",jnames[j],k);
945 }
946 #endif
947 }
948 }
949
950 SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
951 #endif /* !NeXT */
Cache object: ccebda1c74d950134de5d066f3a25d1d
|