#include #include #include #include #include "cbi.h" /* All the apparently redundant sigemptyset() calls are because sigsetops(3) says that it (or sigfillset()) must be called before anything else is done with a sigset_t...including, by implication, fetching one via calls like sigprocmask() or sigaction(). */ static int ifd; static int ttyp; static struct termios tio; static struct termios tio2; static unsigned int initflags; static struct sigaction tstpsa; static struct sigaction oldtstp; static void cbi_tstp(int sig __attribute__((__unused__))) { sigset_t m; sigaction(SIGTSTP,&oldtstp,0); tcgetattr(ifd,&tio); kill(getpid(),SIGTSTP); sigemptyset(&m); sigprocmask(SIG_BLOCK,0,&m); sigdelset(&m,SIGTSTP); sigsuspend(&m); tcsetattr(ifd,TCSADRAIN|TCSASOFT,&tio); sigaction(SIGTSTP,&tstpsa,&oldtstp); } void cbi_init(int fd, unsigned int flags) { ifd = fd; initflags = flags; ttyp = (tcgetattr(ifd,&tio) == 0); if (ttyp) { tio2 = tio; tio2.c_lflag &= ~(ICANON|ECHO|ECHOKE|ECHOE|ECHONL); tio2.c_cc[VMIN] = 1; tio2.c_cc[VTIME] = 0; tcsetattr(ifd,TCSADRAIN|TCSASOFT,&tio2); if (! (initflags & CBI_NO_TSTP)) { tstpsa.sa_handler = cbi_tstp; sigemptyset(&tstpsa.sa_mask); tstpsa.sa_flags = 0; sigemptyset(&oldtstp.sa_mask); sigaction(SIGTSTP,&tstpsa,&oldtstp); if (oldtstp.sa_handler == SIG_IGN) { sigaction(SIGTSTP,&oldtstp,0); initflags |= CBI_NO_TSTP; } } } } int cbi_getc(void) { unsigned char c; int n; n = read(ifd,&c,1); return((n<=0)?EOF:c); } void cbi_end(void) { sigset_t m1; sigset_t m2; sigemptyset(&m1); sigemptyset(&m2); sigaddset(&m2,SIGTSTP); sigprocmask(SIG_BLOCK,&m2,&m1); if (ttyp) tcsetattr(ifd,TCSADRAIN|TCSASOFT,&tio); if (! (initflags & CBI_NO_TSTP)) sigaction(SIGTSTP,&oldtstp,0); sigprocmask(SIG_SETMASK,&m1,0); }