aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pw.c141
1 files changed, 85 insertions, 56 deletions
diff --git a/pw.c b/pw.c
index 9749933..60cdf13 100644
--- a/pw.c
+++ b/pw.c
@@ -11,6 +11,8 @@
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
#include <regex.h>
enum status_flags {
@@ -120,6 +122,21 @@ static char *addch(char *line, int ch)
abort();
}
+static char *addchesc(char *line, int ch)
+{
+ if (ch == 127) {
+ line = addch(line, '^');
+ line = addch(line, '?');
+ } else if (ch < 32) {
+ line = addch(line, '^');
+ line = addch(line, ch + 64);
+ } else {
+ line = addch(line, ch);
+ }
+
+ return line;
+}
+
static char *getln(FILE *stream)
{
char *line = 0;
@@ -136,15 +153,7 @@ static char *getln(FILE *stream)
return addch(line, 0);
}
- if (ch == 127) {
- line = addch(line, '^');
- line = addch(line, '?');
- } else if (ch < 32) {
- line = addch(line, '^');
- line = addch(line, ch + 64);
- } else {
- line = addch(line, ch);
- }
+ line = addchesc(line, ch);
}
}
@@ -294,7 +303,7 @@ static void execute(char *cmd)
int main(int argc, char **argv)
{
- char *line;
+ char *line = 0;
FILE *tty = fopen("/dev/tty", "r+");
int maxlines = 15, nlines = 0;
int poll_interval = 1000;
@@ -383,12 +392,14 @@ int main(int argc, char **argv)
panic("unable to set TTY parameters");
setvbuf(tty, NULL, _IONBF, 0);
- setvbuf(stdin, NULL, _IONBF, 0);
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+ panic("unable to set stdin nonblocking");
for (unsigned stat = stat_dirty, hpos = 0, kbd_state = kbd_cmd, lasttime = ~0U;
kbd_state != kbd_exit ;)
{
- int force = 0;
+ int force = 0, nfds = 2, pollms = poll_interval;
struct pollfd pe[2] = {
{ .fd = ttyfd, .events = POLLIN | POLLHUP | POLLERR },
{ .fd = fd, .events = POLLIN | POLLHUP | POLLERR },
@@ -412,59 +423,77 @@ int main(int argc, char **argv)
}
}
- if (force) {
- redraw(circbuf, nlines, hpos, columns, stat, curcmd);
- stat &= ~(stat_dirty | stat_trgrd);
- }
-
- if (poll(pe, ((stat & stat_eof)) ? 1 : 2, poll_interval) <= 0) {
- if ((stat & stat_dirty) && nlines == maxlines) {
- redraw(circbuf, nlines, hpos, columns, stat, curcmd);
- stat &= ~stat_dirty;
- }
- if (kbd_state == kbd_esc || kbd_state == kbd_result) {
- kbd_state = kbd_cmd;
- curcmd = 0;
- clrline();
- drawstatus(stat, curcmd);
- }
- } else {
- if ((stat & stat_eof) == 0 && pe[1].revents) {
- if ((line = getln(stdin))) {
- if ((stat & stat_htmode))
- if (regexec(&trigex, line, 0, NULL, 0) == 0)
- stat |= stat_trgrd;
- if (nlines == maxlines) {
- dsdrop(circbuf[0]);
- memmove(circbuf, circbuf + 1, (nlines - 1) * sizeof *circbuf);
- circbuf[nlines - 1] = line;
- stat |= stat_dirty;
- if ((stat & stat_ttmode))
- if (regexec(&trigex, circbuf[0], 0, NULL, 0) == 0)
- stat |= stat_trgrd;
- } else {
- circbuf[nlines++] = line;
- if ((stat & stat_susp) == 0) {
- snapshot[snaplines++] = dsref(line);
- clrline();
- drawline(line, hpos, columns);
- drawstatus(stat, curcmd);
- }
- }
- } else {
- if (auto_quit)
- kbd_state = kbd_exit;
- else
+ if ((stat & stat_eof) == 0) {
+ int ch;
+ while ((ch = getc(stdin)) != EOF && ch != '\n')
+ line = addchesc(line, ch);
+ if (ch == EOF) {
+ if (feof(stdin) || (errno != EAGAIN && errno != EWOULDBLOCK)) {
+ nfds = 1;
+ if (!auto_quit)
stat |= stat_eof;
redraw(circbuf, nlines, hpos, columns, stat, curcmd);
stat |= stat_eof;
stat &= ~stat_dirty;
if (!ferror(stdin))
exit_status = 0;
- continue;
+ if (auto_quit)
+ break;
+ }
+ clearerr(stdin);
+ } else {
+ nfds = 1;
+ line = addch(line, 0);
+ if ((stat & stat_htmode))
+ if (regexec(&trigex, line, 0, NULL, 0) == 0)
+ stat |= stat_trgrd;
+ if (nlines == maxlines) {
+ dsdrop(circbuf[0]);
+ memmove(circbuf, circbuf + 1, (nlines - 1) * sizeof *circbuf);
+ circbuf[nlines - 1] = line;
+ stat |= stat_dirty;
+ if ((stat & stat_ttmode))
+ if (regexec(&trigex, circbuf[0], 0, NULL, 0) == 0)
+ stat |= stat_trgrd;
+ } else {
+ circbuf[nlines++] = line;
+ if ((stat & stat_susp) == 0) {
+ snapshot[snaplines++] = dsref(line);
+ clrline();
+ drawline(line, hpos, columns);
+ drawstatus(stat, curcmd);
+ }
}
+ line = 0;
}
+ } else {
+ nfds = 1;
+ }
+
+ if (force) {
+ redraw(circbuf, nlines, hpos, columns, stat, curcmd);
+ stat &= ~(stat_dirty | stat_trgrd);
+ }
+
+ if ((stat & stat_eof))
+ pollms = -1;
+ else if (nfds < 2)
+ pollms = 0;
+ if (poll(pe, nfds, pollms) <= 0) {
+ if (pollms) {
+ if ((stat & stat_dirty) && nlines == maxlines) {
+ redraw(circbuf, nlines, hpos, columns, stat, curcmd);
+ stat &= ~stat_dirty;
+ }
+ if (kbd_state == kbd_esc || kbd_state == kbd_result) {
+ kbd_state = kbd_cmd;
+ curcmd = 0;
+ clrline();
+ drawstatus(stat, curcmd);
+ }
+ }
+ } else {
if ((pe[0].revents)) {
int ch = getc(tty);