|
|
1.1 root 1: /*
2: * File: $USRSRC/ttydrv/tty.c
3: *
4: * Purpose: COHERENT line discipline module.
5: * This is the common part of typewriter service. It handles all device-
6: * independent aspects of a typewriter, including tandem flow control,
7: * erase and kill, stop and start, and common ioctl functions.
8: *
9: * $Log: tty.c,v $
10: * Revision 1.2 92/08/04 12:54:52 bin
11: * upd for ker59
12: *
13: * Revision 1.12 92/06/06 12:39:28 hal
14: * Last before adding termio field to tty struct.
15: *
16: * Revision 1.11 92/04/30 08:58:50 hal
17: * Add asy. Remove silos from tty struct.
18: *
19: * Revision 1.10 92/04/13 10:14:01 hal
20: * Kernel #52.
21: *
22: * Revision 1.9 92/03/18 07:44:47 hal
23: * ttwrite0() needed to break pty deadlock.
24: *
25: * Revision 1.8 92/03/18 05:27:05 hal
26: * Add ttrtp(), ttinp(), ttoutp().
27: * Fix ctrl-s/ctrl-q transposition in termio routine.
28: * TIOCSET[PN] now sets RAW depending on RAWIN&RAWOUT & vice versa.
29: *
30: * Revision 1.7 92/02/20 20:25:36 hal
31: * Minor fixes
32: *
33: * Revision 1.6 92/02/20 19:43:30 piggy
34: * Add "mode" arg to ttsetgrp() for NOCTTY support.
35: *
36: * Revision 1.5 92/02/16 23:14:23 hal
37: * Initial termio support.
38: *
39: * Revision 1.4 92/02/16 18:27:33 hal
40: * Binary compatibility with Sys V sgtty
41: *
42: * Revision 1.3 92/02/15 15:43:46 root
43: * Merge with 286 kernel tty.c.
44: */
45:
46: /*
47: * About STOP flag bits:
48: * T_ISTOP is set when the tty module's input queue is in danger of
49: * overflow. It is up to the device driver to check this flag
50: * and do something about it. If ttin() is called with a
51: * character from the device while T_ISTOP is set, the character
52: * is discarded. T_ISTOP is cleared when the input queue is
53: * sufficiently empty. The device driver can monitor this bit for
54: * hardware flow control.
55: * T_TSTOP is the "Tandem" flow control flag for input. If TANDEM is set
56: * and the input queue is in danger of overflow, t_stopc is sent
57: * and T_TSTOP is set. When the input queue is empty enough,
58: * t_startc is sent and T_TSTOP is cleared.
59: * T_STOP is the flow control bit for output. No output will be
60: * written to the output queue while this bit is true.
61: * Except for initialization of flags in the TTY struct, by
62: * ttopen(), this bit is not written by tty.c.
63: * 91/09/15 - hal
64: */
65:
66: /*
67: * Includes.
68: */
69: #include <sys/clist.h>
70: #include <sys/coherent.h>
71: #include <sys/con.h>
72: #include <sys/deftty.h>
73: #include <sys/io.h>
74: #include <sys/proc.h>
75: #include <sys/sched.h>
76: #include <sys/stat.h>
77: #include <sys/tty.h>
78: #include <errno.h>
79: #ifdef _I386
80: #include <termio.h>
81: #include <sys/inode.h>
82: #else
83: #endif
84:
85: #ifdef TRACER
86: #define DUMPSGTTY(sp) dumpsgtty(sp)
87:
88: static void dumpsgtty(sp)
89: struct sgttyb * sp;
90: {
91: T_HAL(2, printf("S:%x:%x ", sp->sg_ispeed, sp->sg_flags));
92: }
93: #else
94: #define DUMPSGTTY(sp)
95: #endif
96:
97: /*
98: * Definitions.
99: * Constants.
100: * Macros with argument lists.
101: * Typedefs.
102: * Enums.
103: */
104:
105: #define SGTTY_CPY_LEN (sizeof (struct sgttyb))
106:
107: /* NEAR_OR_FAR_CALL is for invoking t_param and t_start */
108: #ifdef _I386
109: #define NEAR_OR_FAR_CALL(tp_fn) { (*tp->tp_fn)(tp); }
110: #define SET_HPCL { \
111: if (tp->t_termio.c_cflag & HUPCL) \
112: tp->t_flags |= T_HPCL; \
113: else \
114: tp->t_flags &= ~T_HPCL; }
115: #else
116: #define NEAR_OR_FAR_CALL(tp_fn) {\
117: if (tp->t_cs_sel) \
118: ld_call(tp->t_cs_sel, tp->tp_fn, tp); \
119: else \
120: (*tp->tp_fn)(tp); }
121: #define SET_HPCL
122: #endif
123:
124: /*
125: * Functions.
126: * Import Functions.
127: * Export Functions.
128: * Local Functions.
129: */
130: void ttclose();
131: void ttflush();
132: void tthup();
133: void ttin();
134: int ttinp();
135: void ttioctl();
136: void ttopen();
137: int ttout();
138: int ttoutp();
139: int ttpoll();
140: void ttread();
141: void ttread0();
142: void ttsetgrp();
143: void ttsignal();
144: void ttstart();
145: void ttwrite();
146: void ttwrite0();
147:
148: static void ttstash();
149: static void ttrtp();
150:
151: #ifdef _I386
152: static void make_termio();
153: static void make_sg();
154: #else
155: #define make_termio(a1,a2,a3)
156: #define make_sg(a1,a2,a3)
157: #endif
158:
159: /*
160: * Global Data.
161: * Import Variables.
162: * Export Variables.
163: * Local Variables.
164: */
165: extern int wakeup();
166: extern void pollwake();
167:
168: /*
169: * ttopen()
170: *
171: * Called by driver on first open.
172: * Set up defaults.
173: */
174: void
175: ttopen(tp)
176: register TTY *tp;
177: {
178: tp->t_escape = 0;
179: tp->t_sgttyb.sg_ispeed = tp->t_dispeed;
180: tp->t_sgttyb.sg_ospeed = tp->t_dospeed;
181: tp->t_sgttyb.sg_erase = DEF_SG_ERASE;
182: tp->t_sgttyb.sg_kill = DEF_SG_KILL;
183: tp->t_sgttyb.sg_flags = DEF_SG_FLAGS;
184: tp->t_tchars.t_intrc = DEF_T_INTRC;
185: tp->t_tchars.t_quitc = DEF_T_QUITC;
186: tp->t_tchars.t_startc = DEF_T_STARTC;
187: tp->t_tchars.t_stopc = DEF_T_STOPC;
188: tp->t_tchars.t_eofc = DEF_T_EOFC;
189: tp->t_tchars.t_brkc = DEF_T_BRKC;
190: #ifdef _I386
191: make_termio(&tp->t_sgttyb, &tp->t_tchars, &tp->t_termio);
192: if (tp->t_flags & T_HPCL)
193: tp->t_termio.c_cflag |= HUPCL;
194: else
195: tp->t_termio.c_cflag &= ~HUPCL;
196: tp->t_termio.c_cflag |= (CS8|CREAD);
197: #endif
198: if (tp->t_param)
199: NEAR_OR_FAR_CALL(t_param)
200: }
201:
202: /*
203: * ttsetgrp()
204: *
205: * If process is a group leader without a control terminal,
206: * make its control terminal this device.
207: *
208: * If process is a group leader and this device does not have
209: * a process group, give it the group of the current process.
210: */
211: void ttsetgrp(tp, ctdev, mode)
212: register TTY *tp;
213: dev_t ctdev;
214: int mode;
215: {
216: register PROC *pp;
217:
218: pp = SELF;
219: #ifdef _I386
220: if (pp->p_group == pp->p_pid && 0 == (mode & IPNOCTTY)) {
221: #else
222: if (pp->p_group == pp->p_pid) {
223: #endif
224: if (pp->p_ttdev == NODEV)
225: pp->p_ttdev = ctdev;
226: if (tp->t_group == 0)
227: tp->t_group = pp->p_pid;
228: }
229: }
230:
231: /*
232: * ttyclose()
233: *
234: * Called by driver on the last close.
235: * Wait for all pending output to go out.
236: * Kill input.
237: */
238: void ttclose(tp)
239: register TTY *tp;
240: {
241: register int s;
242:
243: while (tp->t_oq.cq_cc) {
244: s = sphi();
245: if (tp->t_oq.cq_cc) {
246: tp->t_flags |= T_DRAIN;
247: v_sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT,
248: "ttydrain");
249: /* The line discipline is waiting for the tty to drain. */
250: }
251: spl(s);
252: if (SELF->p_ssig && nondsig())
253: break;
254: }
255: ttflush(tp);
256: tp->t_flags = tp->t_group = 0;
257: }
258:
259: /*
260: * ttread()
261: *
262: * The read routine for a tty device driver will call this function.
263: *
264: * Move data from tp->t_iq to io segment iop.
265: * Number of characters to copy is in iop->ioc.
266: *
267: * In cooked mode, copy up to the first newline or break character, or
268: * until the count runs out.
269: * In CBREAK or RAW modes, return when count runs out or when input clist
270: * is empty and we're returning at least one byte.
271: */
272:
273: void ttread(tp, iop)
274: register TTY *tp;
275: register IO *iop;
276: {
277: ttread0(tp, iop, 0, 0, 0, 0);
278: }
279:
280: /*
281: * ttread0()
282: *
283: * Move data from user (in IO struct) to clists.
284: * Do wakeups on functions supplied when read is blocked or completed.
285: */
286: void ttread0(tp, iop, func1, arg1, func2, arg2)
287: register TTY *tp;
288: register IO *iop;
289: int (*func1)(), arg1, (*func2)(), arg2;
290: {
291: register int c;
292: int o;
293: int sioc = iop->io_ioc; /* number of bytes to read */
294:
295: while (iop->io_ioc) {
296: o = sphi();
297: while ((c = getq(&tp->t_iq)) < 0) {
298: if ((tp->t_flags & T_CARR) == 0) {
299: u.u_error = EIO; /* error since no carrier */
300: spl(o);
301: return;
302: }
303:
304: /* If we're in CBREAK or RAW mode, and we don't */
305: /* have the special "blocking read" bit set for */
306: /* these modes, and we read at least one byte */
307: /* of input, return immediately, since we have */
308: /* run out of characters from the clist. */
309:
310: if (ISBBYB && ((tp->t_flags & T_BRD) == 0)
311: && iop->io_ioc < sioc) {
312: spl(o);
313: return;
314: }
315:
316: /*
317: * Non-blocking reads.
318: * Tell user process to try again later.
319: */
320: if (iop->io_flag & IONDLY) {
321: u.u_error = EAGAIN;
322: spl(o);
323: return;
324: }
325:
326: tp->t_flags |= T_INPUT; /* wait for more data */
327: if (func1)
328: (*func1)(arg1);
329: if (func2)
330: (*func2)(arg2);
331: v_sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN,
332: "ttywait");
333: /* The line discipline is waiting for more data. */
334:
335: if (SELF->p_ssig && nondsig()) {
336: if (iop->io_ioc == sioc)
337: u.u_error = EINTR;
338: spl(o);
339: return;
340: }
341: }
342: /*
343: * Flow control - can we turn on input from the driver yet?
344: */
345: if (tp->t_iq.cq_cc <= ILOLIM) {
346: if (tp->t_flags & T_ISTOP)
347: tp->t_flags &= ~T_ISTOP;
348: if (ISTAND && (tp->t_flags&T_TSTOP)) {
349: tp->t_flags &= ~T_TSTOP;
350: while (putq(&tp->t_oq, startc) < 0) {
351: ttstart(tp);
352: waitq();
353: }
354: ttstart(tp);
355: }
356: }
357: spl(o);
358: if (!ISBBYB && ISEOF)
359: goto read_done;
360: if (ioputc(c, iop) < 0)
361: goto read_done;
362: if (!ISBBYB && (c=='\n' || ISBRK))
363: goto read_done;
364: }
365: read_done:
366: if (func1)
367: (*func1)(arg1);
368: if (func2)
369: (*func2)(arg2);
370: }
371:
372: /*
373: * ttwrite()
374: *
375: * Write routine.
376: */
377: void ttwrite(tp, iop)
378: register TTY *tp;
379: register IO *iop;
380: {
381: ttwrite0(tp, iop, 0, 0, 0, 0);
382: }
383:
384: /*
385: * ttwrite0()
386: *
387: * Move data from user (in IO struct) to clists.
388: * Do wakeups on functions supplied when write is blocked or completed.
389: */
390: void ttwrite0(tp, iop, func1, arg1, func2, arg2)
391: register TTY *tp;
392: register IO *iop;
393: int (*func1)(), arg1, (*func2)(), arg2;
394: {
395: register int c;
396: int o;
397:
398: /*
399: * Non-blocking writes which can fit.
400: * NOTE: exhaustion of clists can still cause blocking writes.
401: */
402: if ((iop->io_flag & IONDLY) && (OHILIM >= iop->io_ioc)) {
403:
404: /*
405: * No room.
406: */
407: if (tp->t_oq.cq_cc >= OHILIM-iop->io_ioc) {
408: u.u_error = EAGAIN;
409: return;
410: }
411: }
412:
413: while ((c = iogetc(iop)) >= 0) {
414: if ((tp->t_flags & T_CARR) == 0) {
415: u.u_error = EIO; /* error since no carrier */
416: return;
417: }
418: o = sphi();
419: while (tp->t_oq.cq_cc >= OHILIM) {
420: ttstart(tp);
421: if (tp->t_oq.cq_cc < OHILIM)
422: break;
423: tp->t_flags |= T_HILIM;
424: if (func1)
425: (*func1)(arg1);
426: if (func2)
427: (*func2)(arg2);
428: v_sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT,
429: "ttyoq");
430: /*
431: * The line discipline is waiting for an output
432: * queue to drain.
433: */
434: if (SELF->p_ssig && nondsig()) {
435: u.u_error = EINTR;
436: spl(o);
437: return;
438: }
439: }
440: while (putq(&tp->t_oq, c) < 0) {
441: ttstart(tp);
442: waitq();
443: }
444: spl(o);
445: }
446: o = sphi();
447: ttstart(tp);
448: spl(o);
449: if (func1)
450: (*func1)(arg1);
451: if (func2)
452: (*func2)(arg2);
453: }
454:
455: /*
456: * ttioctl()
457: *
458: * This routine handles common typewriter ioctl functions.
459: * Note that flushing the stream now means drain the output
460: * and clear the input.
461: */
462: void ttioctl(tp, com, vec)
463: register TTY *tp;
464: int com;
465: register struct sgttyb *vec;
466: {
467: register int flush = 0;
468: register int drain = 0;
469: int s;
470: int rload = 0;
471: int was_bbyb;
472:
473: /*
474: * Keep sgttyb, t_chars, AND termio structs for each tty device.
475: *
476: * TCSET* writes a new termio and converts so as to update
477: * sgttyb and t_chars as well.
478: *
479: * TIOCSET[NP] writes new sgttyb and converts so as to update termio.
480: *
481: * TIOCSETC writes new t_chars and converts so as to update termio.
482: */
483: switch (com) {
484: #ifdef _I386
485: case TCGETA:
486: kucopy(&tp->t_termio, vec, sizeof(struct termio));
487: break;
488: case TCSETA:
489: ukcopy(vec, &tp->t_termio, sizeof(struct termio));
490: was_bbyb = ISBBYB; /* previous mode */
491: make_sg(vec, &tp->t_sgttyb, &tp->t_tchars);
492: SET_HPCL;
493: ++rload;
494: if (!was_bbyb && ISBBYB)
495: ttrtp(tp);
496: break;
497: case TCSETAW:
498: ukcopy(vec, &tp->t_termio, sizeof(struct termio));
499: make_sg(vec, &tp->t_sgttyb, &tp->t_tchars);
500: SET_HPCL;
501: ++drain; /* delay for output */
502: ++rload;
503: break;
504: case TCSETAF:
505: ukcopy(vec, &tp->t_termio, sizeof(struct termio));
506: make_sg(vec, &tp->t_sgttyb, &tp->t_tchars);
507: SET_HPCL;
508: ++flush; /* flush input */
509: ++drain; /* delay for output */
510: ++rload;
511: break;
512: #endif
513: case TIOCQUERY:
514: kucopy(&tp->t_iq.cq_cc, vec, sizeof(int));
515: break;
516: case TIOCGETP:
517: kucopy(&tp->t_sgttyb, vec, SGTTY_CPY_LEN);
518: break;
519: case TIOCSETP:
520: DUMPSGTTY(&tp->t_sgttyb);
521: ++flush; /* flush input */
522: ++drain; /* delay for output */
523: ++rload;
524: ukcopy(vec, &tp->t_sgttyb, SGTTY_CPY_LEN);
525: make_termio(&tp->t_sgttyb, &tp->t_tchars, &tp->t_termio);
526: break;
527: case TIOCSETN:
528: DUMPSGTTY(&tp->t_sgttyb);
529: was_bbyb = ISBBYB; /* previous mode */
530: ++rload;
531: ukcopy(vec, &tp->t_sgttyb, SGTTY_CPY_LEN);
532: make_termio(&tp->t_sgttyb, &tp->t_tchars, &tp->t_termio);
533: if (!was_bbyb && ISBBYB)
534: ttrtp(tp);
535: break;
536: case TIOCGETC:
537: kucopy(&tp->t_tchars, vec, sizeof (struct tchars));
538: break;
539: case TIOCSETC:
540: ++rload;
541: ++drain;
542: ukcopy(vec, &tp->t_tchars, sizeof (struct tchars));
543: make_termio(&tp->t_sgttyb, &tp->t_tchars, &tp->t_termio);
544: break;
545: case TIOCEXCL:
546: s = sphi();
547: tp->t_flags |= T_EXCL;
548: spl(s);
549: break;
550: case TIOCNXCL:
551: s = sphi();
552: tp->t_flags &= ~T_EXCL;
553: spl(s);
554: break;
555: case TIOCHPCL: /* set hangup on last close */
556: s = sphi();
557: tp->t_flags |= T_HPCL;
558: spl(s);
559: #ifdef _I386
560: tp->t_termio.c_cflag |= HUPCL;
561: #endif
562: break;
563: case TIOCCHPCL: /* don't hangup on last close */
564: if (!super()) /* only superuser may do this */
565: u.u_error = EPERM; /* not su */
566: else {
567: s = sphi();
568: tp->t_flags &= ~T_HPCL; /* turn off hangup bit */
569: spl(s);
570: #ifdef _I386
571: tp->t_termio.c_cflag &= ~HUPCL;
572: #endif
573: }
574: break;
575: case TIOCGETTF: /* get tty flag word */
576: kucopy(&tp->t_flags, (unsigned *) vec, sizeof(unsigned));
577: break;
578: #ifdef _I386
579: case TCFLSH: /* sleazy - should look at 2nd arg but don't yet */
580: #endif
581: case TIOCFLUSH:
582: ++flush; /* flush both input and output */
583: /* ++drain; Why? - hws - 91/11/22 */
584: break;
585: case TIOCBREAD: /* blocking read for CBREAK/RAW mode */
586: s = sphi();
587: tp->t_flags |= T_BRD;
588: spl(s);
589: break;
590: case TIOCCBREAD: /* turn off CBREAK/RAW blocking read mode */
591: s = sphi();
592: tp->t_flags &= ~T_BRD;
593: spl(s);
594: break;
595: /*
596: * The following is a hack so that the process group for /dev/console
597: * contains the current login shell running on it.
598: * Only expect /etc/init to use this ugliness.
599: */
600: case TIOCSETG:
601: if (super())
602: tp->t_group = SELF->p_group;
603: break;
604: default:
605: u.u_error = EINVAL;
606: }
607:
608: /*
609: * T_STOP is set under two conditions:
610: * - a modem control device is awaiting carrier
611: * - a stopc (usually Ctrl-S) character was received.
612: *
613: * If ioctl just put device into RAWIN mode, make sure device
614: * is not still waiting for startc.
615: */
616: if (ISRIN && (tp->t_flags & T_STOP) && !(tp->t_flags & T_HOPEN)) {
617: s = sphi();
618: tp->t_flags &= ~T_STOP;
619: ttstart(tp);
620: spl(s);
621: }
622:
623: /*
624: * Wait for output to drain, or signal to arrive.
625: */
626: if (drain) {
627: while (tp->t_oq.cq_cc) {
628: s = sphi();
629: tp->t_flags |= T_DRAIN;
630: spl(s);
631: v_sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT,
632: "ttyiodrn");
633: /* A TIOC has asked for tty output to drain. */
634: if (SELF->p_ssig && nondsig())
635: break;
636: }
637: }
638:
639: /*
640: * Flush input.
641: */
642: if (flush)
643: ttflush(tp);
644:
645: /*
646: * Re-initialize hardware.
647: */
648: if (rload) {
649: if ((tp->t_sgttyb.sg_flags & RAWIN)
650: && (tp->t_sgttyb.sg_flags & RAWOUT))
651: tp->t_sgttyb.sg_flags |= RAW;
652: if (tp->t_sgttyb.sg_flags & RAW)
653: tp->t_sgttyb.sg_flags |= (RAWIN|RAWOUT);
654: if (tp->t_param)
655: NEAR_OR_FAR_CALL(t_param)
656: }
657: }
658:
659: /*
660: * ttpoll()
661: *
662: * Polling routine.
663: * [System V.3 Compatible]
664: */
665: int ttpoll(tp, ev, msec)
666: register TTY * tp;
667: int ev;
668: int msec;
669: {
670: /*
671: * Priority polls not supported.
672: */
673: ev &= ~POLLPRI;
674:
675: /*
676: * Input poll with no data present.
677: */
678: if ((ev & POLLIN) && (tp->t_iq.cq_cc == 0)) {
679:
680: /*
681: * Blocking input poll.
682: */
683: if (msec)
684: pollopen(&tp->t_ipolls);
685:
686: /*
687: * Second look to avoid interrupt race.
688: */
689: if (tp->t_iq.cq_cc == 0)
690: ev &= ~POLLIN;
691: }
692:
693: /*
694: * Output poll with no space.
695: */
696: if ((ev & POLLOUT) && (tp->t_oq.cq_cc >= OLOLIM)) {
697:
698: /*
699: * Blocking output poll.
700: */
701: if (msec)
702: pollopen(&tp->t_opolls);
703:
704: /*
705: * Second look to avoid interrupt race.
706: */
707: if (tp->t_oq.cq_cc >= OLOLIM)
708: ev &= ~POLLIN;
709: }
710:
711: if (((ev & POLLIN) == 0) && ((tp->t_flags & T_CARR) == 0))
712: ev |= POLLHUP;
713:
714: return ev;
715: }
716:
717: /*
718: * ttout()
719: *
720: * Pull a character from the output queues of the typewriter.
721: * Doing fills, newline insert, tab expansion, etc.
722: *
723: * If the stream is empty return a -1.
724: * Called at high priority.
725: */
726: int ttout(tp)
727: register TTY *tp;
728: {
729: register int c;
730:
731: if (tp->t_nfill) {
732: --tp->t_nfill;
733: c = tp->t_fillb;
734: } else if (tp->t_flags & T_INL) {
735: tp->t_flags &= ~T_INL;
736: c = '\n';
737: } else {
738: if ((c=getq(&tp->t_oq)) < 0)
739: return -1;
740: if (!ISROUT) {
741: if (c=='\n' && ISCRMOD) {
742: tp->t_flags |= T_INL;
743: c = '\r';
744: } else if (c=='\t' && ISXTABS) {
745: tp->t_nfill = ~(tp->t_hpos|~07);
746: tp->t_fillb = ' ';
747: c = ' ';
748: }
749: }
750: }
751: if (!ISROUT) {
752: if (c == '\b') {
753: if (tp->t_hpos)
754: --tp->t_hpos;
755: } else if (c == '\r')
756: tp->t_hpos = 0;
757: else if (c == '\t')
758: tp->t_hpos = (tp->t_hpos|07) + 1;
759: #if NOT_8_BIT
760: else if (c >= ' ' && c <= '~')
761: #else
762: else if ((c >= ' ' && c <= '~') || (c >= 0200 && c <= 0376))
763: #endif
764: ++tp->t_hpos;
765: }
766: return c;
767: }
768:
769: /*
770: * ttin()
771: *
772: * Pass a character to the device independent typewriter routines.
773: * Handle erase and kill, tandem flow control, and other magic.
774: * Often called at high priority from the driver's interrupt routine.
775: */
776: void
777: ttin(tp, c)
778: register TTY *tp;
779: register int c;
780: {
781: int dc, i, n;
782: int s;
783:
784: if (!ISRIN) {
785: #if NOT_8_BIT
786: c &= 0177;
787: #endif
788: if (ISINTR) {
789: ttsignal(tp, SIGINT);
790: goto ttin_ret;
791: }
792: if (ISQUIT) {
793: ttsignal(tp, SIGQUIT);
794: goto ttin_ret;
795: }
796: }
797: if (tp->t_flags & T_ISTOP)
798: goto ttin_ret;
799: if (!ISRIN) {
800: if (c=='\r' && ISCRMOD)
801: c = '\n';
802: if (tp->t_escape) {
803: if (c == ESC)
804: ++tp->t_escape;
805: else {
806: if (ISERASE || ISKILL) {
807: c |= 0200;
808: --tp->t_escape;
809: }
810: while (tp->t_escape && tp->t_ibx<NCIB-1) {
811: tp->t_ib[tp->t_ibx++] = ESC;
812: --tp->t_escape;
813: }
814: ttstash(tp, c);
815: }
816: if (ISECHO) {
817: #if NOT_8_BIT
818: putq(&tp->t_oq, c&0177);
819: #else
820: putq(&tp->t_oq, c); /* no strip for 8-bit */
821: #endif
822: ttstart(tp);
823: }
824: goto ttin_ret;
825: }
826: if (ISERASE && !ISCBRK) {
827: while (tp->t_escape && tp->t_ibx<NCIB-1) {
828: tp->t_ib[tp->t_ibx++] = ESC;
829: --tp->t_escape;
830: }
831: if (tp->t_ibx == 0)
832: goto ttin_ret;
833: dc = tp->t_ib[--tp->t_ibx];
834: if (ISECHO) {
835: if (!ISCRT)
836: putq(&tp->t_oq, c);
837: /* don't erase for bell, null, or rubout */
838: #if NOT_8_BIT
839: else if (((c = dc&0177) == '\007')
840: || c == 0 || c == 0177)
841: #else
842: else if (((c = dc) == '\007')
843: || c == 0 || c == 0177 || c == 0377)
844: #endif
845: goto ttin_ret;
846: else if (c != '\b' && c != '\t') {
847: putq(&tp->t_oq, '\b');
848: putq(&tp->t_oq, ' ');
849: putq(&tp->t_oq, '\b');
850: } else if (c == '\t') {
851: n = tp->t_opos + tp->t_escape;
852: for (i=0; i<tp->t_ibx; ++i) {
853: c = tp->t_ib[i];
854: #if NOT_8_BIT
855: if (c & 0200) {
856: ++n;
857: c &= 0177;
858: }
859: #endif
860: if (c == '\b')
861: --n;
862: else {
863: if (c == '\t')
864: n |= 07;
865: ++n;
866: }
867: }
868: while (n++ < tp->t_hpos)
869: putq(&tp->t_oq, '\b');
870: }
871: #if NOT_8_BIT
872: if (dc & 0200) {
873: if ((dc&0177) != '\b')
874: putq(&tp->t_oq, '\b');
875: putq(&tp->t_oq, ' ');
876: putq(&tp->t_oq, '\b');
877: }
878: #endif
879: ttstart(tp);
880: }
881: goto ttin_ret;
882: }
883: if (ISKILL && !ISCBRK) {
884: tp->t_ibx = 0;
885: tp->t_escape = 0;
886: if (ISECHO) {
887: if (c < 0x20) {
888: putq(&tp->t_oq, '^');
889: c += 0x40;
890: }
891: putq(&tp->t_oq, c);
892: putq(&tp->t_oq, '\n');
893: ttstart(tp);
894: }
895: goto ttin_ret;
896: }
897: }
898: if (ISBBYB) {
899: putq(&tp->t_iq, c);
900: if (tp->t_flags & T_INPUT) {
901: s = sphi();
902: tp->t_flags &= ~T_INPUT;
903: spl(s);
904: defer(wakeup, (char *) &tp->t_iq);
905: }
906: if (tp->t_ipolls.e_procp) {
907: tp->t_ipolls.e_procp = 0;
908: defer(pollwake, (char *) &tp->t_ipolls);
909: }
910: } else {
911: if (tp->t_ibx == 0)
912: tp->t_opos = tp->t_hpos;
913: if (c == ESC)
914: ++tp->t_escape;
915: else
916: ttstash(tp, c);
917: }
918: if (ISECHO) {
919: if (ISRIN || !ISEOF) {
920: putq(&tp->t_oq, c);
921: ttstart(tp);
922: }
923: }
924: if ((n=tp->t_iq.cq_cc)>=IHILIM) {
925: s = sphi();
926: tp->t_flags |= T_ISTOP;
927: spl(s);
928: } else if (ISTAND && (tp->t_flags&T_TSTOP)==0 && n>=ITSLIM) {
929: s = sphi();
930: tp->t_flags |= T_TSTOP;
931: spl(s);
932: putq(&tp->t_oq, stopc);
933: ttstart(tp);
934: }
935:
936: ttin_ret:
937: return;
938: }
939:
940: /*
941: * ttstash()
942: *
943: * Cooked mode.
944: * Put character in the buffer and check for end of line.
945: * Only a legal end of line can take the last character position.
946: *
947: * Only called from ttin(), and ttin() is called at high priority.
948: */
949: static void ttstash(tp, c)
950: register TTY *tp;
951: {
952: register char *p1, *p2;
953:
954: if (c=='\n' || ISEOF || ISBRK) {
955: p1 = &tp->t_ib[0];
956: p2 = &tp->t_ib[tp->t_ibx];
957: *p2++ = c; /* Always room */
958: while (p1 < p2)
959: #if NOT_8_BIT
960: putq(&tp->t_iq, (*p1++)&0177);
961: #else
962: putq(&tp->t_iq, (*p1++));
963: #endif
964: tp->t_ibx = 0;
965: tp->t_escape = 0;
966:
967: if (tp->t_flags & T_INPUT) {
968: tp->t_flags &= ~T_INPUT;
969: defer(wakeup, (char *) &tp->t_iq);
970: }
971:
972: if (tp->t_ipolls.e_procp) {
973: tp->t_ipolls.e_procp = 0;
974: defer(pollwake, (char *) &tp->t_ipolls);
975: }
976:
977: } else if (tp->t_ibx < NCIB-1)
978: tp->t_ib[tp->t_ibx++] = c;
979: }
980:
981: /*
982: * ttstart()
983: *
984: * Start output on a tty.
985: * Duck out if stopped. Do wakeups.
986: */
987: void ttstart(tp)
988: register TTY *tp;
989: {
990: register int n;
991: int s;
992:
993: n = tp->t_flags;
994: if (n & T_STOP)
995: goto stdone;
996:
997: if ((n&T_DRAIN) && tp->t_oq.cq_cc==0
998: && (n&T_INL)==0 && tp->t_nfill==0) {
999: s = sphi();
1000: tp->t_flags &= ~T_DRAIN;
1001: spl(s);
1002: defer(wakeup, (char *) &tp->t_oq);
1003: goto stdone;
1004: }
1005:
1006: NEAR_OR_FAR_CALL(t_start)
1007:
1008: if (tp->t_oq.cq_cc > OLOLIM)
1009: goto stdone;
1010:
1011: if (n & T_HILIM) {
1012: s = sphi();
1013: tp->t_flags &= ~T_HILIM;
1014: spl(s);
1015: defer(wakeup, (char *) &tp->t_oq);
1016: }
1017:
1018: if (tp->t_opolls.e_procp) {
1019: tp->t_opolls.e_procp = 0;
1020: defer(pollwake, (char *) &tp->t_opolls);
1021: }
1022: stdone:
1023: return;
1024: }
1025:
1026: /*
1027: * ttflush()
1028: *
1029: * Flush a tty.
1030: * Called to clear out queues.
1031: */
1032: void ttflush(tp)
1033: register TTY *tp;
1034: {
1035: int s;
1036:
1037: clrq(&tp->t_iq);
1038: clrq(&tp->t_oq);
1039:
1040: if (tp->t_flags & T_INPUT) {
1041: defer(wakeup, (char *) &tp->t_iq);
1042: }
1043:
1044: if (tp->t_flags & (T_DRAIN|T_HILIM)) {
1045: defer(wakeup, (char *) &tp->t_oq);
1046: }
1047:
1048: if (tp->t_ipolls.e_procp) {
1049: tp->t_ipolls.e_procp = 0;
1050: defer(pollwake, (char *) &tp->t_ipolls);
1051: }
1052:
1053: if (tp->t_opolls.e_procp) {
1054: tp->t_opolls.e_procp = 0;
1055: defer(pollwake, (char *) &tp->t_opolls);
1056: }
1057:
1058: tp->t_ibx = 0;
1059: tp->t_escape = 0;
1060: s = sphi();
1061: tp->t_flags &= T_SAVE; /* reset most flag bits */
1062: spl(s);
1063: }
1064:
1065: /*
1066: * ttsignal()
1067: *
1068: * Send a signal to every process in the given process group.
1069: */
1070: void
1071: ttsignal(tp, sig)
1072: TTY *tp;
1073: int sig;
1074: {
1075: register int g;
1076: register PROC *pp;
1077:
1078: g = tp->t_group;
1079: if (g == 0)
1080: goto sigdone;
1081: ttflush(tp);
1082: pp = &procq;
1083: while ((pp=pp->p_nforw) != &procq)
1084: if (pp->p_group == g) {
1085: sendsig(sig, pp);
1086: }
1087: sigdone:
1088: return;
1089: }
1090:
1091: /*
1092: * tthup()
1093: *
1094: * Flag hangup internally to force errors on tty read/write, flush tty,
1095: * then send hangup signal.
1096: */
1097: void tthup(tp)
1098: register TTY *tp;
1099: {
1100: ttflush(tp);
1101: ttsignal(tp, SIGHUP);
1102: }
1103:
1104: #ifdef _I386
1105: /*
1106: * Convert from sgttyb and tchars structs to termio.
1107: */
1108: static void
1109: make_termio(sgp, tcp, trp)
1110: struct sgttyb * sgp;
1111: struct tchars * tcp;
1112: struct termio * trp;
1113: {
1114: trp->c_cc[VINTR] = tcp->t_intrc;
1115: trp->c_cc[VQUIT] = tcp->t_quitc;
1116: trp->c_cc[VEOF ] = tcp->t_eofc;
1117: trp->c_cc[VEOL ] = '\n';
1118: trp->c_cc[VERASE] = sgp->sg_erase;
1119: trp->c_cc[VKILL ] = sgp->sg_kill;
1120:
1121: trp->c_iflag = BRKINT | ISTRIP | IXON | IGNPAR | INPCK | ISTRIP;
1122: trp->c_oflag = OPOST;
1123: trp->c_cflag &= (CSIZE|HUPCL|CLOCAL|CREAD);
1124: trp->c_lflag = ICANON | ISIG | ECHONL | ECHOK;
1125:
1126: if (sgp->sg_flags & TANDEM)
1127: trp->c_iflag |= IXOFF;
1128:
1129: if (sgp->sg_flags & CRMOD)
1130: trp->c_iflag |= ICRNL;
1131:
1132: if (sgp->sg_flags & LCASE) {
1133: trp->c_lflag |= XCASE;
1134: trp->c_iflag |= IUCLC;
1135: trp->c_oflag |= OLCUC;
1136: }
1137:
1138: if (sgp->sg_flags & RAWIN)
1139: trp->c_iflag &= ~IXON;
1140:
1141: if (sgp->sg_flags & RAWOUT)
1142: trp->c_oflag &= ~OPOST;
1143:
1144: if (sgp->sg_flags & XTABS)
1145: trp->c_oflag |= XTABS;
1146:
1147: if (sgp->sg_flags & CRMOD)
1148: trp->c_oflag |= ONLCR;
1149:
1150: if (sgp->sg_flags & (EVENP|ODDP)) {
1151: trp->c_cflag |= PARENB;
1152: if (sgp->sg_flags & ODDP)
1153: trp->c_cflag |= PARODD;
1154: }
1155: trp->c_cflag |= sgp->sg_ispeed;
1156:
1157: if (sgp->sg_flags & CRT)
1158: trp->c_lflag |= ECHOE;
1159:
1160: if (sgp->sg_flags & RAWIN)
1161: trp->c_lflag &= ~(ISIG|ICANON);
1162:
1163: if (sgp->sg_flags & CBREAK)
1164: trp->c_lflag &= ~ICANON;
1165:
1166: if (sgp->sg_flags & ECHO)
1167: trp->c_lflag |= ECHO;
1168: }
1169:
1170: /*
1171: * Convert from termio struct to sgttyb and tchars.
1172: */
1173: static void
1174: make_sg(trp, sgp, tcp)
1175: struct termio * trp;
1176: struct sgttyb * sgp;
1177: struct tchars * tcp;
1178: {
1179: T_HAL(1, { printf("T:%x:%x:%x:%x ", trp->c_iflag, trp->c_oflag, \
1180: trp->c_cflag, trp->c_lflag);});
1181: tcp->t_intrc = trp->c_cc[VINTR];
1182: tcp->t_quitc = trp->c_cc[VQUIT];
1183: tcp->t_startc= '\021'; /* Ctrl-Q */
1184: tcp->t_stopc = '\023'; /* Ctrl-S */
1185: tcp->t_eofc = trp->c_cc[VEOF];
1186: tcp->t_brkc = -1;
1187:
1188: sgp->sg_erase = trp->c_cc[VERASE];
1189: sgp->sg_kill = trp->c_cc[VKILL ];
1190: sgp->sg_ispeed = trp->c_cflag & CBAUD;
1191: sgp->sg_ospeed = sgp->sg_ispeed;
1192: sgp->sg_flags = RAWIN | RAWOUT | CBREAK;
1193:
1194: if (trp->c_lflag & ECHO)
1195: sgp->sg_flags |= ECHO;
1196:
1197: if (trp->c_lflag & ECHOE)
1198: sgp->sg_flags |= CRT;
1199:
1200: if ( (trp->c_lflag & XCASE)
1201: || (trp->c_oflag & OLCUC)
1202: || (trp->c_iflag & IUCLC))
1203: sgp->sg_flags |= LCASE;
1204:
1205: if (trp->c_iflag & IXOFF)
1206: sgp->sg_flags |= TANDEM;
1207:
1208: if (trp->c_iflag & ICRNL)
1209: sgp->sg_flags |= CRMOD;
1210:
1211: if (trp->c_oflag & ONLCR)
1212: sgp->sg_flags |= CRMOD;
1213:
1214: if (trp->c_oflag & OPOST)
1215: sgp->sg_flags &= ~RAWOUT;
1216:
1217: if (trp->c_oflag & XTABS)
1218: sgp->sg_flags |= XTABS;
1219:
1220: if (trp->c_cflag & PARENB) {
1221: if (trp->c_cflag & PARODD)
1222: sgp->sg_flags |= ODDP;
1223: else
1224: sgp->sg_flags |= EVENP;
1225: }
1226:
1227: if (trp->c_lflag & ISIG)
1228: sgp->sg_flags &= ~RAWIN;
1229:
1230: if (trp->c_lflag & ICANON)
1231: sgp->sg_flags &= ~CBREAK;
1232: }
1233: #endif
1234:
1235: /*
1236: * ttrtp()
1237: *
1238: * Recover contents of typeahead when changing modes.
1239: * Called for ioctls of TIOCSETP and TCSETA,
1240: * when going from not byte-by-byte input to BBYB.
1241: */
1242: static void
1243: ttrtp(tp)
1244: TTY * tp;
1245: {
1246: register char *p1, *p2;
1247:
1248: if (tp->t_ibx) {
1249: p1 = &tp->t_ib[0];
1250: p2 = &tp->t_ib[tp->t_ibx];
1251: while (p1 < p2) {
1252: #if NOT_8_BIT
1253: putq(&tp->t_iq, (*p1++) & 0177);
1254: #else
1255: putq(&tp->t_iq, (*p1++));
1256: #endif
1257: }
1258: tp->t_ibx = 0;
1259: }
1260: }
1261:
1262: /*
1263: * ttinp()
1264: *
1265: * Return nonzero if ttin() may be called to send data for pickup by ttread(),
1266: * or 0 if not.
1267: */
1268: int
1269: ttinp(tp)
1270: TTY * tp;
1271: {
1272: return ((tp->t_flags&T_ISTOP) == 0);
1273: }
1274:
1275: /*
1276: * ttoutp()
1277: *
1278: * Return nonzero if ttout() may be called to fetch data stored by ttwrite(),
1279: * or 0 if not.
1280: */
1281: int
1282: ttoutp(tp)
1283: TTY * tp;
1284: {
1285: return (tp->t_nfill || (tp->t_flags&T_INL) || tp->t_oq.cq_cc);
1286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.