main() { int n; char buf[256]; setraw(0); for(;;) { n = read(0, buf, sizeof(buf)); if(n > 0) { if(buf[0] == '!') break; write(1, buf, n); } } setcooked(0); }
int unblock_itrm(void) { if (!ditrm) return -1; if (ditrm->in.ctl >= 0 && setraw(ditrm, 0)) return -1; ditrm->blocked = 0; send_init_sequence(ditrm->out.std, ditrm->altscreen); handle_itrm_stdin(ditrm); resume_mouse(ditrm->mouse_h); handle_terminal_resize(ditrm->in.ctl, resize_terminal); unblock_stdin(); return 0; }
bool kbdinput::start () { if (kbdfd < 0 || !isatty (kbdfd)) return false; /* Make sure we are in the foreground when getting the original * attributes. Many shells actually leave the terminal in cbreak * mode when all jobs are in the background. */ pid_t pgrp; if ((pgrp = tcgetpgrp (kbdfd)) > 0 && pgrp != getpgrp ()) kill (0, SIGTTOU); if (tcgetattr (kbdfd, &torig) < 0) { warn ("/dev/tty: %m\n"); return false; } traw = torig; traw.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK |ISTRIP|INLCR|IGNCR|ICRNL|IXON); // traw.c_oflag &= ~OPOST; traw.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); traw.c_cflag &= ~(CSIZE|PARENB); traw.c_cflag |= CS8; traw.c_cc[VMIN] = traw.c_cc[VTIME] = 0; if (!setraw ()) { setorig (); warn ("/dev/tty: %m\n"); return false; } tok = true; getclocknoise (dst); fdcb (kbdfd, selread, wrap (this, &kbdinput::readcb)); return true; }
void kbdinput::readcb () { struct _isigs { int ch; int sig; }; static const _isigs isig[] = { { VINTR, SIGINT }, { VQUIT, SIGQUIT }, { VSUSP, SIGTSTP }, #ifdef VDSUSP { VDSUSP, SIGTSTP }, #endif /* VDSUSP */ { -1, -1 } }; u_char c; size_t n = read (kbdfd, &c, 1); if (n <= 0) { setorig (); if (n == 0) fatal ("keyboard: EOF (with ICANON clear)\n"); else fatal ("keyboard: %m\n"); } dst->update (&c, 1); getclocknoise (dst); if (!lnext && c != _POSIX_VDISABLE) { #ifdef VLNEXT if (c == torig.c_cc[VLNEXT]) { lnext = true; return; } #endif /* VLNEXT */ for (int i = 0; isig[i].sig > 0; i++) if (c == torig.c_cc[isig[i].ch]) { setorig (); tcflush (kbdfd, TCIFLUSH); kill (0, isig[i].sig); gotsig = true; setraw (); getclocknoise (dst); vreprint (); gotsig = false; return; } if (iserase (c)) verase (); else if (iskill (c)) vkill (); else if (isreprint (c)) vreprint (); else goto normal; return; } normal: bool olnext = lnext; lnext = false; gotch (c, olnext); c = 0; }
/** Construct the struct itrm of this process, make ::ditrm point to it, * set up select() handlers, and send the initial interlink packet. * * The first five parameters are file descriptors that this function * saves in submembers of struct itrm, and for which this function may * set select() handlers. Please see the definitions of struct * itrm_in and struct itrm_out for further explanations. * * @param std_in itrm_in.std: read tty device (or pipe) * @param std_out itrm_out.std: write tty device (or pipe) * @param sock_in itrm_in.sock * - If master: == @a std_out (masterhood flag) * - If slave: read socket from master * @param sock_out itrm_out.sock * - If master: write pipe to same process * - If slave: write socket to master * @param ctl_in itrm_in.ctl: control tty device * * The remaining three parameters control the initial interlink packet. * * @param init_string A string to be passed to the master process. Need * not be null-terminated. If @a remote == 0, this is * a URI. Otherwise, this is a remote command. * @param init_len The length of init_string, in bytes. * @param remote = 0 if asking the master to start a new session * and display it via this process. Otherwise, * enum ::remote_session_flags. */ void handle_trm(int std_in, int std_out, int sock_in, int sock_out, int ctl_in, void *init_string, int init_len, int remote) { struct itrm *itrm; struct terminal_info info; struct interlink_event_size *size = &info.event.info.size; unsigned char *ts; memset(&info, 0, sizeof(info)); get_terminal_size(ctl_in, &size->width, &size->height); info.event.ev = EVENT_INIT; info.system_env = get_system_env(); info.length = init_len; if (remote) { info.session_info = remote; info.magic = INTERLINK_REMOTE_MAGIC; } else { info.session_info = get_cmd_opt_int("base-session"); info.magic = INTERLINK_NORMAL_MAGIC; } itrm = mem_calloc(1, sizeof(*itrm)); if (!itrm) return; itrm->in.queue.data = mem_calloc(1, ITRM_IN_QUEUE_SIZE); if (!itrm->in.queue.data) { mem_free(itrm); return; } ditrm = itrm; itrm->in.std = std_in; itrm->out.std = std_out; itrm->in.sock = sock_in; itrm->out.sock = sock_out; itrm->in.ctl = ctl_in; itrm->timer = TIMER_ID_UNDEF; itrm->remote = !!remote; /* If the master does not tell which charset it's using in * this terminal, assume it's some ISO 8859. Because that's * what older versions of ELinks did. */ itrm->title_codepage = get_cp_index("ISO-8859-1"); /* FIXME: Combination altscreen + xwin does not work as it should, * mouse clicks are reportedly partially ignored. */ if (info.system_env & (ENV_SCREEN | ENV_XWIN)) itrm->altscreen = 1; if (!remote) { if (ctl_in >= 0) setraw(itrm, 1); send_init_sequence(std_out, itrm->altscreen); handle_terminal_resize(ctl_in, resize_terminal); #ifdef CONFIG_MOUSE enable_mouse(); #endif handle_itrm_stdin(itrm); } else { /* elinks -remote may not have a valid stdin if not run from a tty (bug 938) */ if (std_in >= 0) handle_itrm_stdin(itrm); } if (sock_in != std_out) set_handlers(sock_in, (select_handler_T) in_sock, NULL, (select_handler_T) free_itrm, itrm); get_terminal_name(info.name); ts = get_cwd(); if (ts) { memcpy(info.cwd, ts, int_min(strlen(ts), MAX_CWD_LEN)); mem_free(ts); } itrm_queue_event(itrm, (char *) &info, TERMINAL_INFO_SIZE); itrm_queue_event(itrm, (char *) init_string, init_len); }