int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag) { struct termios *t; int towrite; uint8_t c; rawflag; flag; // shut up compiler /* Minor == 0 means that it is the controlling tty of the process */ if (!minor) minor = udata.u_ptab->p_tty; if (!udata.u_ptab->p_tty) udata.u_ptab->p_tty = minor; t = &ttydata[minor]; towrite = udata.u_count; while (udata.u_count-- != 0) { for (;;) { /* Wait on the ^S/^Q flag */ if (deadflag[minor]) { udata.u_error = ENXIO; return -1; } if (!stopflag[minor]) break; if (psleep_flags(&stopflag[minor], flag)) return -1; } if (!flshflag[minor]) { if (udata.u_sysio) c = *udata.u_base; else c = ugetc(udata.u_base); if (t->c_oflag & OPOST) { if (c == '\n' && (t->c_oflag & ONLCR)) tty_putc_wait(minor, '\r'); if (c == '\r' && (t->c_oflag & OCRNL)) c = '\n'; } tty_putc_wait(minor, c); } ++udata.u_base; } return towrite; }
int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag) { struct tty *t; usize_t written = 0; uint8_t c; used(rawflag); used(flag); t = &ttydata[minor]; while (udata.u_count-- != 0) { for (;;) { /* Wait on the ^S/^Q flag */ if (t->flag & TTYF_DEAD) { udata.u_error = ENXIO; return -1; } if (!(t->flag & TTYF_STOP)) break; if (psleep_flags_io(&t->flag, flag, &written)) return written; jobcontrol_out(minor, t); } if (!(t->flag & TTYF_DISCARD)) { if (udata.u_sysio) c = *udata.u_base; else c = ugetc(udata.u_base); if (t->termios.c_oflag & OPOST) { if (c == '\n' && (t->termios.c_oflag & ONLCR)) tty_putc_wait(minor, '\r'); else if (c == '\r' && (t->termios.c_oflag & OCRNL)) c = '\n'; } tty_putc_wait(minor, c); } ++udata.u_base; ++written; } return written; }
void tty_erase(uint8_t minor) { tty_putc_wait(minor, '\b'); tty_putc_wait(minor, ' '); tty_putc_wait(minor, '\b'); }
void tty_echo(uint8_t minor, unsigned char c) { if (ttydata[minor].c_lflag & ECHO) tty_putc_wait(minor, c); }
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; }