📄 pty.c
字号:
pty_t *pp;{/* Transfer bytes written to the output buffer to the PTY reader. */ int count; /* While there are things to do. */ for (;;) { int s; count = bufend(pp->obuf) - pp->otail; if (count > pp->ocount) count = pp->ocount; if (count > pp->rdleft) count = pp->rdleft; if (count == 0) break; /* Copy from the output buffer to the readers address space. */ if ((s = sys_vircopy(SELF, D, (vir_bytes)pp->otail, (vir_bytes) pp->rdproc, D, (vir_bytes) pp->rdvir, (phys_bytes) count)) != OK) { printf("pty tty%d: copy failed (error %d)\n", s); break; } /* Bookkeeping. */ pp->ocount -= count; if ((pp->otail += count) == bufend(pp->obuf)) pp->otail = pp->obuf; pp->rdvir += count; pp->rdcum += count; pp->rdleft -= count; }}/*===========================================================================* * pty_finish * *===========================================================================*/PRIVATE void pty_finish(pp)pty_t *pp;{/* Finish the read request of a PTY reader if there is at least one byte * transferred. */ if (pp->rdcum > 0) { if (pp->rdsendreply) { tty_reply(TASK_REPLY, pp->rdcaller, pp->rdproc, pp->rdcum); pp->rdleft = pp->rdcum = 0; } else notify(pp->rdcaller); }}/*===========================================================================* * pty_read * *===========================================================================*/PRIVATE int pty_read(tp, try)tty_t *tp;int try;{/* Offer bytes from the PTY writer for input on the TTY. (Do it one byte at * a time, 99% of the writes will be for one byte, so no sense in being smart.) */ pty_t *pp = tp->tty_priv; char c; if (pp->state & PTY_CLOSED) { if (try) return 1; if (tp->tty_inleft > 0) { tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc, tp->tty_incum); tp->tty_inleft = tp->tty_incum = 0; } return 1; } if (try) { if (pp->wrleft > 0) return 1; return 0; } while (pp->wrleft > 0) { int s; /* Transfer one character to 'c'. */ if ((s = sys_vircopy(pp->wrproc, D, (vir_bytes) pp->wrvir, SELF, D, (vir_bytes) &c, (phys_bytes) 1)) != OK) { printf("pty: copy failed (error %d)\n", s); break; } /* Input processing. */ if (in_process(tp, &c, 1) == 0) break; /* PTY writer bookkeeping. */ pp->wrvir++; pp->wrcum++; if (--pp->wrleft == 0) { if (pp->wrsendreply) { tty_reply(TASK_REPLY, pp->wrcaller, pp->wrproc, pp->wrcum); pp->wrcum = 0; } else notify(pp->wrcaller); } }}/*===========================================================================* * pty_close * *===========================================================================*/PRIVATE int pty_close(tp, try)tty_t *tp;int try;{/* The tty side has closed, so shut down the pty side. */ pty_t *pp = tp->tty_priv; if (!(pp->state & PTY_ACTIVE)) return; if (pp->rdleft > 0) { assert(!pp->rdsendreply); notify(pp->rdcaller); } if (pp->wrleft > 0) { assert(!pp->wrsendreply); notify(pp->wrcaller); } if (pp->state & PTY_CLOSED) pp->state = 0; else pp->state |= TTY_CLOSED;}/*===========================================================================* * pty_icancel * *===========================================================================*/PRIVATE int pty_icancel(tp, try)tty_t *tp;int try;{/* Discard waiting input. */ pty_t *pp = tp->tty_priv; if (pp->wrleft > 0) { assert(!pp->wrsendreply); pp->wrcum += pp->wrleft; pp->wrleft= 0; notify(pp->wrcaller); }}/*===========================================================================* * pty_ocancel * *===========================================================================*/PRIVATE int pty_ocancel(tp, try)tty_t *tp;int try;{/* Drain the output buffer. */ pty_t *pp = tp->tty_priv; pp->ocount = 0; pp->otail = pp->ohead;}/*===========================================================================* * pty_init * *===========================================================================*/PUBLIC void pty_init(tp)tty_t *tp;{ pty_t *pp; int line; /* Associate PTY and TTY structures. */ line = tp - &tty_table[NR_CONS + NR_RS_LINES]; pp = tp->tty_priv = &pty_table[line]; pp->tty = tp; pp->select_ops = 0; /* Set up output queue. */ pp->ohead = pp->otail = pp->obuf; /* Fill in TTY function hooks. */ tp->tty_devread = pty_read; tp->tty_devwrite = pty_write; tp->tty_echo = pty_echo; tp->tty_icancel = pty_icancel; tp->tty_ocancel = pty_ocancel; tp->tty_close = pty_close; tp->tty_select_ops = 0;}/*===========================================================================* * pty_status * *===========================================================================*/PUBLIC int pty_status(message *m_ptr){ int i, event_found; pty_t *pp; event_found = 0; for (i= 0, pp = pty_table; i<NR_PTYS; i++, pp++) { if ((((pp->state & TTY_CLOSED) && pp->rdleft > 0) || pp->rdcum > 0) && pp->rdcaller == m_ptr->m_source) { m_ptr->m_type = DEV_REVIVE; m_ptr->REP_PROC_NR = pp->rdproc; m_ptr->REP_STATUS = pp->rdcum; pp->rdleft = pp->rdcum = 0; event_found = 1; break; } if ((((pp->state & TTY_CLOSED) && pp->wrleft > 0) || pp->wrcum > 0) && pp->wrcaller == m_ptr->m_source) { m_ptr->m_type = DEV_REVIVE; m_ptr->REP_PROC_NR = pp->wrproc; if (pp->wrcum == 0) m_ptr->REP_STATUS = EIO; else m_ptr->REP_STATUS = pp->wrcum; pp->wrleft = pp->wrcum = 0; event_found = 1; break; } if (pp->select_ready_ops && pp->select_proc == m_ptr->m_source) { m_ptr->m_type = DEV_IO_READY; m_ptr->DEV_MINOR = PTYPX_MINOR + i; m_ptr->DEV_SEL_OPS = pp->select_ready_ops; pp->select_ready_ops = 0; event_found = 1; break; } } return event_found;}/*===========================================================================* * select_try_pty * *===========================================================================*/PRIVATE int select_try_pty(tty_t *tp, int ops){ pty_t *pp = tp->tty_priv; int r = 0; if (ops & SEL_WR) { /* Write won't block on error. */ if (pp->state & TTY_CLOSED) r |= SEL_WR; else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR; else r |= SEL_WR; } if (ops & SEL_RD) { /* Read won't block on error. */ if (pp->state & TTY_CLOSED) r |= SEL_RD; else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD; else if (pp->ocount > 0) r |= SEL_RD; /* Actual data. */ } return r;}/*===========================================================================* * select_retry_pty * *===========================================================================*/PUBLIC void select_retry_pty(tty_t *tp){ pty_t *pp = tp->tty_priv; int r; /* See if the pty side of a pty is ready to return a select. */ if (pp->select_ops && (r=select_try_pty(tp, pp->select_ops))) { pp->select_ops &= ~r; pp->select_ready_ops |= r; notify(pp->select_proc); }}/*===========================================================================* * pty_select * *===========================================================================*/PRIVATE int pty_select(tty_t *tp, message *m){ pty_t *pp = tp->tty_priv; int ops, ready_ops = 0, watch; ops = m->PROC_NR & (SEL_RD|SEL_WR|SEL_ERR); watch = (m->PROC_NR & SEL_NOTIFY) ? 1 : 0; ready_ops = select_try_pty(tp, ops); if (!ready_ops && ops && watch) { pp->select_ops |= ops; pp->select_proc = m->m_source; } return ready_ops;}#endif /* NR_PTYS > 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -