void tty_cooked(register int fd) { register Edit_t *ep = (Edit_t*)(shgd->ed_context); ep->e_keytrap = 0; if(ep->e_raw==0) return; if(fd < 0) fd = ep->e_savefd; #ifdef L_MASK /* restore flags */ if(l_changed&L_MASK) ioctl(fd,TIOCLSET,&l_mask); if(l_changed&T_CHARS) /* restore alternate break character */ ioctl(fd,TIOCSETC,&l_ttychars); if(l_changed&L_CHARS) /* restore alternate break character */ ioctl(fd,TIOCSLTC,&l_chars); l_changed = 0; #endif /* L_MASK */ /*** don't do tty_set unless ttyparm has valid data ***/ if(tty_set(fd, TCSANOW, &ttyparm) == SYSERR) return; ep->e_raw = 0; return; }
static SIGRETTYPE ctl_c(int sig) { tty_reset(tty_fd); sys_sigset(sig, orig_ctl_c); /* Set ctl_c break handler to original */ sys_sigrelease(sig); /* Allow 'sig' to come through */ kill(getpid(), sig); /* Send ourselves the signal */ sys_sigblock(sig); /* Reset to old mask */ sys_sigset(sig, ctl_c); /* Reset signal handler */ tty_set(tty_fd); }
static SIGRETTYPE suspend(int sig) { tty_reset(tty_fd); sys_sigset(sig, SIG_DFL); /* Set signal handler to default */ sys_sigrelease(sig); /* Allow 'sig' to come through */ kill(getpid(), sig); /* Send ourselves the signal */ sys_sigblock(sig); /* Reset to old mask */ sys_sigset(sig, suspend); /* Reset signal handler */ tty_set(tty_fd); }
/* ** funkey_meta(test_list, status, ch) ** ** Test meta key (km) (smm) (rmm) */ static void funkey_meta( TestList * t, int *state, int *ch) { if (has_meta_key) { int i, j, k, len; char outbuf[256]; put_crlf(); if (char_mask != ALLOW_PARITY) { if (tty_meta_prep()) { ptext("\nHit any key to continue > "); (void) wait_here(); put_crlf(); } } ptext("Begin meta key test. (km) (smm) (rmm) Hit any key"); ptext(" with the meta key. The character will be"); ptext(" displayed in hex. If the meta key is working"); ptext(" then the most significant bit will be set. Type"); ptextln(" 'end' to exit."); tty_raw(1, ALLOW_PARITY); tc_putp(meta_on); for (i = j = k = len = 0; i != 'e' || j != 'n' || k != 'd';) { i = j; j = k; k = getchp(ALLOW_PARITY); if (k == EOF) { break; } if ((len += 3) >= columns) { put_crlf(); len = 3; } sprintf(outbuf, "%02X ", k); put_str(outbuf); k &= STRIP_PARITY; } tc_putp(meta_off); put_crlf(); tty_set(); put_crlf(); } else { ptext("(km) Has-meta-key is not set. "); } generic_done_message(t, state, ch); }
/**** start of autodetect code ***************************/ int is_it_is_it_huh(int port) { int j; tty_clear(port, 1, 0); ioctl(port, TIOCMGET, &j); if ((j & TIOCM_CTS) || (j & TIOCM_DSR)) return 0; tty_set(port, 1, 0); ioctl(port, TIOCMGET, &j); if ((!(j & TIOCM_CTS)) || (j & TIOCM_DSR)) return 0; return 1; }
int tty_init(int fd, unsigned int baudrate) { /* FIXME: handle speed */ if (tcgetattr(fd, &tty_rmode) < 0) return -1; tty_smode = tty_rmode; /* Default characteristics for all usage including termcap output. */ tty_smode.c_iflag &= ~ISTRIP; tty_smode.c_iflag |= ICRNL; /* cr -> nl on input */ tty_smode.c_lflag &= ~ICANON; tty_smode.c_oflag |= OPOST; /* nl -> cr-nl .. */ /* Must get these really right or funny effects can occur. */ tty_smode.c_cc[VMIN] = 1; tty_smode.c_cc[VTIME] = 0; #ifdef VDSUSP tty_smode.c_cc[VDSUSP] = 0; #endif tty_smode.c_cflag &= ~(CSIZE | PARENB); /* clear char-size,diable parity */ tty_smode.c_cflag |= CS8; /* 8-bit */ tty_smode.c_lflag &= ~ECHO; /* no echo */ if (tty_set(fd) < 0) { tty_fd = -1; tty_reset(fd); return -1; } tty_fd = fd; sys_sigset(SIGTSTP, suspend); sys_sigset(SIGTTIN, suspend); sys_sigset(SIGTTOU, suspend); orig_ctl_c = sys_sigset(SIGINT, ctl_c); return 0; }
/* ** subtest_xenl(test_list, status, ch) ** ** (xenl) eat newline glitch */ static void subtest_xenl( struct test_list *t, int *state, int *ch) { int i, j, k; if (over_strike) { /* test (xenl) on overstrike terminals */ if (!can_go_home || !can_clear_screen) { ptextln("(xenl) Newline-glitch not tested, can't home cursor and clear."); generic_done_message(t, state, ch); return; } put_clear(); /* this test must be done in raw mode. Otherwise UNIX will translate CR to CRLF. */ if (stty_query(TTY_OUT_TRANS)) tty_raw(1, char_mask); ptext("\nreset (xenl). Does "); i = char_count; put_str("not ignore CR, does "); k = char_count; put_str("not ignore LF"); go_home(); for (j = 0; j < columns; j++) put_this(' '); put_cr(); for (j = 0; j < i; j++) putchp(' '); put_str("@@@\n@@"); go_home(); for (j = 0; j < columns; j++) put_this(' '); put_lf(); for (j = 0; j < k; j++) putchp(' '); put_str("@@@\r@@"); tty_set(); go_home(); put_newlines(4); sprintf(temp, "(xenl) Newline-glitch is %s in the data base", eat_newline_glitch ? "true" : "false"); ptextln(temp); } else { /* test (xenl) when (os) is reset */ if (!can_go_home) { ptextln("(xenl) Newline-glitch not tested, can't home cursor"); generic_done_message(t, state, ch); return; } /* (xenl) test */ put_clear(); /* this test must be done in raw mode. Otherwise UNIX will translate CR to CRLF. */ if (stty_query(TTY_OUT_TRANS)) tty_raw(1, char_mask); for (j = 0; j < columns; j++) put_this(' '); put_cr(); ptext("(xenl) should be set. Does not ignore CR"); go_home(); put_crlf(); for (j = 0; j < columns; j++) put_this(' '); put_lf(); /* test (cud1) */ ptext("(xenl) should be set. Ignores (cud1)"); go_home(); put_newlines(3); if (scroll_forward && cursor_down && strcmp(scroll_forward, cursor_down)) { for (j = 0; j < columns; j++) put_this(' '); put_ind(); /* test (ind) */ ptext("(xenl) should be set. Ignores (ind)"); go_home(); put_newlines(5); } tty_set(); ptextln("If you don't see text above telling you to set it, (xenl) should be false"); sprintf(temp, "(xenl) Newline-glitch is %s in the data base", eat_newline_glitch ? "true" : "false"); ptextln(temp); } generic_done_message(t, state, ch); }
/* ** curses_setup(exec_name) ** ** Startup ncurses */ void curses_setup( char *exec_name) { int status; static TERMTYPE term; char tty_filename[2048]; tty_init(); /** See if the terminal is in the terminfo data base. This call has two useful benefits, 1) it returns the filename of the terminfo entry, and 2) it searches only terminfo's. This allows us to abort before ncurses starts scanning the termcap file. **/ if ((status = _nc_read_entry(tty_basename, tty_filename, &term)) == 0) { const TERMTYPE *fallback = _nc_fallback(tty_basename); if (fallback) { term = *fallback; sprintf(tty_filename, "(fallback)%s", tty_basename); status = 1; } else { fprintf(stderr, "Terminal not found: TERM=%s\n", tty_basename); show_usage(exec_name); exit(1); } } if (status == -1) { fprintf(stderr, "Terminfo database is inaccessible\n"); exit(1); } /** This call will load the terminfo data base and set the cur-term variable. Only terminals that actually exist will get here so its OK to ignore errors. This is a good thing since ncurses does not permit (os) or (gn) to be set. **/ setupterm(tty_basename, 1, &status); /** Get the current terminal definitions. This must be done before getting the baudrate. **/ _nc_get_curterm(&cur_term->Nttyb); tty_baud_rate = baudrate(); tty_cps = (tty_baud_rate << 1) / tty_frame_size; /* set up the defaults */ replace_mode = TRUE; scan_mode = 0; char_count = 0; select_delay_type = debug_level = 0; char_mask = (meta_on && meta_on[0] == '\0') ? ALLOW_PARITY : STRIP_PARITY; /* Don't change the XON/XOFF modes yet. */ select_xon_xoff = initial_stty_query(TTY_XON_XOFF) ? 1 : needs_xon_xoff; fflush(stdout); /* flush any output */ tty_set(); go_home(); /* set can_go_home */ put_clear(); /* set can_clear_screen */ if (send_reset_init) { reset_init(); } /* I assume that the reset and init strings may not have the correct pads. (Because that part of the test comes much later.) Because of this, I allow the terminal some time to catch up. */ fflush(stdout); /* waste some time */ sleep(1); /* waste more time */ charset_can_test(); can_test("lines cols cr nxon rf if iprog rmp smcup rmcup", FLAG_CAN_TEST); edit_init(); /* initialize the edit data base */ if (send_reset_init && enter_ca_mode) { tc_putp(enter_ca_mode); put_clear(); /* just in case we switched pages */ } put_crlf(); ptext("Using terminfo from: "); ptextln(tty_filename); put_crlf(); if (tty_can_sync == SYNC_NEEDED) { verify_time(); } display_basic(); }
/* ** keys_tested(first-time, show-help, hex-output) ** ** Display a list of the keys not tested. */ static void keys_tested( int first_time, int show_help, int hex_output) { int i, l; char outbuf[256]; alloc_strings(); put_clear(); tty_set(); flush_input(); if (got_labels) { putln("Function key labels:"); for (i = 0; i < key_count; ++i) { if (fk_label[i]) { sprintf(outbuf, "%s %s", fk_name[i] ? fk_name[i] : "??", fk_label[i]); put_columns(outbuf, (int) strlen(outbuf), 16); } } put_newlines(2); } if (funk) { putln("The following keys are not defined:"); for (i = 0; i < funk; ++i) { put_columns(fk_unknown[i], fk_length[i], 16); } put_mode(exit_attribute_mode); put_newlines(2); } if (first_time) { putln("The following keys are defined:"); } else { putln("The following keys have not been tested:"); } if (scan_mode) { for (i = 0; scan_down[i]; i++) { if (!scan_tested[i]) { if (hex_output) { strcpy(outbuf, hex_expand_to(scan_down[i], 3)); } else { strcpy(outbuf, expand(scan_down[i])); } l = expand_chars; if (hex_output) { strcat(outbuf, hex_expand_to(scan_up[i], 3)); } else { strcat(outbuf, expand(scan_up[i])); } expand_chars += l; l = (int) strlen(scan_name[i]); if (((char_count + 16) & ~15) + ((expand_chars + 7) & ~7) + l >= columns) { put_crlf(); } else if (char_count + 24 > columns) { put_crlf(); } else if (char_count) { putchp(' '); } put_columns(outbuf, expand_chars, 16); put_columns(scan_name[i], l, 8); } } } else { for (i = 0; i < key_count; i++) { if (!fk_tested[i] && fk_name[i] != 0) { if (hex_output) { strcpy(outbuf, hex_expand_to(fkval[i], 3)); } else { strcpy(outbuf, expand(fkval[i])); } l = (int) strlen(fk_name[i]); if (((char_count + 16) & ~15) + ((expand_chars + 7) & ~7) + l >= columns) { put_crlf(); } else if (char_count + 24 > columns) { put_crlf(); } else if (char_count) { putchp(' '); } put_columns(outbuf, expand_chars, 16); put_columns(fk_name[i], l, 8); } } } put_newlines(2); if (show_help) { ptextln("Hit any function key. Type 'end' to quit. Type ? to update the display."); put_crlf(); } }
static int found_exit(char *keybuf, int hx, int cc) { /* return true if the user wants to exit */ int j; char *s; if (scan_mode) { if (*keybuf == '\0') { return TRUE; } } else { int k; /* break is a special case */ if (*keybuf == '\0') { fresh_line(); tty_set(); ptext("Hit X to exit: "); if (wait_here() == 'X') { return TRUE; } keys_tested(0, 1, hx); tty_raw(cc, char_mask); return FALSE; } /* is this the end? */ for (k = 0; (j = (keybuf[k] & STRIP_PARITY)); k++) { if (end_funky(j)) { return TRUE; } } j = TRUE; /* does he need an updated list? */ for (k = 0; keybuf[k]; k++) { j &= (keybuf[k] & STRIP_PARITY) == '?'; } if (j || end_state == '?') { keys_tested(0, 1, hx); tty_raw(cc, char_mask); end_state = 0; return FALSE; } } put_cr(); if (hx) { s = hex_expand_to(keybuf, 10); } else { s = expand_to(keybuf, 10); } sprintf(temp, "%s Unknown", s); put_str(temp); for (j = 0; j < MAX_FK_UNK; j++) { if (j == funk) { fk_length[funk] = expand_chars; if ((fk_unknown[funk] = (char *) malloc(strlen(s) + 1))) { strcpy(fk_unknown[funk++], s); } break; } if (fk_length[j] == expand_chars) { if (!strcmp(fk_unknown[j], s)) { break; } } } return FALSE; }
int tty_alt(register int fd) { register Edit_t *ep = (Edit_t*)(shgd->ed_context); switch(ep->e_raw) { case ECHOMODE: return(-1); case ALTMODE: return(0); case RAWMODE: tty_cooked(fd); } if((tty_get(fd, &ttyparm)==SYSERR) || (!(ttyparm.c_lflag&ECHO))) return(-1); # ifdef FLUSHO ttyparm.c_lflag &= ~FLUSHO; # endif /* FLUSHO */ nttyparm = ttyparm; ep->e_eof = ttyparm.c_cc[VEOF]; # ifdef ECHOCTL /* escape character echos as ^[ */ nttyparm.c_lflag |= (ECHOE|ECHOK|ECHOCTL|PENDIN|IEXTEN); nttyparm.c_cc[VEOL] = ESC; # else /* switch VEOL2 and EOF, since EOF isn't echo'd by driver */ nttyparm.c_lflag |= (ECHOE|ECHOK); nttyparm.c_cc[VEOF] = ESC; /* make ESC the eof char */ # ifdef VEOL2 nttyparm.c_iflag &= ~(IGNCR|ICRNL); nttyparm.c_iflag |= INLCR; nttyparm.c_cc[VEOL] = '\r'; /* make CR an eol char */ nttyparm.c_cc[VEOL2] = ep->e_eof; /* make EOF an eol char */ # else nttyparm.c_cc[VEOL] = ep->e_eof; /* make EOF an eol char */ # endif /* VEOL2 */ # endif /* ECHOCTL */ # ifdef VREPRINT nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE; # endif /* VREPRINT */ # ifdef VDISCARD nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE; # endif /* VDISCARD */ # ifdef VWERASE if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE) nttyparm.c_cc[VWERASE] = cntl('W'); ep->e_werase = nttyparm.c_cc[VWERASE]; # else ep->e_werase = cntl('W'); # endif /* VWERASE */ # ifdef VLNEXT if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE ) nttyparm.c_cc[VLNEXT] = cntl('V'); ep->e_lnext = nttyparm.c_cc[VLNEXT]; # else ep->e_lnext = cntl('V'); # endif /* VLNEXT */ ep->e_erase = ttyparm.c_cc[VERASE]; ep->e_kill = ttyparm.c_cc[VKILL]; if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR ) return(-1); ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW); ep->e_raw = ALTMODE; return(0); }
int tty_raw(register int fd, int echomode) { int echo = echomode; #ifdef L_MASK struct ltchars lchars; #endif /* L_MASK */ register Edit_t *ep = (Edit_t*)(shgd->ed_context); if(ep->e_raw==RAWMODE) return(echo?-1:0); else if(ep->e_raw==ECHOMODE) return(echo?0:-1); #if !SHOPT_RAWONLY if(ep->e_raw != ALTMODE) #endif /* SHOPT_RAWONLY */ { if(tty_get(fd,&ttyparm) == SYSERR) return(-1); } #if L_MASK || VENIX if(ttyparm.sg_flags&LCASE) return(-1); if(!(ttyparm.sg_flags&ECHO)) { if(!echomode) return(-1); echo = 0; } nttyparm = ttyparm; if(!echo) nttyparm.sg_flags &= ~(ECHO | TBDELAY); # ifdef CBREAK nttyparm.sg_flags |= CBREAK; # else nttyparm.sg_flags |= RAW; # endif /* CBREAK */ ep->e_erase = ttyparm.sg_erase; ep->e_kill = ttyparm.sg_kill; ep->e_eof = cntl('D'); ep->e_werase = cntl('W'); ep->e_lnext = cntl('V'); if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR ) return(-1); ep->e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW); # ifdef TIOCGLTC /* try to remove effect of ^V and ^Y and ^O */ if(ioctl(fd,TIOCGLTC,&l_chars) != SYSERR) { lchars = l_chars; lchars.t_lnextc = -1; lchars.t_flushc = -1; lchars.t_dsuspc = -1; /* no delayed stop process signal */ if(ioctl(fd,TIOCSLTC,&lchars) != SYSERR) l_changed |= L_CHARS; } # endif /* TIOCGLTC */ #else if (!(ttyparm.c_lflag & ECHO )) { if(!echomode) return(-1); echo = 0; } # ifdef FLUSHO ttyparm.c_lflag &= ~FLUSHO; # endif /* FLUSHO */ nttyparm = ttyparm; # ifndef u370 nttyparm.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL); nttyparm.c_iflag |= BRKINT; # else nttyparm.c_iflag &= ~(IGNBRK|PARMRK|INLCR|IGNCR|ICRNL|INPCK); nttyparm.c_iflag |= (BRKINT|IGNPAR); # endif /* u370 */ if(echo) nttyparm.c_lflag &= ~(ICANON); else nttyparm.c_lflag &= ~(ICANON|ISIG|ECHO|ECHOK); nttyparm.c_cc[VTIME] = 0; nttyparm.c_cc[VMIN] = 1; # ifdef VREPRINT nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE; # endif /* VREPRINT */ # ifdef VDISCARD nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE; # endif /* VDISCARD */ # ifdef VDSUSP nttyparm.c_cc[VDSUSP] = _POSIX_DISABLE; # endif /* VDSUSP */ # ifdef VWERASE if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE) ep->e_werase = cntl('W'); else ep->e_werase = nttyparm.c_cc[VWERASE]; nttyparm.c_cc[VWERASE] = _POSIX_DISABLE; # else ep->e_werase = cntl('W'); # endif /* VWERASE */ # ifdef VLNEXT if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE ) ep->e_lnext = cntl('V'); else ep->e_lnext = nttyparm.c_cc[VLNEXT]; nttyparm.c_cc[VLNEXT] = _POSIX_DISABLE; # else ep->e_lnext = cntl('V'); # endif /* VLNEXT */ ep->e_intr = ttyparm.c_cc[VINTR]; ep->e_eof = ttyparm.c_cc[VEOF]; ep->e_erase = ttyparm.c_cc[VERASE]; ep->e_kill = ttyparm.c_cc[VKILL]; if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR ) return(-1); ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW); #endif ep->e_raw = (echomode?ECHOMODE:RAWMODE); return(0); }
int pinsys_init(void) { signal_length = (hw.code_length + (hw.code_length / BITS_COUNT) * 2) * 1000000 / 1200; if (!tty_create_lock(hw.device)) { logprintf(LOG_ERR, "could not create lock files"); return (0); } if ((hw.fd = open(hw.device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) { int detected; /* last character gets overwritten */ char auto_lirc_device[] = "/dev/ttyS_"; tty_delete_lock(); logprintf(LOG_WARNING, "could not open %s, autodetecting on /dev/ttyS[0-3]", hw.device); logperror(LOG_WARNING, "pinsys_init()"); /* it can also mean you compiled serial support as a module and it isn't inserted, but that's unlikely unless you're me. */ detected = autodetect(); if (detected == -1) { logprintf(LOG_ERR, "no device found on /dev/ttyS[0-3]"); tty_delete_lock(); return (0); } else { /* detected */ auto_lirc_device[9] = '0' + detected; hw.device = auto_lirc_device; if ((hw.fd = open(hw.device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) { /* unlikely, but hey. */ logprintf(LOG_ERR, "couldn't open autodetected device \"%s\"", hw.device); logperror(LOG_ERR, "pinsys_init()"); tty_delete_lock(); return (0); } } } if (!tty_reset(hw.fd)) { logprintf(LOG_ERR, "could not reset tty"); pinsys_deinit(); return (0); } if (!tty_setbaud(hw.fd, 1200)) { logprintf(LOG_ERR, "could not set baud rate"); pinsys_deinit(); return (0); } /* set RTS, clear DTR */ if (!tty_set(hw.fd, 1, 0) || !tty_clear(hw.fd, 0, 1)) { logprintf(LOG_ERR, "could not set modem lines (DTR/RTS)"); pinsys_deinit(); return (0); } /* I dunno, but when lircd starts may log `reading of byte 1 failed' I know that happened when testing, it's a zero byte. Problem is, flushing doesn't fix it. It's not fatal, it's an indication that it gets fixed. still... */ if (tcflush(hw.fd, TCIFLUSH) < 0) { logprintf(LOG_ERR, "could not flush input buffer"); pinsys_deinit(); return (0); } return (1); }