📄 term.c
字号:
/* vi: set sw=4 ts=4: * * term.c * * General purpose terminal handling library. * * Nick Patavalis (npat@inaccessnetworks.com) * * originaly by Pantelis Antoniou (panto@intranet.gr), Nick Patavalis * * Documentation can be found in the header file "term.h". * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * $Id$ */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <unistd.h>#ifdef __linux__#include <termio.h>#else#include <termios.h>#endif /* of __linux__ */#include "term.h"/***************************************************************************/static struct term_s { int init; int fd[MAX_TERMS]; struct termios origtermios[MAX_TERMS]; struct termios currtermios[MAX_TERMS]; struct termios nexttermios[MAX_TERMS];} term;/***************************************************************************/int term_errno;static const char * const term_err_str[] = { [TERM_EOK] = "No error", [TERM_ENOINIT] = "Framework is uninitialized", [TERM_EFULL] = "Framework is full", [TERM_ENOTFOUND] = "Filedes not in the framework", [TERM_EEXISTS] = "Filedes already in the framework", [TERM_EATEXIT] = "Cannot install atexit handler", [TERM_EISATTY] = "Filedes is not a tty", [TERM_EFLUSH] = "Cannot flush the device", [TERM_EGETATTR] = "Cannot get the device attributes", [TERM_ESETATTR] = "Cannot set the device attributes", [TERM_EBAUD] = "Invalid baud rate", [TERM_ESETOSPEED] = "Cannot set the output speed", [TERM_ESETISPEED] = "Cannot set the input speed", [TERM_EPARITY] = "Invalid parity mode", [TERM_EDATABITS] = "Invalid number of databits", [TERM_EFLOW] = "Invalid flowcontrol mode", [TERM_EDTRDOWN] = "Cannot lower DTR", [TERM_EDTRUP] = "Cannot raise DTR", [TERM_EDRAIN] = "Cannot drain the device", [TERM_EBREAK] = "Cannot send break sequence"};static char term_err_buff[1024];const char *term_strerror (int terrnum, int errnum){ const char *rval; switch(terrnum) { case TERM_EFLUSH: case TERM_EGETATTR: case TERM_ESETATTR: case TERM_ESETOSPEED: case TERM_ESETISPEED: case TERM_EDRAIN: case TERM_EBREAK: snprintf(term_err_buff, sizeof(term_err_buff), "%s: %s", term_err_str[terrnum], strerror(errnum)); rval = term_err_buff; break; case TERM_EOK: case TERM_ENOINIT: case TERM_EFULL: case TERM_ENOTFOUND: case TERM_EEXISTS: case TERM_EATEXIT: case TERM_EISATTY: case TERM_EBAUD: case TERM_EPARITY: case TERM_EDATABITS: case TERM_EFLOW: case TERM_EDTRDOWN: case TERM_EDTRUP: snprintf(term_err_buff, sizeof(term_err_buff), "%s", term_err_str[terrnum]); rval = term_err_buff; break; default: rval = NULL; break; } return rval;}intterm_perror (const char *prefix){ return fprintf(stderr, "%s %s\n", prefix, term_strerror(term_errno, errno));}/***************************************************************************/static intterm_find_next_free (void){ int rval, i; do { /* dummy */ if ( ! term.init ) { term_errno = TERM_ENOINIT; rval = -1; break; } for (i = 0; i < MAX_TERMS; i++) if ( term.fd[i] == -1 ) break; if ( i == MAX_TERMS ) { term_errno = TERM_EFULL; rval = -1; break; } rval = i; } while (0); return rval;}/***************************************************************************/static intterm_find (int fd){ int rval, i; do { /* dummy */ if ( ! term.init ) { term_errno = TERM_ENOINIT; rval = -1; break; } for (i = 0; i < MAX_TERMS; i++) if (term.fd[i] == fd) break; if ( i == MAX_TERMS ) { term_errno = TERM_ENOTFOUND; rval = -1; break; } rval = i; } while (0); return rval;}/***************************************************************************/static voidterm_exitfunc (void){ int r, i; do { /* dummy */ if ( ! term.init ) break; for (i = 0; i < MAX_TERMS; i++) { if (term.fd[i] == -1) continue; do { /* dummy */ r = tcflush(term.fd[i], TCIOFLUSH); if ( r < 0 ) break; r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); if ( r < 0 ) break; } while (0); if ( r < 0 ) { char *tname; tname = ttyname(term.fd[i]); if ( ! tname ) tname = "UNKNOWN"; fprintf(stderr, "%s: reset failed for dev %s: %s\n", __FUNCTION__, tname, strerror(errno)); } term.fd[i] = -1; } } while (0);}/***************************************************************************/intterm_lib_init (void){ int rval, r, i; rval = 0; do { /* dummy */ if ( term.init ) { /* reset all terms back to their original settings */ for (i = 0; i < MAX_TERMS; i++) { if (term.fd[i] == -1) continue; do { r = tcflush(term.fd[i], TCIOFLUSH); if ( r < 0 ) break; r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); if ( r < 0 ) break; } while (0); if ( r < 0 ) { char *tname; tname = ttyname(term.fd[i]); if ( ! tname ) tname = "UNKNOWN"; fprintf(stderr, "%s: reset failed for dev %s: %s\n", __FUNCTION__, tname, strerror(errno)); } term.fd[i] = -1; } } else { /* initialize term structure. */ for (i = 0; i < MAX_TERMS; i++) term.fd[i] = -1; if ( atexit(term_exitfunc) != 0 ) { term_errno = TERM_EATEXIT; rval = -1; break; } /* ok. term struct is now initialized. */ term.init = 1; } } while(0); return rval;}/***************************************************************************/intterm_add (int fd){ int rval, r, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i >= 0 ) { term_errno = TERM_EEXISTS; rval = -1; break; } if ( ! isatty(fd) ) { term_errno = TERM_EISATTY; rval = -1; break; } i = term_find_next_free(); if ( i < 0 ) { rval = -1; break; } r = tcgetattr(fd, &term.origtermios[i]); if ( r < 0 ) { term_errno = TERM_EGETATTR; rval = -1; break; } term.currtermios[i] = term.origtermios[i]; term.nexttermios[i] = term.origtermios[i]; term.fd[i] = fd; } while (0); return rval;}/***************************************************************************/intterm_remove(int fd){ int rval, r, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } do { /* dummy */ r = tcflush(term.fd[i], TCIOFLUSH); if ( r < 0 ) { term_errno = TERM_EFLUSH; rval = -1; break; } r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); if ( r < 0 ) { term_errno = TERM_ESETATTR; rval = -1; break; } } while (0); term.fd[i] = -1; } while (0); return rval;}/***************************************************************************/intterm_erase(int fd){ int rval, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } term.fd[i] = -1; } while (0); return rval;}/***************************************************************************/intterm_replace (int oldfd, int newfd){ int rval, r, i; rval = 0; do { /* dummy */ i = term_find(oldfd); if ( i < 0 ) { rval = -1; break; } r = tcsetattr(newfd, TCSAFLUSH, &term.currtermios[i]); if ( r < 0 ) { term_errno = TERM_ESETATTR; rval = -1; break; } term.fd[i] = newfd; } while (0); return rval;}/***************************************************************************/intterm_reset (int fd){ int rval, r, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } r = tcflush(term.fd[i], TCIOFLUSH); if ( r < 0 ) { term_errno = TERM_EFLUSH; rval = -1; break; } r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); if ( r < 0 ) { term_errno = TERM_ESETATTR; rval = -1; break; } term.currtermios[i] = term.origtermios[i]; term.nexttermios[i] = term.origtermios[i]; } while (0); return rval;}/***************************************************************************/intterm_revert (int fd){ int rval, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } term.nexttermios[i] = term.currtermios[i]; } while (0); return rval;}/***************************************************************************/intterm_refresh (int fd){ int rval, r, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } r = tcgetattr(fd, &term.currtermios[i]); if ( r < 0 ) { term_errno = TERM_EGETATTR; rval = -1; break; } } while (0); return rval;}/***************************************************************************/intterm_apply (int fd){ int rval, r, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } r = tcsetattr(term.fd[i], TCSAFLUSH, &term.nexttermios[i]); if ( r < 0 ) { term_errno = TERM_ESETATTR; rval = -1; break; } term.currtermios[i] = term.nexttermios[i]; } while (0); return rval;}/***************************************************************************/intterm_set_raw (int fd){ int rval, i; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } /* BSD raw mode */ cfmakeraw(&term.nexttermios[i]); /* one byte at a time, no timer */ term.nexttermios[i].c_cc[VMIN] = 1; term.nexttermios[i].c_cc[VTIME] = 0; } while (0); return rval;}/***************************************************************************/intterm_set_baudrate (int fd, int baudrate){ int rval, r, i; speed_t spd; struct termios tio; rval = 0; do { /* dummy */ i = term_find(fd); if ( i < 0 ) { rval = -1; break; } tio = term.nexttermios[i]; switch (baudrate) { case 0: spd = B0; break; case 50: spd = B50; break; case 75: spd = B75; break; case 110: spd = B110; break; case 134: spd = B134; break; case 150: spd = B150; break; case 200: spd = B200; break; case 300:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -