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