📄 tty.c
字号:
/* $NetBSD: tty.c,v 1.16 2002/03/18 16:01:01 christos Exp $ *//*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "config.h"#if !defined(lint) && !defined(SCCSID)#if 0static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";#else__RCSID("$NetBSD: tty.c,v 1.16 2002/03/18 16:01:01 christos Exp $");#endif#endif /* not lint && not SCCSID *//* * tty.c: tty interface stuff */#include "tty.h"#include "el.h"typedef struct ttymodes_t { const char *m_name; u_int m_value; int m_type;} ttymodes_t;typedef struct ttymap_t { int nch, och; /* Internal and termio rep of chars */ el_action_t bind[3]; /* emacs, vi, and vi-cmd */} ttymap_t;private const ttyperm_t ttyperm = { { {"iflag:", ICRNL, (INLCR | IGNCR)}, {"oflag:", (OPOST | ONLCR), ONLRET}, {"cflag:", 0, 0}, {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN), (NOFLSH | ECHONL | EXTPROC | FLUSHO)}, {"chars:", 0, 0}, }, { {"iflag:", (INLCR | ICRNL), IGNCR}, {"oflag:", (OPOST | ONLCR), ONLRET}, {"cflag:", 0, 0}, {"lflag:", ISIG, (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)}, {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) | C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) | C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0} }, { {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL}, {"oflag:", 0, 0}, {"cflag:", 0, 0}, {"lflag:", 0, ISIG | IEXTEN}, {"chars:", 0, 0}, }};private const ttychar_t ttychar = { { CINTR, CQUIT, CERASE, CKILL, CEOF, CEOL, CEOL2, CSWTCH, CDSWTCH, CERASE2, CSTART, CSTOP, CWERASE, CSUSP, CDSUSP, CREPRINT, CDISCARD, CLNEXT, CSTATUS, CPAGE, CPGOFF, CKILL2, CBRK, CMIN, CTIME }, { CINTR, CQUIT, CERASE, CKILL, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, CERASE2, CSTART, CSTOP, _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE, CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};private const ttymap_t tty_map[] = {#ifdef VERASE {C_ERASE, VERASE, {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},#endif /* VERASE */#ifdef VERASE2 {C_ERASE2, VERASE2, {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},#endif /* VERASE2 */#ifdef VKILL {C_KILL, VKILL, {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},#endif /* VKILL */#ifdef VKILL2 {C_KILL2, VKILL2, {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},#endif /* VKILL2 */#ifdef VEOF {C_EOF, VEOF, {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},#endif /* VEOF */#ifdef VWERASE {C_WERASE, VWERASE, {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},#endif /* VWERASE */#ifdef VREPRINT {C_REPRINT, VREPRINT, {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},#endif /* VREPRINT */#ifdef VLNEXT {C_LNEXT, VLNEXT, {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},#endif /* VLNEXT */ {-1, -1, {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}};private const ttymodes_t ttymodes[] = {#ifdef IGNBRK {"ignbrk", IGNBRK, MD_INP},#endif /* IGNBRK */#ifdef BRKINT {"brkint", BRKINT, MD_INP},#endif /* BRKINT */#ifdef IGNPAR {"ignpar", IGNPAR, MD_INP},#endif /* IGNPAR */#ifdef PARMRK {"parmrk", PARMRK, MD_INP},#endif /* PARMRK */#ifdef INPCK {"inpck", INPCK, MD_INP},#endif /* INPCK */#ifdef ISTRIP {"istrip", ISTRIP, MD_INP},#endif /* ISTRIP */#ifdef INLCR {"inlcr", INLCR, MD_INP},#endif /* INLCR */#ifdef IGNCR {"igncr", IGNCR, MD_INP},#endif /* IGNCR */#ifdef ICRNL {"icrnl", ICRNL, MD_INP},#endif /* ICRNL */#ifdef IUCLC {"iuclc", IUCLC, MD_INP},#endif /* IUCLC */#ifdef IXON {"ixon", IXON, MD_INP},#endif /* IXON */#ifdef IXANY {"ixany", IXANY, MD_INP},#endif /* IXANY */#ifdef IXOFF {"ixoff", IXOFF, MD_INP},#endif /* IXOFF */#ifdef IMAXBEL {"imaxbel", IMAXBEL, MD_INP},#endif /* IMAXBEL */#ifdef OPOST {"opost", OPOST, MD_OUT},#endif /* OPOST */#ifdef OLCUC {"olcuc", OLCUC, MD_OUT},#endif /* OLCUC */#ifdef ONLCR {"onlcr", ONLCR, MD_OUT},#endif /* ONLCR */#ifdef OCRNL {"ocrnl", OCRNL, MD_OUT},#endif /* OCRNL */#ifdef ONOCR {"onocr", ONOCR, MD_OUT},#endif /* ONOCR */#ifdef ONOEOT {"onoeot", ONOEOT, MD_OUT},#endif /* ONOEOT */#ifdef ONLRET {"onlret", ONLRET, MD_OUT},#endif /* ONLRET */#ifdef OFILL {"ofill", OFILL, MD_OUT},#endif /* OFILL */#ifdef OFDEL {"ofdel", OFDEL, MD_OUT},#endif /* OFDEL */#ifdef NLDLY {"nldly", NLDLY, MD_OUT},#endif /* NLDLY */#ifdef CRDLY {"crdly", CRDLY, MD_OUT},#endif /* CRDLY */#ifdef TABDLY {"tabdly", TABDLY, MD_OUT},#endif /* TABDLY */#ifdef XTABS {"xtabs", XTABS, MD_OUT},#endif /* XTABS */#ifdef BSDLY {"bsdly", BSDLY, MD_OUT},#endif /* BSDLY */#ifdef VTDLY {"vtdly", VTDLY, MD_OUT},#endif /* VTDLY */#ifdef FFDLY {"ffdly", FFDLY, MD_OUT},#endif /* FFDLY */#ifdef PAGEOUT {"pageout", PAGEOUT, MD_OUT},#endif /* PAGEOUT */#ifdef WRAP {"wrap", WRAP, MD_OUT},#endif /* WRAP */#ifdef CIGNORE {"cignore", CIGNORE, MD_CTL},#endif /* CBAUD */#ifdef CBAUD {"cbaud", CBAUD, MD_CTL},#endif /* CBAUD */#ifdef CSTOPB {"cstopb", CSTOPB, MD_CTL},#endif /* CSTOPB */#ifdef CREAD {"cread", CREAD, MD_CTL},#endif /* CREAD */#ifdef PARENB {"parenb", PARENB, MD_CTL},#endif /* PARENB */#ifdef PARODD {"parodd", PARODD, MD_CTL},#endif /* PARODD */#ifdef HUPCL {"hupcl", HUPCL, MD_CTL},#endif /* HUPCL */#ifdef CLOCAL {"clocal", CLOCAL, MD_CTL},#endif /* CLOCAL */#ifdef LOBLK {"loblk", LOBLK, MD_CTL},#endif /* LOBLK */#ifdef CIBAUD {"cibaud", CIBAUD, MD_CTL},#endif /* CIBAUD */#ifdef CRTSCTS#ifdef CCTS_OFLOW {"ccts_oflow", CCTS_OFLOW, MD_CTL},#else {"crtscts", CRTSCTS, MD_CTL},#endif /* CCTS_OFLOW */#endif /* CRTSCTS */#ifdef CRTS_IFLOW {"crts_iflow", CRTS_IFLOW, MD_CTL},#endif /* CRTS_IFLOW */#ifdef CDTRCTS {"cdtrcts", CDTRCTS, MD_CTL},#endif /* CDTRCTS */#ifdef MDMBUF {"mdmbuf", MDMBUF, MD_CTL},#endif /* MDMBUF */#ifdef RCV1EN {"rcv1en", RCV1EN, MD_CTL},#endif /* RCV1EN */#ifdef XMT1EN {"xmt1en", XMT1EN, MD_CTL},#endif /* XMT1EN */#ifdef ISIG {"isig", ISIG, MD_LIN},#endif /* ISIG */#ifdef ICANON {"icanon", ICANON, MD_LIN},#endif /* ICANON */#ifdef XCASE {"xcase", XCASE, MD_LIN},#endif /* XCASE */#ifdef ECHO {"echo", ECHO, MD_LIN},#endif /* ECHO */#ifdef ECHOE {"echoe", ECHOE, MD_LIN},#endif /* ECHOE */#ifdef ECHOK {"echok", ECHOK, MD_LIN},#endif /* ECHOK */#ifdef ECHONL {"echonl", ECHONL, MD_LIN},#endif /* ECHONL */#ifdef NOFLSH {"noflsh", NOFLSH, MD_LIN},#endif /* NOFLSH */#ifdef TOSTOP {"tostop", TOSTOP, MD_LIN},#endif /* TOSTOP */#ifdef ECHOCTL {"echoctl", ECHOCTL, MD_LIN},#endif /* ECHOCTL */#ifdef ECHOPRT {"echoprt", ECHOPRT, MD_LIN},#endif /* ECHOPRT */#ifdef ECHOKE {"echoke", ECHOKE, MD_LIN},#endif /* ECHOKE */#ifdef DEFECHO {"defecho", DEFECHO, MD_LIN},#endif /* DEFECHO */#ifdef FLUSHO {"flusho", FLUSHO, MD_LIN},#endif /* FLUSHO */#ifdef PENDIN {"pendin", PENDIN, MD_LIN},#endif /* PENDIN */#ifdef IEXTEN {"iexten", IEXTEN, MD_LIN},#endif /* IEXTEN */#ifdef NOKERNINFO {"nokerninfo", NOKERNINFO, MD_LIN},#endif /* NOKERNINFO */#ifdef ALTWERASE {"altwerase", ALTWERASE, MD_LIN},#endif /* ALTWERASE */#ifdef EXTPROC {"extproc", EXTPROC, MD_LIN},#endif /* EXTPROC */#if defined(VINTR) {"intr", C_SH(C_INTR), MD_CHAR},#endif /* VINTR */#if defined(VQUIT) {"quit", C_SH(C_QUIT), MD_CHAR},#endif /* VQUIT */#if defined(VERASE) {"erase", C_SH(C_ERASE), MD_CHAR},#endif /* VERASE */#if defined(VKILL) {"kill", C_SH(C_KILL), MD_CHAR},#endif /* VKILL */#if defined(VEOF) {"eof", C_SH(C_EOF), MD_CHAR},#endif /* VEOF */#if defined(VEOL) {"eol", C_SH(C_EOL), MD_CHAR},#endif /* VEOL */#if defined(VEOL2) {"eol2", C_SH(C_EOL2), MD_CHAR},#endif /* VEOL2 */#if defined(VSWTCH) {"swtch", C_SH(C_SWTCH), MD_CHAR},#endif /* VSWTCH */#if defined(VDSWTCH) {"dswtch", C_SH(C_DSWTCH), MD_CHAR},#endif /* VDSWTCH */#if defined(VERASE2) {"erase2", C_SH(C_ERASE2), MD_CHAR},#endif /* VERASE2 */#if defined(VSTART) {"start", C_SH(C_START), MD_CHAR},#endif /* VSTART */#if defined(VSTOP) {"stop", C_SH(C_STOP), MD_CHAR},#endif /* VSTOP */#if defined(VWERASE) {"werase", C_SH(C_WERASE), MD_CHAR},#endif /* VWERASE */#if defined(VSUSP) {"susp", C_SH(C_SUSP), MD_CHAR},#endif /* VSUSP */#if defined(VDSUSP) {"dsusp", C_SH(C_DSUSP), MD_CHAR},#endif /* VDSUSP */#if defined(VREPRINT) {"reprint", C_SH(C_REPRINT), MD_CHAR},#endif /* VREPRINT */#if defined(VDISCARD) {"discard", C_SH(C_DISCARD), MD_CHAR},#endif /* VDISCARD */#if defined(VLNEXT) {"lnext", C_SH(C_LNEXT), MD_CHAR},#endif /* VLNEXT */#if defined(VSTATUS) {"status", C_SH(C_STATUS), MD_CHAR},#endif /* VSTATUS */#if defined(VPAGE) {"page", C_SH(C_PAGE), MD_CHAR},#endif /* VPAGE */#if defined(VPGOFF) {"pgoff", C_SH(C_PGOFF), MD_CHAR},#endif /* VPGOFF */#if defined(VKILL2) {"kill2", C_SH(C_KILL2), MD_CHAR},#endif /* VKILL2 */#if defined(VBRK) {"brk", C_SH(C_BRK), MD_CHAR},#endif /* VBRK */#if defined(VMIN) {"min", C_SH(C_MIN), MD_CHAR},#endif /* VMIN */#if defined(VTIME) {"time", C_SH(C_TIME), MD_CHAR},#endif /* VTIME */ {NULL, 0, -1},};#define tty_getty(el, td) tcgetattr((el)->el_infd, (td))#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)#define tty__cooked_mode(td) ((td)->c_lflag & ICANON)private void tty__getchar(struct termios *, unsigned char *);private void tty__setchar(struct termios *, unsigned char *);private speed_t tty__getspeed(struct termios *);private int tty_setup(EditLine *);#define t_qu t_ts/* tty_setup(): * Get the tty parameters and initialize the editing state */private inttty_setup(EditLine *el){ int rst = 1; if (el->el_flags & EDIT_DISABLED) return (0); if (tty_getty(el, &el->el_tty.t_ed) == -1) {#ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "tty_setup: tty_getty: %s\n", strerror(errno));#endif /* DEBUG_TTY */ return (-1); } el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed; el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask; el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask; el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask; el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask; el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask; el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask; el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask; el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask; /* * Reset the tty chars to reasonable defaults * If they are disabled, then enable them. */ if (rst) { if (tty__cooked_mode(&el->el_tty.t_ts)) { tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); /* * Don't affect CMIN and CTIME for the editor mode */ for (rst = 0; rst < C_NCC - 2; rst++) if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable && el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable) el->el_tty.t_c[ED_IO][rst] = el->el_tty.t_c[TS_IO][rst]; for (rst = 0; rst < C_NCC; rst++) if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable) el->el_tty.t_c[EX_IO][rst] = el->el_tty.t_c[TS_IO][rst]; } tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); if (tty_setty(el, &el->el_tty.t_ex) == -1) {#ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n", strerror(errno));#endif /* DEBUG_TTY */ return (-1); } } else tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask; el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask; el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask; el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask; el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask; el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask; el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask; tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); tty_bind_char(el, 1); return (0);}protected inttty_init(EditLine *el){ el->el_tty.t_mode = EX_IO; el->el_tty.t_vdisable = _POSIX_VDISABLE; (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); return (tty_setup(el));}/* tty_end(): * Restore the tty to its original settings */protected void/*ARGSUSED*/tty_end(EditLine *el){ /* XXX: Maybe reset to an initial state? */}/* tty__getspeed(): * Get the tty speed */private speed_ttty__getspeed(struct termios *td){ speed_t spd; if ((spd = cfgetispeed(td)) == 0) spd = cfgetospeed(td); return (spd);}/* tty__getchar():
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -