void tty_hangup(uint8_t minor) { struct tty *t = &ttydata[minor]; /* Kill users */ sgrpsig(t->pgrp, SIGHUP); sgrpsig(t->pgrp, SIGCONT); t->pgrp = 0; /* Stop any new I/O with errors */ t->flag |= TTYF_DEAD; /* Wake up read/write */ wakeup(&ttyinq[minor]); /* Wake stopped stuff */ wakeup(&t->flag); /* and deadflag will clear when the last user goes away */ }
void tty_hangup(uint8_t minor) { /* Kill users */ sgrpsig(tty_pgrp[minor], SIGHUP); /* Stop any new I/O with errors */ deadflag[minor] = 1; /* Wake up read/write */ wakeup(&ttyinq[minor]); wakeup(&stopflag[minor]); /* and deadflag will clear when the last user goes away */ }
int tty_inproc(uint8_t minor, unsigned char c) { unsigned char oc; struct termios *td; struct s_queue *q = &ttyinq[minor]; int canon; uint16_t pgrp = tty_pgrp[minor]; uint8_t wr; td = &ttydata[minor]; canon = td->c_lflag & ICANON; if (td->c_iflag & ISTRIP) c &= 0x7f; /* Strip off parity */ if (canon && !c) return 1; /* Simply quit if Null character */ #ifdef CONFIG_IDUMP if (c == 0x1a) /* ^Z */ idump(); /* (For debugging) */ #endif #ifdef CONFIG_MONITOR if (c == 0x01) /* ^A */ trap_monitor(); #endif if (c == '\r' && (td->c_iflag & ICRNL)) c = '\n'; if (c == '\n' && (td->c_iflag & INLCR)) c = '\r'; if (td->c_lflag & ISIG) { if (c == td->c_cc[VINTR]) { /* ^C */ sgrpsig(pgrp, SIGINT); clrq(q); stopflag[minor] = flshflag[minor] = false; return 1; } else if (c == td->c_cc[VQUIT]) { /* ^\ */ sgrpsig(pgrp, SIGQUIT); clrq(q); stopflag[minor] = flshflag[minor] = false; return 1; } } if (c == td->c_cc[VDISCARD]) { /* ^O */ flshflag[minor] = !flshflag[minor]; return 1; } if (td->c_iflag & IXON) { if (c == td->c_cc[VSTOP]) { /* ^S */ stopflag[minor] = true; return 1; } if (c == td->c_cc[VSTART]) { /* ^Q */ stopflag[minor] = false; wakeup(&stopflag[minor]); return 1; } } if (canon) { if (c == td->c_cc[VERASE]) { if (uninsq(q, &oc)) { if (oc == '\n' || oc == td->c_cc[VEOL]) insq(q, oc); /* Don't erase past nl */ else if (td->c_lflag & ECHOE) tty_erase(minor); return 1; } else if (c == td->c_cc[VKILL]) { while (uninsq(q, &oc)) { if (oc == '\n' || oc == td->c_cc[VEOL]) { insq(q, oc); /* Don't erase past nl */ break; } if (td->c_lflag & ECHOK) tty_erase(minor); } return 1; } } } /* All modes come here */ if (c == '\n') { if ((td->c_oflag & OPOST | ONLCR) == OPOST | ONLCR) tty_echo(minor, '\r'); } wr = insq(q, c); if (wr) tty_echo(minor, c); else if (minor < PTY_OFFSET) tty_putc_wait(minor, '\007'); /* Beep if no more room */ if (!canon || c == td->c_cc[VEOL] || c == '\n' || c == td->c_cc[VEOF]) wakeup(q); return wr; }
/* This routine processes a character in response to an interrupt. It * adds the character to the tty input queue, echoing and processing * backspace and carriage return. If the queue contains a full line, * it wakes up anything waiting on it. If it is totally full, it beeps * at the user. * UZI180 - This routine is called from the raw Hardware read routine, * either interrupt or polled, to process the input character. HFB */ int tty_inproc(uint8_t minor, unsigned char c) { unsigned char oc; int canon; uint8_t wr; struct tty *t = &ttydata[minor]; struct s_queue *q = &ttyinq[minor]; canon = t->termios.c_lflag & ICANON; if (t->termios.c_iflag & ISTRIP) c &= 0x7f; /* Strip off parity */ if (canon && !c) return 1; /* Simply quit if Null character */ #ifdef CONFIG_IDUMP if (c == 0x1a) /* ^Z */ idump(); /* (For debugging) */ #endif #ifdef CONFIG_MONITOR if (c == 0x01) /* ^A */ trap_monitor(); #endif if (c == '\r' && (t->termios.c_iflag & ICRNL)) c = '\n'; if (c == '\n' && (t->termios.c_iflag & INLCR)) c = '\r'; if (t->termios.c_lflag & ISIG) { if (c == t->termios.c_cc[VINTR]) { /* ^C */ wr = SIGINT; goto sigout; } else if (c == t->termios.c_cc[VQUIT]) { /* ^\ */ wr = SIGQUIT; sigout: sgrpsig(t->pgrp, wr); clrq(q); t->flag &= ~(TTYF_STOP | TTYF_DISCARD); return 1; } } if (c == t->termios.c_cc[VDISCARD]) { /* ^O */ t->flag ^= TTYF_DISCARD; return 1; } if (t->termios.c_iflag & IXON) { if (c == t->termios.c_cc[VSTOP]) { /* ^S */ t->flag |= TTYF_STOP; return 1; } if (c == t->termios.c_cc[VSTART]) { /* ^Q */ t->flag &= ~TTYF_STOP; wakeup(&t->flag); return 1; } } if (canon) { if (c == t->termios.c_cc[VERASE]) { wr = ECHOE; goto eraseout; } else if (c == t->termios.c_cc[VKILL]) { wr = ECHOK; goto eraseout; } } /* All modes come here */ if (c == '\n') { if ((t->termios.c_oflag & (OPOST | ONLCR)) == (OPOST | ONLCR)) tty_echo(minor, '\r'); } wr = insq(q, c); if (wr) tty_echo(minor, c); else tty_putc(minor, '\007'); /* Beep if no more room */ if (!canon || c == t->termios.c_cc[VEOL] || c == '\n' || c == t->termios.c_cc[VEOF]) wakeup(q); return wr; eraseout: while (uninsq(q, &oc)) { if (oc == '\n' || oc == t->termios.c_cc[VEOL]) { insq(q, oc); /* Don't erase past nl */ break; } if (t->termios.c_lflag & wr) tty_erase(minor); if (wr == ECHOE) break; } return 1; }
int tty_ioctl(uint8_t minor, uarg_t request, char *data) { /* Data in User Space */ struct tty *t; if (minor > NUM_DEV_TTY + 1) { udata.u_error = ENODEV; return -1; } t = &ttydata[minor]; if (t->flag & TTYF_DEAD) { udata.u_error = ENXIO; return -1; } jobcontrol_in(minor, t); switch (request) { case TCGETS: return uput(&t->termios, data, sizeof(struct termios)); break; case TCSETSF: clrq(&ttyinq[minor]); /* Fall through for now */ case TCSETSW: /* We don't have an output queue really so for now drop through */ case TCSETS: if (uget(data, &t->termios, sizeof(struct termios)) == -1) return -1; tty_setup(minor); break; case TIOCINQ: return uput(&ttyinq[minor].q_count, data, 2); case TIOCFLUSH: clrq(&ttyinq[minor]); break; case TIOCHANGUP: tty_hangup(minor); return 0; case TIOCOSTOP: t->flag |= TTYF_STOP; break; case TIOCOSTART: t->flag &= ~TTYF_STOP; break; case TIOCGWINSZ: return uput(&t->winsize, data, sizeof(struct winsize)); case TIOCSWINSZ: if (uget(&t->winsize, data, sizeof(struct winsize))) return -1; sgrpsig(t->pgrp, SIGWINCH); return 0; case TIOCGPGRP: return uputw(t->pgrp, data); #ifdef CONFIG_LEVEL_2 case TIOCSPGRP: /* Only applicable via controlling terminal */ if (minor != udata.u_ptab->p_tty) { udata.u_error = ENOTTY; return -1; } return tcsetpgrp(t, data); #endif default: udata.u_error = ENOTTY; return -1; } return 0; }