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