From ce8503f859345990a14be90bf89dadf7f73d7613 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Thu, 6 Jan 2011 16:25:40 +0100 Subject: BarReadline rewrite Doesn't use c streams any more, allows multiplexing of fifo/stdin in all situations. --- src/ui_readline.c | 110 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 31 deletions(-) (limited to 'src/ui_readline.c') diff --git a/src/ui_readline.c b/src/ui_readline.c index 98af5ea..8e6ecb4 100644 --- a/src/ui_readline.c +++ b/src/ui_readline.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2010 +Copyright (c) 2008-2011 Lars-Dominik Braun Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,6 +24,10 @@ THE SOFTWARE. #include #include #include +#include +#include + +#include "ui_readline.h" static inline void BarReadlineMoveLeft (char *buf, size_t *bufPos, size_t *bufLen) { @@ -52,33 +56,73 @@ static inline char BarReadlineIsUtf8Content (char b) { * @param buffer * @param buffer size * @param accept these characters - * @param return if buffer full (otherwise more characters are not accepted) - * @param don't echo anything (for passwords) - * @param read from this fd + * @param input fds + * @param flags + * @param timeout (seconds) or -1 (no timeout) * @return number of bytes read from stdin */ -size_t BarReadline (char *buf, size_t bufSize, const char *mask, - char fullReturn, char noEcho, FILE *fd) { - int chr = 0; +size_t BarReadline (char *buf, const size_t bufSize, const char *mask, + BarReadlineFds_t *input, const BarReadlineFlags_t flags, int timeout) { size_t bufPos = 0; size_t bufLen = 0; unsigned char escapeState = 0; + fd_set set; + const bool echo = !(flags & BAR_RL_NOECHO); + + assert (buf != NULL); + assert (bufSize > 0); + assert (input != NULL); memset (buf, 0, bufSize); /* if fd is a fifo fgetc will always return EOF if nobody writes to * it, stdin will block */ - while ((chr = fgetc (fd)) != EOF) { + while (1) { + int curFd = -1; + char chr; + struct timeval timeoutstruct; + + /* select modifies set and timeout */ + memcpy (&set, &input->set, sizeof (set)); + timeoutstruct.tv_sec = timeout; + timeoutstruct.tv_usec = 0; + + if (select (input->maxfd, &set, NULL, NULL, + (timeout == -1) ? NULL : &timeoutstruct) <= 0) { + /* fail or timeout */ + break; + } + + assert (sizeof (input->fds) / sizeof (*input->fds) == 2); + if (FD_ISSET(input->fds[0], &set)) { + curFd = input->fds[0]; + } else if (input->fds[1] != -1 && FD_ISSET(input->fds[1], &set)) { + curFd = input->fds[1]; + } + if (read (curFd, &chr, sizeof (chr)) <= 0) { + /* select() is going wild if fdset contains EOFed stdin, only check + * for stdin, fifo is "reopened" as soon as another writer is + * available + * FIXME: ugly */ + if (curFd == STDIN_FILENO) { + FD_CLR (curFd, &input->set); + } + continue; + } switch (chr) { /* EOT */ case 4: - printf ("\n"); + if (echo) { + fputs ("\n", stdout); + } return bufLen; break; /* return */ case 10: - printf ("\n"); + if (echo) { + fputs ("\n", stdout); + } return bufLen; break; @@ -109,15 +153,15 @@ size_t BarReadline (char *buf, size_t bufSize, const char *mask, } } /* move caret back and delete last character */ - if (!noEcho) { - printf ("\033[D\033[K"); + if (echo) { + fputs ("\033[D\033[K", stdout); fflush (stdout); } } else if (bufPos == 0 && buf[bufPos] != '\0') { /* delete char at position 0 but don't move cursor any further */ buf[bufPos] = '\0'; - if (!noEcho) { - printf ("\033[K"); + if (echo) { + fputs ("\033[K", stdout); fflush (stdout); } } @@ -145,18 +189,21 @@ size_t BarReadline (char *buf, size_t bufSize, const char *mask, buf[bufPos] = chr; ++bufPos; ++bufLen; - if (!noEcho) { - fputc (chr, stdout); + if (echo) { + putchar (chr); + fflush (stdout); } /* buffer full => return if requested */ - if (fullReturn && bufPos >= bufSize-1) { - printf ("\n"); + if (bufPos >= bufSize-1 && (flags & BAR_RL_FULLRETURN)) { + if (echo) { + fputs ("\n", stdout); + } return bufLen; } } break; - } - } + } /* end switch */ + } /* end while */ return 0; } @@ -165,35 +212,36 @@ size_t BarReadline (char *buf, size_t bufSize, const char *mask, * @param buffer size * @return number of bytes read from stdin */ -size_t BarReadlineStr (char *buf, size_t bufSize, char noEcho, - FILE *fd) { - return BarReadline (buf, bufSize, NULL, 0, noEcho, fd); +size_t BarReadlineStr (char *buf, const size_t bufSize, + BarReadlineFds_t *input, const BarReadlineFlags_t flags) { + return BarReadline (buf, bufSize, NULL, input, flags, -1); } /* Read int from stdin * @param write result into this variable * @return number of bytes read from stdin */ -size_t BarReadlineInt (int *ret, FILE *fd) { +size_t BarReadlineInt (int *ret, BarReadlineFds_t *input) { int rlRet = 0; char buf[16]; - rlRet = BarReadline (buf, sizeof (buf), "0123456789", 0, 0, fd); + rlRet = BarReadline (buf, sizeof (buf), "0123456789", input, + BAR_RL_DEFAULT, -1); *ret = atoi ((char *) buf); return rlRet; } /* Yes/No? - * @param defaul (user presses enter) + * @param default (user presses enter) */ -int BarReadlineYesNo (char def, FILE *fd) { +bool BarReadlineYesNo (bool def, BarReadlineFds_t *input) { char buf[2]; - BarReadline (buf, sizeof (buf), "yYnN", 1, 0, fd); - if (*buf == 'y' || *buf == 'Y' || (def == 1 && *buf == '\0')) { - return 1; + BarReadline (buf, sizeof (buf), "yYnN", input, BAR_RL_FULLRETURN, -1); + if (*buf == 'y' || *buf == 'Y' || (def == true && *buf == '\0')) { + return true; } else { - return 0; + return false; } } -- cgit v1.2.3