diff options
-rw-r--r-- | lib/lib.c | 98 | ||||
-rw-r--r-- | lib/lib.h | 3 | ||||
-rw-r--r-- | lib/net.c | 5 | ||||
-rw-r--r-- | lib/password.c | 33 | ||||
-rw-r--r-- | toys/other/hexedit.c (renamed from toys/pending/hexedit.c) | 0 |
5 files changed, 106 insertions, 33 deletions
@@ -637,6 +637,40 @@ int terminal_size(unsigned *xx, unsigned *yy) return x || y; } +// Reset terminal to known state, saving copy of old state if old != NULL. +int set_terminal(int fd, int raw, struct termios *old) +{ + struct termios termio; + + // Fetch local copy of old terminfo, and copy struct contents to *old if set + if (!tcgetattr(fd, &termio) && old) *old = termio; + + // the following are the bits set for an xterm. Linux text mode TTYs by + // default add two additional bits that only matter for serial processing + // (turn serial line break into an interrupt, and XON/XOFF flow control) + + // Any key unblocks output, swap CR and NL on input + termio.c_iflag = IXANY|ICRNL|INLCR; + if (toys.which->flags & TOYFLAG_LOCALE) termio.c_iflag |= IUTF8; + + // Output appends CR to NL, does magic undocumented postprocessing + termio.c_oflag = ONLCR|OPOST; + + // Leave serial port speed alone + // termio.c_cflag = C_READ|CS8|EXTB; + + // Generate signals, input entire line at once, echo output + // erase, line kill, escape control characters with ^ + // erase line char at a time + // "extended" behavior: ctrl-V quotes next char, ctrl-R reprints unread chars, + // ctrl-W erases word + termio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; + + if (raw) cfmakeraw(&termio); + + return tcsetattr(fd, TCSANOW, &termio); +} + int yesno(char *prompt, int def) { char buf; @@ -895,3 +929,67 @@ int qstrcmp(const void *a, const void *b) { return strcmp(*(char **)a, *(char **)b); } + +int xpoll(struct pollfd *fds, int nfds, int timeout) +{ + int i; + + for (;;) { + if (0>(i = poll(fds, nfds, timeout))) { + if (errno != EINTR && errno != ENOMEM) perror_exit("xpoll"); + else if (timeout>0) timeout--; + } else return i; + } +} + +// Scan stdin for a keypress, parsing known escape sequences +// seq is array of char * strings, ends with NULL ptr +// Returns: 0-255=literal, -1=EOF, -2=NONE, 256-...=index into seq +// scratch space is necessary because last char of !seq could start new seq +// Zero out first byte of scratch before first call to scan_key +// block=0 allows fetching multiple characters before updating display +int scan_key(char *scratch, char **seqs, int block) +{ + struct pollfd pfd; + int maybe, i, j; + char *test; + + for (;;) { + pfd.fd = 0; + pfd.events = POLLIN; + pfd.revents = 0; + + // check sequences + maybe = 0; + if (*scratch) { + for (i = maybe = 0; (test = seqs[i]); i++) { + for (j = 0; j<*scratch; j++) if (scratch[j+1] != test[j]) break; + if (j == *scratch) { + maybe = 1; + if (!test[j]) { + // We recognized current sequence: consume and return + *scratch = 0; + return 256+i; + } + } + } + // If current data can't be a known sequence, return next raw char + if (!maybe) break; + } + + // Need more data to decide + + // 30 miliseconds is about the gap between characters at 300 baud + if (maybe || !block) if (!xpoll(&pfd, 1, 30*maybe)) break; + + if (1 != read(0, scratch+1+*scratch, 1)) return -1; + ++*scratch; + } + + // Was not a sequence + if (!*scratch) return -2; + i = scratch[1]; + if (--*scratch) memmove(scratch+1, scratch+2, *scratch); + + return i; +} @@ -174,9 +174,12 @@ void replace_tempfile(int fdin, int fdout, char **tempname); void crc_init(unsigned int *crc_table, int little_endian); void base64_init(char *p); int terminal_size(unsigned *x, unsigned *y); +int set_terminal(int fd, int raw, struct termios *old); int yesno(char *prompt, int def); int human_readable(char *buf, unsigned long long num); int qstrcmp(const void *a, const void *b); +int xpoll(struct pollfd *fds, int nfds, int timeout); +int scan_key(char *scratch, char **seqs, int block); // net.c int xsocket(int domain, int type, int protocol); @@ -7,3 +7,8 @@ int xsocket(int domain, int type, int protocol) if (fd < 0) perror_exit("socket %x %x", type, protocol); return fd; } + +void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len) +{ + if (-1 == setsockopt(fd, level, opt, val, len)) perror_exit("setsockopt"); +} diff --git a/lib/password.c b/lib/password.c index b3cc199e..9654d42d 100644 --- a/lib/password.c +++ b/lib/password.c @@ -46,39 +46,6 @@ int get_salt(char *salt, char *algo) return -1; } -// Reset terminal to known state, returning old state if old != NULL. -int set_terminal(int fd, int raw, struct termios *old) -{ - struct termios termio; - - if (!tcgetattr(fd, &termio) && old) *old = termio; - - // the following are the bits set for an xterm. Linux text mode TTYs by - // default add two additional bits that only matter for serial processing - // (turn serial line break into an interrupt, and XON/XOFF flow control) - - // Any key unblocks output, swap CR and NL on input - termio.c_iflag = IXANY|ICRNL|INLCR; - if (toys.which->flags & TOYFLAG_LOCALE) termio.c_iflag |= IUTF8; - - // Output appends CR to NL, does magic undocumented postprocessing - termio.c_oflag = ONLCR|OPOST; - - // Leave serial port speed alone - // termio.c_cflag = C_READ|CS8|EXTB; - - // Generate signals, input entire line at once, echo output - // erase, line kill, escape control characters with ^ - // erase line char at a time - // "extended" behavior: ctrl-V quotes next char, ctrl-R reprints unread chars, - // ctrl-W erases word - termio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; - - if (raw) cfmakeraw(&termio); - - return tcsetattr(fd, TCSANOW, &termio); -} - // Prompt with mesg, read password into buf, return 0 for success 1 for fail int read_password(char *buf, int buflen, char *mesg) { diff --git a/toys/pending/hexedit.c b/toys/other/hexedit.c index 668e51c4..668e51c4 100644 --- a/toys/pending/hexedit.c +++ b/toys/other/hexedit.c |