|
|
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.15 92/01/13 08:58:40 bin
11: * update by hal for 321 kernel (looks like just additions of debug stuff)
12: *
13: * Revision 1.15 92/01/13 08:36:53 hal
14: * Add a few DEBUG lines.
15: *
16: * Revision 1.14 92/01/09 09:42:31 hal
17: * Add debug conditionals for sleeps.
18: * Fix process group logic, including TIOCSETG hack.
19: *
20: * Revision 1.13 91/12/10 17:01:56 hal
21: * Don't wait for drain on TIOCFLUSH.
22: *
23: * Revision 1.12 91/11/14 14:28:51 hal
24: * Move flow control out of tty.c.
25: * Make ttin() run at hi priority.
26: *
27: * Revision 1.11 91/09/16 18:11:08 hal
28: * Update t_flags in ttstart() at high priority.
29: * Document that ttstash() is local.
30: *
31: * Revision 1.10 91/09/16 15:58:26 hal
32: * Mask interrrupts when modifying tp->t_flags as some IRQ handlers change this.
33: *
34: * Revision 1.9 91/09/16 10:27:47 hal
35: * Explain T_ISTOP/T_TSTOP/T_STOP.
36: * Add check for TANDEM before sending t_startc.
37: *
38: * Revision 1.8 91/09/13 18:01:39 piggy
39: * Only do XON/XOFF flow control if TANDEM is set.
40: *
41: * Revision 1.7 91/09/13 17:58:00 hal
42: * Drop 3rd arg (was writing PSW directly from it!) for ttread/ttwrite.
43: * General face lift.
44: *
45: * Bug: no support for 8-bit characters.
46: * Fix: don't strip keyboard input. 01/22/91. (norm)
47: *
48: * Bug: Switching modes between cooked and CBREAK/RAW left buffered input
49: * in the input buffer until returning to cooked mode. 05/13/91 norm
50: *
51: * Bug: setting speed to default in ttopen() was conditioned to
52: * use hard constants. 90/08/28. hws
53: *
54: * Revision 1.5 91/06/06 18:28:53 norm
55: * Restore 8-bit fix.
56: *
57: * Revision 1.2 89/07/17 11:51:20 src
58: * Bug: Terminal could lock up when setting it to RAWIN mode, if
59: * output was suspended due to X-OFF, and output data was present.
60: * Fix: Setting terminal to RAWIN mode now clears X-OFF, starts output
61: * BEFORE waiting for output to drain. Received signals now cause
62: * operation to complete without waiting for drain. (ABC)
63: *
64: * Revision 1.1 88/03/24 16:18:12 src
65: * Initial revision
66: *
67: * 86/12/12 Allan Cornish /usr/src/sys/drv/tty.c
68: * Added 3rd argument to ttpoll() to support non-blocking polls.
69: *
70: * 86/11/19 Allan Cornish /usr/src/sys/drv/tty.c
71: * Made ttread() and ttwrite() recognize the IONDLY flag in iop->io_flag.
72: * wakeup() and pollwake() now have delayed invocation by defer().
73: * Added poll [System V.3] capability.
74: *
75: * 85/06/28 Allan Cornish
76: * made ttioctl() clear T_STOP flag if ISRIN.
77: *
78: * 85/03/04 Allan Cornish
79: * made ttread() interruptible.
80: *
81: * 85/03/01 Allan Cornish
82: * made ttclose() interruptible.
83: */
84:
85: /*
86: * About STOP flag bits:
87: * T_ISTOP is set when the tty module's input queue is in danger of
88: * overflow. It is up to the device driver to check this flag
89: * and do something about it. If ttin() is called with a
90: * character from the device while T_ISTOP is set, the character
91: * is discarded. T_ISTOP is cleared when the input queue is
92: * sufficiently empty. The device driver can monitor this bit for
93: * hardware flow control.
94: * T_TSTOP is the "Tandem" flow control flag for input. If TANDEM is set
95: * and the input queue is in danger of overflow, t_stopc is sent
96: * and T_TSTOP is set. When the input queue is empty enough,
97: * t_startc is sent and T_TSTOP is cleared.
98: * T_STOP is the flow control bit for output. No output will be
99: * written to the output queue while this bit is true.
100: * Except for initialization of flags in the TTY struct, by
101: * ttopen(), this bit is not written by tty.c.
102: * 91/09/15 - hal
103: */
104:
105: /*
106: * Includes.
107: */
108: #include <sys/clist.h>
109: #include <sys/coherent.h>
110: #include <sys/con.h>
111: #include <sys/deftty.h>
112: #include <sys/io.h>
113: #include <sys/proc.h>
114: #include <sys/sched.h>
115: #include <sys/stat.h>
116: #include <sys/tty.h>
117: #include <sys/uproc.h>
118: #include <errno.h>
119:
120: /*
121: * Definitions.
122: * Constants.
123: * Macros with argument lists.
124: * Typedefs.
125: * Enums.
126: */
127:
128: /* NEAR_OR_FAR_CALL is for invoking t_param and t_start */
129: #define NEAR_OR_FAR_CALL(tp_fn) {\
130: if (tp->t_cs_sel) \
131: ld_call(tp->t_cs_sel, tp->tp_fn, tp); \
132: else \
133: (*tp->tp_fn)(tp); }
134:
135: /*
136: * Functions.
137: * Import Functions.
138: * Export Functions.
139: * Local Functions.
140: */
141: void ttclose();
142: void ttflush();
143: void tthup();
144: void ttin();
145: void ttioctl();
146: void ttopen();
147: int ttout();
148: int ttpoll();
149: void ttread();
150: void ttsetgrp();
151: void ttsignal();
152: void ttstart();
153: void ttwrite();
154:
155: static void ttstash();
156:
157: /*
158: * Global Data.
159: * Import Variables.
160: * Export Variables.
161: * Local Variables.
162: */
163: extern int wakeup();
164: extern void pollwake();
165:
166: /*
167: * ttopen()
168: *
169: * Called by driver on first open.
170: * Set up defaults.
171: */
172: void ttopen(tp)
173: register TTY *tp;
174: {
175: tp->t_escape = 0;
176: tp->t_sgttyb.sg_ispeed = tp->t_dispeed;
177: tp->t_sgttyb.sg_ospeed = tp->t_dospeed;
178: tp->t_sgttyb.sg_erase = DEF_SG_ERASE;
179: tp->t_sgttyb.sg_kill = DEF_SG_KILL;
180: tp->t_sgttyb.sg_flags = DEF_SG_FLAGS;
181: tp->t_tchars.t_intrc = DEF_T_INTRC;
182: tp->t_tchars.t_quitc = DEF_T_QUITC;
183: tp->t_tchars.t_startc = DEF_T_STARTC;
184: tp->t_tchars.t_stopc = DEF_T_STOPC;
185: tp->t_tchars.t_eofc = DEF_T_EOFC;
186: tp->t_tchars.t_brkc = DEF_T_BRKC;
187: if (tp->t_param != NULL) {
188: NEAR_OR_FAR_CALL(t_param)
189: }
190: }
191:
192: /*
193: * ttsetgrp()
194: *
195: * If process is a group leader without a control terminal,
196: * make its control terminal this device.
197: *
198: * If process is a group leader and this device does not have
199: * a process group, give it the group of the current process.
200: */
201: void ttsetgrp(tp, ctdev)
202: register TTY *tp;
203: dev_t ctdev;
204: {
205: register PROC *pp;
206:
207: pp = SELF;
208: #if DEBUG
209: printf("ttsetgrp dev=%x pid=%d pg=%d ", ctdev, pp->p_pid, pp->p_group);
210: printf("old_ct=%x old_tg=%d ", pp->p_ttdev, tp->t_group);
211: #endif
212: if (pp->p_group == pp->p_pid) {
213: if (pp->p_ttdev == NODEV)
214: pp->p_ttdev = ctdev;
215: if (tp->t_group == 0)
216: tp->t_group = pp->p_pid;
217: }
218: #if DEBUG
219: printf("new_ct=%x new_tg=%d\n", pp->p_ttdev, tp->t_group);
220: #endif
221: }
222:
223: /*
224: * ttyclose()
225: *
226: * Called by driver on the last close.
227: * Wait for all pending output to go out.
228: * Kill input.
229: */
230: void ttclose(tp)
231: register TTY *tp;
232: {
233: register int s;
234:
235: while (tp->t_oq.cq_cc != 0) {
236: s = sphi();
237: if (tp->t_oq.cq_cc != 0) {
238: tp->t_flags |= T_DRAIN;
239: #if DEBUG
240: printf("T1 ");
241: #endif
242: sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
243: #if DEBUG
244: printf("z ");
245: #endif
246: }
247: spl(s);
248: if (SELF->p_ssig && nondsig())
249: break;
250: }
251: ttflush(tp);
252: tp->t_flags = tp->t_group = 0;
253: }
254:
255: /*
256: * ttread()
257: *
258: * The read routine for a tty device driver will call this function.
259: *
260: * Move data from tp->t_iq to io segment iop.
261: * Number of characters to copy is in iop->ioc.
262: *
263: * In cooked mode, copy up to the first newline or break character, or
264: * until the count runs out.
265: * In CBREAK or RAW modes, return when count runs out or when input clist
266: * is empty and we're returning at least one byte.
267: */
268: void ttread(tp, iop)
269: register TTY *tp;
270: register IO *iop;
271: {
272: register c;
273: int o;
274: int sioc = iop->io_ioc; /* number of bytes to read */
275:
276: while (iop->io_ioc) {
277: o = sphi();
278: while ((c = getq(&tp->t_iq)) < 0) {
279: if ((tp->t_flags & T_CARR) == 0) {
280: u.u_error = EIO; /* error since no carrier */
281: spl(o);
282: return;
283: }
284:
285: /* If we're in CBREAK or RAW mode, and we don't */
286: /* have the special "blocking read" bit set for */
287: /* these modes, and we read at least one byte */
288: /* of input, return immediately, since we have */
289: /* run out of characters from the clist. */
290:
291: if (ISBBYB && ((tp->t_flags & T_BRD) == 0)
292: && iop->io_ioc < sioc) {
293: spl(o);
294: return;
295: }
296:
297: /*
298: * Non-blocking reads.
299: * Tell user process to try again later.
300: */
301: if (iop->io_flag & IONDLY) {
302: u.u_error = EAGAIN;
303: spl(o);
304: return;
305: }
306:
307: tp->t_flags |= T_INPUT; /* wait for more data */
308: #if DEBUG
309: printf("T2 ");
310: #endif
311: sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN);
312: #if DEBUG
313: printf("z ");
314: #endif
315:
316: if (SELF->p_ssig && nondsig()) {
317: if (iop->io_ioc == sioc)
318: u.u_error = EINTR;
319: spl(o);
320: return;
321: }
322: }
323: /*
324: * Flow control - can we turn on input from the driver yet?
325: */
326: if (tp->t_iq.cq_cc <= ILOLIM) {
327: if ((tp->t_flags&T_ISTOP) != 0)
328: tp->t_flags &= ~T_ISTOP;
329: if (ISTAND && (tp->t_flags&T_TSTOP) != 0) {
330: tp->t_flags &= ~T_TSTOP;
331: while (putq(&tp->t_oq, startc) < 0) {
332: ttstart(tp);
333: waitq();
334: }
335: ttstart(tp);
336: }
337: }
338: spl(o);
339: if (!ISBBYB && ISEOF)
340: return;
341: if (ioputc(c, iop) < 0)
342: return;
343: if (!ISBBYB && (c=='\n' || ISBRK))
344: return;
345: }
346: }
347:
348: /*
349: * ttwrite()
350: *
351: * Write routine.
352: * Transfer stuff to the character list.
353: */
354: void ttwrite(tp, iop)
355: register TTY *tp;
356: register IO *iop;
357: {
358: register c;
359: int o;
360:
361: /*
362: * Non-blocking writes which can fit.
363: * NOTE: exhaustion of clists can still cause blocking writes.
364: */
365: if ((iop->io_flag & IONDLY) && (OHILIM >= iop->io_ioc)) {
366:
367: /*
368: * No room.
369: */
370: if (tp->t_oq.cq_cc >= OHILIM-iop->io_ioc) {
371: u.u_error = EAGAIN;
372: return;
373: }
374: }
375:
376: while ((c = iogetc(iop)) >= 0) {
377: if ((tp->t_flags & T_CARR) == 0) {
378: u.u_error = EIO; /* error since no carrier */
379: return;
380: }
381: o = sphi();
382: while (tp->t_oq.cq_cc >= OHILIM) {
383: ttstart(tp);
384: if (tp->t_oq.cq_cc < OHILIM)
385: break;
386: tp->t_flags |= T_HILIM;
387: #if DEBUG
388: printf("T3 ");
389: #endif
390: sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
391: #if DEBUG
392: printf("z ");
393: #endif
394: if (SELF->p_ssig && nondsig()) {
395: u.u_error = EINTR;
396: spl(o);
397: return;
398: }
399: }
400: while (putq(&tp->t_oq, c) < 0) {
401: ttstart(tp);
402: waitq();
403: }
404: spl(o);
405: }
406: o = sphi();
407: ttstart(tp);
408: spl(o);
409: }
410:
411: /*
412: * ttioctl()
413: *
414: * This routine handles common typewriter ioctl functions.
415: * Note that flushing the stream now means drain the output
416: * and clear the input.
417: */
418: void ttioctl(tp, com, vec)
419: register TTY *tp;
420: register struct sgttyb *vec;
421: {
422: register int flush = 0;
423: register int drain = 0;
424: register char *p1, *p2;
425: int s;
426: int rload = 0;
427: int was_bbyb = 0;
428:
429: switch (com) {
430: case TIOCQUERY:
431: kucopy(&tp->t_iq.cq_cc, vec, sizeof(int));
432: break;
433: case TIOCGETP:
434: kucopy(&tp->t_sgttyb, vec, sizeof (struct sgttyb));
435: break;
436: case TIOCSETP:
437: ++flush; /* flush input */
438: ++drain; /* delay for output */
439: ++rload;
440: ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
441: break;
442: case TIOCSETN:
443: was_bbyb = ISBBYB; /* previous mode */
444: ++rload;
445: ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
446: if (!was_bbyb && ISBBYB && tp->t_ibx != 0) {
447: p1 = &tp->t_ib[0];
448: p2 = &tp->t_ib[tp->t_ibx];
449: while (p1 < p2)
450: #if NOT_8_BIT
451: putq(&tp->t_iq, (*p1++) & 0177);
452: #else
453: putq(&tp->t_iq, (*p1++));
454: #endif
455: tp->t_ibx = 0;
456: }
457: break;
458: case TIOCGETC:
459: kucopy(&tp->t_tchars, vec, sizeof (struct tchars));
460: break;
461: case TIOCSETC:
462: ++rload;
463: ++drain;
464: ukcopy(vec, &tp->t_tchars, sizeof (struct tchars));
465: break;
466: case TIOCEXCL:
467: s = sphi();
468: tp->t_flags |= T_EXCL;
469: spl(s);
470: break;
471: case TIOCNXCL:
472: s = sphi();
473: tp->t_flags &= ~T_EXCL;
474: spl(s);
475: break;
476: case TIOCHPCL: /* set hangup on last close */
477: s = sphi();
478: tp->t_flags |= T_HPCL;
479: spl(s);
480: break;
481: case TIOCCHPCL: /* don't hangup on last close */
482: if (!super()) /* only superuser may do this */
483: u.u_error = EPERM; /* not su */
484: else {
485: s = sphi();
486: tp->t_flags &= ~T_HPCL; /* turn off hangup bit */
487: spl(s);
488: }
489: break;
490: case TIOCGETTF: /* get tty flag word */
491: kucopy(&tp->t_flags, (unsigned *) vec, sizeof(unsigned));
492: break;
493: case TIOCFLUSH:
494: ++flush; /* flush both input and output */
495: /* ++drain; Why? - hws - 91/11/22 */
496: break;
497: case TIOCBREAD: /* blocking read for CBREAK/RAW mode */
498: s = sphi();
499: tp->t_flags |= T_BRD;
500: spl(s);
501: break;
502: case TIOCCBREAD: /* turn off CBREAK/RAW blocking read mode */
503: s = sphi();
504: tp->t_flags &= ~T_BRD;
505: spl(s);
506: break;
507: /*
508: * The following is a hack so that the process group for /dev/console
509: * contains the current login shell running on it.
510: * Only expect /etc/init to use this ugliness.
511: */
512: case TIOCSETG:
513: if (super())
514: tp->t_group = SELF->p_group;
515: break;
516: default:
517: u.u_error = EINVAL;
518: }
519:
520: /*
521: * Wait for output to drain, or signal to arrive.
522: */
523: if (drain != 0) {
524:
525: /*
526: * Ensure output is enabled BEFORE waiting for output to drain.
527: */
528: if (ISRIN && (tp->t_flags & T_STOP)) {
529: s = sphi();
530: tp->t_flags &= ~T_STOP;
531: ttstart(tp);
532: spl(s);
533: }
534:
535: while (tp->t_oq.cq_cc != 0) {
536: s = sphi();
537: tp->t_flags |= T_DRAIN;
538: spl(s);
539: #if DEBUG
540: printf("T4 ");
541: #endif
542: sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
543: #if DEBUG
544: printf("z ");
545: #endif
546: if (SELF->p_ssig && nondsig())
547: break;
548: }
549: }
550:
551: /*
552: * Flush input.
553: */
554: if (flush != 0)
555: ttflush(tp);
556:
557: /*
558: * Re-initialize hardware.
559: */
560: if ((rload != 0) && (tp->t_param != NULL))
561: NEAR_OR_FAR_CALL(t_param)
562: }
563:
564: /*
565: * ttpoll()
566: *
567: * Polling routine.
568: * [System V.3 Compatible]
569: */
570: int ttpoll(tp, ev, msec)
571: register TTY * tp;
572: int ev;
573: int msec;
574: {
575: /*
576: * Priority polls not supported.
577: */
578: ev &= ~POLLPRI;
579:
580: /*
581: * Input poll with no data present.
582: */
583: if ((ev & POLLIN) && (tp->t_iq.cq_cc == 0)) {
584:
585: /*
586: * Blocking input poll.
587: */
588: if (msec != 0)
589: pollopen(&tp->t_ipolls);
590:
591: /*
592: * Second look to avoid interrupt race.
593: */
594: if (tp->t_iq.cq_cc == 0)
595: ev &= ~POLLIN;
596: }
597:
598: /*
599: * Output poll with no space.
600: */
601: if ((ev & POLLOUT) && (tp->t_oq.cq_cc >= OLOLIM)) {
602:
603: /*
604: * Blocking output poll.
605: */
606: if (msec != 0)
607: pollopen(&tp->t_opolls);
608:
609: /*
610: * Second look to avoid interrupt race.
611: */
612: if (tp->t_oq.cq_cc >= OLOLIM)
613: ev &= ~POLLIN;
614: }
615:
616: if (((ev & POLLIN) == 0) && ((tp->t_flags & T_CARR) == 0))
617: ev |= POLLHUP;
618:
619: return ev;
620: }
621:
622: /*
623: * ttout()
624: *
625: * Pull a character from the output queues of the typewriter.
626: * Doing fills, newline insert, tab expansion, etc.
627: *
628: * If the stream is empty return a -1.
629: * Called at high priority.
630: */
631: int ttout(tp)
632: register TTY *tp;
633: {
634: register c;
635:
636: if (tp->t_nfill) {
637: --tp->t_nfill;
638: c = tp->t_fillb;
639: } else if ((tp->t_flags&T_INL) != 0) {
640: tp->t_flags &= ~T_INL;
641: c = '\n';
642: } else {
643: if ((c=getq(&tp->t_oq)) < 0)
644: return -1;
645: if (!ISROUT) {
646: if (c=='\n' && ISCRMOD) {
647: tp->t_flags |= T_INL;
648: c = '\r';
649: } else if (c=='\t' && ISXTABS) {
650: tp->t_nfill = ~(tp->t_hpos|~07);
651: tp->t_fillb = ' ';
652: c = ' ';
653: }
654: }
655: }
656: if (!ISROUT) {
657: if (c == '\b') {
658: if (tp->t_hpos)
659: --tp->t_hpos;
660: } else if (c == '\r')
661: tp->t_hpos = 0;
662: else if (c == '\t')
663: tp->t_hpos = (tp->t_hpos|07) + 1;
664: #if NOT_8_BIT
665: else if (c >= ' ' && c <= '~')
666: #else
667: else if ((c >= ' ' && c <= '~') || (c >= 0200 && c <= 0376))
668: #endif
669: ++tp->t_hpos;
670: }
671: return c;
672: }
673:
674: /*
675: * ttin()
676: *
677: * Pass a character to the device independent typewriter routines.
678: * Handle erase and kill, tandem flow control, and other magic.
679: * Often called at high priority from the driver's interrupt routine.
680: */
681: void ttin(tp, c)
682: register TTY *tp;
683: register c;
684: {
685: int dc, i, n;
686: int s;
687:
688: if (!ISRIN) {
689: #if NOT_8_BIT
690: c &= 0177;
691: #endif
692: if (ISINTR) {
693: ttsignal(tp, SIGINT);
694: goto ttin_ret;
695: }
696: if (ISQUIT) {
697: ttsignal(tp, SIGQUIT);
698: goto ttin_ret;
699: }
700: }
701: if ((tp->t_flags&T_ISTOP) != 0)
702: goto ttin_ret;
703: if (!ISRIN) {
704: if (c=='\r' && ISCRMOD)
705: c = '\n';
706: if (tp->t_escape != 0) {
707: if (c == ESC)
708: ++tp->t_escape;
709: else {
710: if (ISERASE || ISKILL) {
711: c |= 0200;
712: --tp->t_escape;
713: }
714: while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
715: tp->t_ib[tp->t_ibx++] = ESC;
716: --tp->t_escape;
717: }
718: ttstash(tp, c);
719: }
720: if (ISECHO) {
721: #if NOT_8_BIT
722: putq(&tp->t_oq, c&0177);
723: #else
724: putq(&tp->t_oq, c); /* no strip for 8-bit */
725: #endif
726: ttstart(tp);
727: }
728: goto ttin_ret;
729: }
730: if (ISERASE && !ISCBRK) {
731: while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
732: tp->t_ib[tp->t_ibx++] = ESC;
733: --tp->t_escape;
734: }
735: if (tp->t_ibx == 0)
736: goto ttin_ret;
737: dc = tp->t_ib[--tp->t_ibx];
738: if (ISECHO) {
739: if (!ISCRT)
740: putq(&tp->t_oq, c);
741: /* don't erase for bell, null, or rubout */
742: #if NOT_8_BIT
743: else if (((c = dc&0177) == '\007')
744: || c == 0 || c == 0177)
745: #else
746: else if (((c = dc) == '\007')
747: || c == 0 || c == 0177 || c == 0377)
748: #endif
749: goto ttin_ret;
750: else if (c != '\b' && c != '\t') {
751: putq(&tp->t_oq, '\b');
752: putq(&tp->t_oq, ' ');
753: putq(&tp->t_oq, '\b');
754: } else if (c == '\t') {
755: n = tp->t_opos + tp->t_escape;
756: for (i=0; i<tp->t_ibx; ++i) {
757: c = tp->t_ib[i];
758: #if NOT_8_BIT
759: if ((c&0200) != 0) {
760: ++n;
761: c &= 0177;
762: }
763: #endif
764: if (c == '\b')
765: --n;
766: else {
767: if (c == '\t')
768: n |= 07;
769: ++n;
770: }
771: }
772: while (n++ < tp->t_hpos)
773: putq(&tp->t_oq, '\b');
774: }
775: #if NOT_8_BIT
776: if ((dc&0200) != 0) {
777: if ((dc&0177) != '\b')
778: putq(&tp->t_oq, '\b');
779: putq(&tp->t_oq, ' ');
780: putq(&tp->t_oq, '\b');
781: }
782: #endif
783: ttstart(tp);
784: }
785: goto ttin_ret;
786: }
787: if (ISKILL && !ISCBRK) {
788: tp->t_ibx = 0;
789: tp->t_escape = 0;
790: if (ISECHO) {
791: if (c < 0x20) {
792: putq(&tp->t_oq, '^');
793: c += 0x40;
794: }
795: putq(&tp->t_oq, c);
796: putq(&tp->t_oq, '\n');
797: ttstart(tp);
798: }
799: goto ttin_ret;
800: }
801: }
802: if (ISBBYB) {
803: putq(&tp->t_iq, c);
804: if ((tp->t_flags&T_INPUT) != 0) {
805: s = sphi();
806: tp->t_flags &= ~T_INPUT;
807: spl(s);
808: defer(wakeup, (char *) &tp->t_iq);
809: }
810: if (tp->t_ipolls.e_procp) {
811: tp->t_ipolls.e_procp = 0;
812: defer(pollwake, (char *) &tp->t_ipolls);
813: }
814: } else {
815: if (tp->t_ibx == 0)
816: tp->t_opos = tp->t_hpos;
817: if (c == ESC)
818: ++tp->t_escape;
819: else
820: ttstash(tp, c);
821: }
822: if (ISECHO) {
823: if (ISRIN || !ISEOF) {
824: putq(&tp->t_oq, c);
825: ttstart(tp);
826: }
827: }
828: if ((n=tp->t_iq.cq_cc)>=IHILIM) {
829: s = sphi();
830: tp->t_flags |= T_ISTOP;
831: spl(s);
832: } else if (ISTAND && (tp->t_flags&T_TSTOP)==0 && n>=ITSLIM) {
833: s = sphi();
834: tp->t_flags |= T_TSTOP;
835: spl(s);
836: putq(&tp->t_oq, stopc);
837: ttstart(tp);
838: }
839:
840: ttin_ret:
841: return;
842: }
843:
844: /*
845: * ttstash()
846: *
847: * Cooked mode.
848: * Put character in the buffer and check for end of line.
849: * Only a legal end of line can take the last character position.
850: *
851: * Only called from ttin(), and ttin() is called at high priority.
852: */
853: static void ttstash(tp, c)
854: register TTY *tp;
855: {
856: register char *p1, *p2;
857:
858: if (c=='\n' || ISEOF || ISBRK) {
859: p1 = &tp->t_ib[0];
860: p2 = &tp->t_ib[tp->t_ibx];
861: *p2++ = c; /* Always room */
862: while (p1 < p2)
863: #if NOT_8_BIT
864: putq(&tp->t_iq, (*p1++)&0177);
865: #else
866: putq(&tp->t_iq, (*p1++));
867: #endif
868: tp->t_ibx = 0;
869: tp->t_escape = 0;
870:
871: if (tp->t_flags & T_INPUT) {
872: tp->t_flags &= ~T_INPUT;
873: defer(wakeup, (char *) &tp->t_iq);
874: }
875:
876: if (tp->t_ipolls.e_procp) {
877: tp->t_ipolls.e_procp = 0;
878: defer(pollwake, (char *) &tp->t_ipolls);
879: }
880:
881: } else if (tp->t_ibx < NCIB-1)
882: tp->t_ib[tp->t_ibx++] = c;
883: }
884:
885: /*
886: * ttstart()
887: *
888: * Start output on a tty.
889: * Duck out if stopped. Do wakeups.
890: */
891: void ttstart(tp)
892: register TTY *tp;
893: {
894: register int n;
895: int s;
896:
897: n = tp->t_flags;
898: if (n & T_STOP)
899: goto stdone;
900:
901: if ((n&T_DRAIN)!=0 && tp->t_oq.cq_cc==0
902: && (n&T_INL)==0 && tp->t_nfill==0) {
903: s = sphi();
904: tp->t_flags &= ~T_DRAIN;
905: spl(s);
906: defer(wakeup, (char *) &tp->t_oq);
907: goto stdone;
908: }
909:
910: NEAR_OR_FAR_CALL(t_start)
911:
912: if (tp->t_oq.cq_cc > OLOLIM)
913: goto stdone;
914:
915: if (n & T_HILIM) {
916: s = sphi();
917: tp->t_flags &= ~T_HILIM;
918: spl(s);
919: defer(wakeup, (char *) &tp->t_oq);
920: }
921:
922: if (tp->t_opolls.e_procp) {
923: tp->t_opolls.e_procp = 0;
924: defer(pollwake, (char *) &tp->t_opolls);
925: }
926: stdone:
927: return;
928: }
929:
930: /*
931: * ttflush()
932: *
933: * Flush a tty.
934: * Called to clear out queues.
935: */
936: void ttflush(tp)
937: register TTY *tp;
938: {
939: int s;
940:
941: clrq(&tp->t_iq);
942: clrq(&tp->t_oq);
943:
944: if (tp->t_flags & T_INPUT)
945: defer(wakeup, (char *) &tp->t_iq);
946:
947: if (tp->t_flags & (T_DRAIN|T_HILIM))
948: defer(wakeup, (char *) &tp->t_oq);
949:
950: if (tp->t_ipolls.e_procp != 0) {
951: tp->t_ipolls.e_procp = 0;
952: defer(pollwake, (char *) &tp->t_ipolls);
953: }
954:
955: if (tp->t_opolls.e_procp != 0) {
956: tp->t_opolls.e_procp = 0;
957: defer(pollwake, (char *) &tp->t_opolls);
958: }
959:
960: tp->t_ibx = 0;
961: tp->t_escape = 0;
962: s = sphi();
963: tp->t_flags &= T_SAVE; /* reset most flag bits */
964: spl(s);
965: }
966:
967: /*
968: * ttsignal()
969: *
970: * Send a signal to every process in the given process group.
971: */
972: void ttsignal(tp, sig)
973: TTY *tp;
974: int sig;
975: {
976: register int g;
977: register PROC *pp;
978:
979: g = tp->t_group;
980: #if DEBUG
981: printf("ttsignal sig=%d gp=%d\n", sig, g);
982: #endif
983: if (g == 0)
984: goto sigdone;
985: ttflush(tp);
986: pp = &procq;
987: while ((pp=pp->p_nforw) != &procq)
988: if (pp->p_group == g) {
989: sendsig(sig, pp);
990: }
991: sigdone:
992: return;
993: }
994:
995: /*
996: * tthup()
997: *
998: * Flag hangup internally to force errors on tty read/write, flush tty,
999: * then send hangup signal.
1000: */
1001: void tthup(tp)
1002: register TTY *tp;
1003: {
1004: ttflush(tp);
1005: ttsignal(tp, SIGHUP);
1006: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.