diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-05-02 21:05:12 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-05-02 21:05:12 -0700 |
commit | b06d9454f395f007a7ef6081fb43c4298b66b09b (patch) | |
tree | 420cee03f2089bb0741d65c33e57ad7004942cc4 | |
parent | e153fa3d6207b5139db352e58cd775c7e42ad202 (diff) | |
download | pw-b06d9454f395f007a7ef6081fb43c4298b66b09b.tar.gz pw-b06d9454f395f007a7ef6081fb43c4298b66b09b.tar.bz2 pw-b06d9454f395f007a7ef6081fb43c4298b66b09b.zip |
Remove non-interactive mode.
-rw-r--r-- | pw.1 | 103 | ||||
-rw-r--r-- | pw.c | 63 |
2 files changed, 92 insertions, 74 deletions
@@ -34,34 +34,15 @@ command | pw [-i interval] [-l interval] [-n number-of-lines] [-dEB] .SH DESCRIPTION .I pw -stands for Pipe Watch. This is a utility which continuously reads textual input -from a pipe or pipe-like source, and maintains a dynamic display of the -most recently read -.I N -lines. - -If -.I pw -is invoked such that its standard input is a TTY, it simply reads lines -and prints them in its characteristic way, with control characters replaced by -caret codes, until end-of-file is encountered. Long lines aren't clipped, -and there is no interactive mode. - -The intended use of -.I pw -is that its standard input is a pipe, such as the output of another command, -or a pipe-like device such as a socket or whatever. -In this situation, -.I pw -expects to be executed in a TTY session in which a -.B /dev/tty -device can be opened, for the purposes of obtaining interactive input. -The remaining description pertains to this interactive mode. +stands for Pipe Watch, a utility that continuously reads lines of +text from a pipe or pipe-like source, passes them through a FIFO buffer, and +maintains a display based on the occasional sampling the contents of the +FIFO buffer, with useful features such as triggering and filtering. -In interactive mode, +Upon successful startup, .I pw -simultaneously monitors its standard input for the arrival of new data, -as well as the TTY for interactive commands. +simultaneously monitors its standard input for the +arrival of new data, as well as the TTY for interactive commands. Lines from standard input are placed into a FIFO buffer. While the FIFO buffer is not yet full, lines are displayed immediately. After the FIFO buffer fills up with the specified number of lines @@ -69,13 +50,27 @@ After the FIFO buffer fills up with the specified number of lines .B -n option) then .I pw -transitions into a mode in which, old lines are bumped from the tail of the -FIFO as new ones are added to the head, and refresh operations are required in -order to display the current FIFO contents. +transitions into the free-running mode in which, old lines are removed from the +tail of the FIFO as new ones are added to the head, and the display is no +longer refreshed for every new line arriving into the FIFO. -The display only refreshes with the latest FIFO data when +In free-running mode, the display is automatically refreshed with the latest +FIFO data only if: .IP 1. -there is some keyboard activity from the terminal; or +suspended mode is not in effect; and +.IP 2. +trigger mode is not in effect; and +.IP 3. +.I pw +isn't executing in the background (see the +.B Ctrl-Z +command). +.PP + +When the above conditions do not hold, and thus the display is being +automatically refreshed, it is refreshed at these times: +.IP 1. +when there is some keyboard activity from the terminal; or .IP 2. when the interval period has expired without new input having been seen; or else @@ -83,12 +78,22 @@ without new input having been seen; or else whenever the long period elapses. .PP -In other words, while the pipe is spewing, and there is -no keyboard input, the display is updated infrequently, only according to the -long interval. +In other words, while the input is rapidly producing data, and there is no +keyboard input, the display is updated infrequently, only according to the long +interval. + +If +.I pw +is executing in the foreground, and if display updates aren't suspended, and if +trigger mode is effect, then the display updates automatically only when a +trigger is activated by a pattern match on the FIFO contents. Trigger mode is +activated using the +.B > +and +.B ? +commands below. -The display is also updated when standard input indicates end-of-data. -In this situation, +When standard input indicates end-of-data. .I pw terminates, unless the .B -d @@ -128,10 +133,9 @@ portion appears delimited by .SH COMMANDS -When +While reading data from standard input, .I pw -enters closed loop operation, the following single-key commands are -available. +monitors the TTY for input, providing the following commands. The commands may be prefixed by a numeric argument, which is ignored by commands to which it is not applicable. The numeric argument is specified by @@ -581,6 +585,27 @@ that is the default, this option has no effect unless it appears after a .B -E option. +.SH ENVIRONMENT + +.I pw +ignores the +.B TERM +environment variable, requiring an ANSI terminal. + +.I pw +requires the following conditions to hold in regard to its execution environment, +otherwise it terminates with an error diagnostic: +.IP 1. +Standard output must be a TTY device. +.IP 2. +Standard input is either not a TTY device, or else not the same TTY device +as standard output. +.IP 3. +It must be possible to open the +.B /dev/tty +device, which is the same TTY as standard output. +.PP + .SH TERMINATION STATUS If @@ -233,26 +233,6 @@ static char *addchesc(char *line, int ch) return line; } -static char *getln(FILE *stream) -{ - char *line = 0; - - for (;;) { - int ch = getc(stream); - - if (ch == EOF) - return line; - - if (ch == '\n') { - if (line) - return line; - return addch(line, 0); - } - - line = addchesc(line, ch); - } -} - static void usage(const char *name) { fprintf(stderr, @@ -702,7 +682,8 @@ int main(int argc, char **argv) FILE *tty = fopen("/dev/tty", "r+"); int maxlines = 15, nlines = 0, maxed = 0; int opt; - int fd = fileno(stdin); + int ifd = fileno(stdin); + int ofd = fileno(stdout); int ttyfd = tty ? fileno(tty) : -1; char **circbuf; struct termios tty_saved, tty_new; @@ -719,11 +700,32 @@ int main(int argc, char **argv) static struct sigaction sa; #endif - if (fd < 0) - panic("unable to obtain input file descriptor"); + if (ifd < 0) + panic("unable to obtain input file descriptor\n"); + + if (ofd < 0) + panic("unable to obtain input file descriptor\n"); + + if (!isatty(ofd)) + error("standard output must be a TTY\n"); if (ttyfd < 0) - panic("unable to open /dev/tty"); + panic("unable to open /dev/tty\n"); + + { + pid_t ogrp = tcgetpgrp(ofd); + pid_t igrp = tcgetpgrp(ifd); + pid_t tgrp = tcgetpgrp(ttyfd); + + if (ogrp < 0) + error("standard output isn't a job control TTY\n"); + + if (ogrp != tgrp) + error("/dev/tty isn't the same as the standard output TTY\n"); + + if (igrp == ogrp) + error("standard input and standard output are the same TTY\n"); + } while ((opt = getopt(argc, argv, "n:i:l:dEB")) != -1) { switch (opt) { @@ -774,15 +776,6 @@ int main(int argc, char **argv) if ((snapshot[0] = calloc(sizeof *snapshot[0], maxlines)) == 0) panic("out of memory"); - if (isatty(fd)) { - while ((line = getln(stdin))) { - puts(line); - dsdrop(line); - } - - return 0; - } - if (ioctl(ttyfd, TIOCGWINSZ, &ws) == 0 && ws.ws_row != 0) { if (maxlines >= ws.ws_row) { maxlines = ws.ws_row - 1; @@ -804,7 +797,7 @@ int main(int argc, char **argv) setvbuf(tty, NULL, _IONBF, 0); - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) + if (fcntl(ifd, F_SETFL, O_NONBLOCK) < 0) panic("unable to set stdin nonblocking"); if (!isbkgnd(stdout)) @@ -826,7 +819,7 @@ int main(int argc, char **argv) int force = 0, nfds = 2, pollms = poll_interval; struct pollfd pe[2] = { { .fd = ttyfd, .events = POLLIN | POLLHUP | POLLERR }, - { .fd = fd, .events = POLLIN | POLLHUP | POLLERR }, + { .fd = ifd, .events = POLLIN | POLLHUP | POLLERR }, }; if ((stat & stat_eof) == 0) { |