📄 tty.c
字号:
12674 /*==========================================================================*
12675 * out_process *
12676 *==========================================================================*/
12677 PUBLIC void out_process(tp, bstart, bpos, bend, icount, ocount)
12678 tty_t *tp;
12679 char *bstart, *bpos, *bend; /* start/pos/end of circular buffer */
12680 int *icount; /* # input chars / input chars used */
12681 int *ocount; /* max output chars / output chars used */
12682 {
12683 /* Perform output processing on a circular buffer. *icount is the number of
12684 * bytes to process, and the number of bytes actually processed on return.
12685 * *ocount is the space available on input and the space used on output.
12686 * (Naturally *icount < *ocount.) The column position is updated modulo
12687 * the TAB size, because we really only need it for tabs.
12688 */
12689
12690 int tablen;
12691 int ict = *icount;
12692 int oct = *ocount;
12693 int pos = tp->tty_position;
12694
12695 while (ict > 0) {
12696 switch (*bpos) {
12697 case '\7':
12698 break;
12699 case '\b':
12700 pos--;
12701 break;
12702 case '\r':
12703 pos = 0;
12704 break;
12705 case '\n':
12706 if ((tp->tty_termios.c_oflag & (OPOST|ONLCR))
12707 == (OPOST|ONLCR)) {
12708 /* Map LF to CR+LF if there is space. Note that the
12709 * next character in the buffer is overwritten, so
12710 * we stop at this point.
12711 */
12712 if (oct >= 2) {
12713 *bpos = '\r';
12714 if (++bpos == bend) bpos = bstart;
12715 *bpos = '\n';
12716 pos = 0;
12717 ict--;
12718 oct -= 2;
12719 }
12720 goto out_done; /* no space or buffer got changed */
12721 }
12722 break;
12723 case '\t':
12724 /* Best guess for the tab length. */
12725 tablen = TAB_SIZE - (pos & TAB_MASK);
12726
12727 if ((tp->tty_termios.c_oflag & (OPOST|XTABS))
12728 == (OPOST|XTABS)) {
12729 /* Tabs must be expanded. */
12730 if (oct >= tablen) {
12731 pos += tablen;
12732 ict--;
12733 oct -= tablen;
12734 do {
12735 *bpos = ' ';
12736 if (++bpos == bend) bpos = bstart;
12737 } while (--tablen != 0);
12738 }
12739 goto out_done;
12740 }
12741 /* Tabs are output directly. */
12742 pos += tablen;
12743 break;
12744 default:
12745 /* Assume any other character prints as one character. */
12746 pos++;
12747 }
12748 if (++bpos == bend) bpos = bstart;
12749 ict--;
12750 oct--;
12751 }
12752 out_done:
12753 tp->tty_position = pos & TAB_MASK;
12754
12755 *icount -= ict; /* [io]ct are the number of chars not used */
12756 *ocount -= oct; /* *[io]count are the number of chars that are used */
12757 }
12760 /*===========================================================================*
12761 * dev_ioctl *
12762 *===========================================================================*/
12763 PRIVATE void dev_ioctl(tp)
12764 tty_t *tp;
12765 {
12766 /* The ioctl's TCSETSW, TCSETSF and TCDRAIN wait for output to finish to make
12767 * sure that an attribute change doesn't affect the processing of current
12768 * output. Once output finishes the ioctl is executed as in do_ioctl().
12769 */
12770 phys_bytes user_phys;
12771
12772 if (tp->tty_outleft > 0) return; /* output not finished */
12773
12774 if (tp->tty_ioreq != TCDRAIN) {
12775 if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);
12776 user_phys = proc_vir2phys(proc_addr(tp->tty_ioproc), tp->tty_iovir);
12777 phys_copy(user_phys, vir2phys(&tp->tty_termios),
12778 (phys_bytes) sizeof(tp->tty_termios));
12779 setattr(tp);
12780 }
12781 tp->tty_ioreq = 0;
12782 tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, OK);
12783 }
12786 /*===========================================================================*
12787 * setattr *
12788 *===========================================================================*/
12789 PRIVATE void setattr(tp)
12790 tty_t *tp;
12791 {
12792 /* Apply the new line attributes (raw/canonical, line speed, etc.) */
12793 u16_t *inp;
12794 int count;
12795
12796 if (!(tp->tty_termios.c_lflag & ICANON)) {
12797 /* Raw mode; put a "line break" on all characters in the input queue.
12798 * It is undefined what happens to the input queue when ICANON is
12799 * switched off, a process should use TCSAFLUSH to flush the queue.
12800 * Keeping the queue to preserve typeahead is the Right Thing, however
12801 * when a process does use TCSANOW to switch to raw mode.
12802 */
12803 count = tp->tty_eotct = tp->tty_incount;
12804 inp = tp->tty_intail;
12805 while (count > 0) {
12806 *inp |= IN_EOT;
12807 if (++inp == bufend(tp->tty_inbuf)) inp = tp->tty_inbuf;
12808 --count;
12809 }
12810 }
12811
12812 /* Inspect MIN and TIME. */
12813 lock();
12814 settimer(tp, FALSE);
12815 unlock();
12816 if (tp->tty_termios.c_lflag & ICANON) {
12817 /* No MIN & TIME in canonical mode. */
12818 tp->tty_min = 1;
12819 } else {
12820 /* In raw mode MIN is the number of chars wanted, and TIME how long
12821 * to wait for them. With interesting exceptions if either is zero.
12822 */
12823 tp->tty_min = tp->tty_termios.c_cc[VMIN];
12824 if (tp->tty_min == 0 && tp->tty_termios.c_cc[VTIME] > 0)
12825 tp->tty_min = 1;
12826 }
12827
12828 if (!(tp->tty_termios.c_iflag & IXON)) {
12829 /* No start/stop output control, so don't leave output inhibited. */
12830 tp->tty_inhibited = RUNNING;
12831 tp->tty_events = 1;
12832 }
12833
12834 /* Setting the output speed to zero hangs up the phone. */
12835 if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);
12836
12837 /* Set new line speed, character size, etc at the device level. */
12838 (*tp->tty_ioctl)(tp);
12839 }
12842 /*===========================================================================*
12843 * tty_reply *
12844 *===========================================================================*/
12845 PUBLIC void tty_reply(code, replyee, proc_nr, status)
12846 int code; /* TASK_REPLY or REVIVE */
12847 int replyee; /* destination address for the reply */
12848 int proc_nr; /* to whom should the reply go? */
12849 int status; /* reply code */
12850 {
12851 /* Send a reply to a process that wanted to read or write data. */
12852
12853 message tty_mess;
12854
12855 tty_mess.m_type = code;
12856 tty_mess.REP_PROC_NR = proc_nr;
12857 tty_mess.REP_STATUS = status;
12858 if ((status = send(replyee, &tty_mess)) != OK)
12859 panic("tty_reply failed, status\n", status);
12860 }
12863 /*===========================================================================*
12864 * sigchar *
12865 *===========================================================================*/
12866 PUBLIC void sigchar(tp, sig)
12867 register tty_t *tp;
12868 int sig; /* SIGINT, SIGQUIT, SIGKILL or SIGHUP */
12869 {
12870 /* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard or SIGHUP from
12871 * a tty close, "stty 0", or a real RS-232 hangup. MM will send the signal to
12872 * the process group (INT, QUIT), all processes (KILL), or the session leader
12873 * (HUP).
12874 */
12875
12876 if (tp->tty_pgrp != 0) cause_sig(tp->tty_pgrp, sig);
12877
12878 if (!(tp->tty_termios.c_lflag & NOFLSH)) {
12879 tp->tty_incount = tp->tty_eotct = 0; /* kill earlier input */
12880 tp->tty_intail = tp->tty_inhead;
12881 (*tp->tty_ocancel)(tp); /* kill all output */
12882 tp->tty_inhibited = RUNNING;
12883 tp->tty_events = 1;
12884 }
12885 }
12888 /*==========================================================================*
12889 * tty_icancel *
12890 *==========================================================================*/
12891 PRIVATE void tty_icancel(tp)
12892 register tty_t *tp;
12893 {
12894 /* Discard all pending input, tty buffer or device. */
12895
12896 tp->tty_incount = tp->tty_eotct = 0;
12897 tp->tty_intail = tp->tty_inhead;
12898 (*tp->tty_icancel)(tp);
12899 }
12902 /*==========================================================================*
12903 * tty_init *
12904 *==========================================================================*/
12905 PRIVATE void tty_init(tp)
12906 tty_t *tp; /* TTY line to initialize. */
12907 {
12908 /* Initialize tty structure and call device initialization routines. */
12909
12910 tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
12911 tp->tty_min = 1;
12912 tp->tty_termios = termios_defaults;
12913 tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close =
12914 tty_devnop;
12915 if (tp < tty_addr(NR_CONS)) {
12916 scr_init(tp);
12917 } else
12918 if (tp < tty_addr(NR_CONS+NR_RS_LINES)) {
12919 rs_init(tp);
12920 } else {
12921 pty_init(tp);
12922 }
12923 }
12926 /*==========================================================================*
12927 * tty_wakeup *
12928 *==========================================================================*/
12929 PUBLIC void tty_wakeup(now)
12930 clock_t now; /* current time */
12931 {
12932 /* Wake up TTY when something interesting is happening on one of the terminal
12933 * lines, like a character arriving on an RS232 line, a key being typed, or
12934 * a timer on a line expiring by TIME.
12935 */
12936 tty_t *tp;
12937
12938 /* Scan the timerlist for expired timers and compute the next timeout time. */
12939 tty_timeout = TIME_NEVER;
12940 while ((tp = tty_timelist) != NULL) {
12941 if (tp->tty_time > now) {
12942 tty_timeout = tp->tty_time; /* this timer is next */
12943 break;
12944 }
12945 tp->tty_min = 0; /* force read to succeed */
12946 tp->tty_events = 1;
12947 tty_timelist = tp->tty_timenext;
12948 }
12949
12950 /* Let TTY know there is something afoot. */
12951 interrupt(TTY);
12952 }
12955 /*===========================================================================*
12956 * settimer *
12957 *===========================================================================*/
12958 PRIVATE void settimer(tp, on)
12959 tty_t *tp; /* line to set or unset a timer on */
12960 int on; /* set timer if true, otherwise unset */
12961 {
12962 /* Set or unset a TIME inspired timer. This function is interrupt sensitive
12963 * due to tty_wakeup(), so it must be called from within lock()/unlock().
12964 */
12965 tty_t **ptp;
12966
12967 /* Take tp out of the timerlist if present. */
12968 for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
12969 if (tp == *ptp) {
12970 *ptp = tp->tty_timenext; /* take tp out of the list */
12971 break;
12972 }
12973 }
12974 if (!on) return; /* unsetting it is enough */
12975
12976 /* Timeout occurs TIME deciseconds from now. */
12977 tp->tty_time = get_uptime() + tp->tty_termios.c_cc[VTIME] * (HZ/10);
12978
12979 /* Find a new place in the list. */
12980 for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
12981 if (tp->tty_time <= (*ptp)->tty_time) break;
12982 }
12983 tp->tty_timenext = *ptp;
12984 *ptp = tp;
12985 if (tp->tty_time < tty_timeout) tty_timeout = tp->tty_time;
12986 }
12989 /*==========================================================================*
12990 * tty_devnop *
12991 *==========================================================================*/
12992 PUBLIC void tty_devnop(tp)
12993 tty_t *tp;
12994 {
12995 /* Some functions need not be implemented at the device level. */
12996 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -