From e1145931a5427552702791220395801d8d09c7ea Mon Sep 17 00:00:00 2001 From: DTB Date: Sat, 31 Aug 2024 22:19:13 -0600 Subject: [PATCH] peek(1): fix erroring on stdin/stdout redirection --- src/peek.c | 74 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/src/peek.c b/src/peek.c index c84a2f8..fb77189 100644 --- a/src/peek.c +++ b/src/peek.c @@ -62,6 +62,9 @@ usage(char *argv0) { } int main(int argc, char *argv[]){ + bool is_term; /* Is stdin a terminal? */ + bool must_be_term = 1; /* Must it be? */ + #ifdef __OpenBSD__ if (pledge("stdio tty unveil", "") != 0 || unveil(NULL, NULL) != 0) { /* This isn't fatal; these return values could be cast to void just as @@ -70,58 +73,63 @@ int main(int argc, char *argv[]){ } #endif + is_term = isatty(STDIN_FILENO); + if (argc > 0) { /* option parsing */ - bool allow_nonterminals; int c; program_name = argv[0]; - allow_nonterminals = 0; while ((c = getopt(argc, argv, "i")) != -1) { switch (c) { - case 'i': allow_nonterminals = 1; break; + case 'i': must_be_term = 0; break; default: return usage(argv[0]); } } if (argc > optind) { return usage(argv[0]); } - - if (!allow_nonterminals && isatty(STDIN_FILENO) != 1) { - (void)fprintf( - stderr, - "%s: Must be run in a terminal (specify -i to skip this" - " check)\n", - argv[0] - ); - return EX_USAGE; - } } - { /* Install signal handler */ - /* There isn't a difference in functionality between the signal(2) and - * sigaction(2) methods. sigaction(2) is vastly preferred for - * portability but some configurations can only use signal(2). */ - /* Errors aren't terminating because the worst that happens is some - * terminal phooeyness if things go awry. */ + if (!is_term && must_be_term) { + (void)fprintf( + stderr, + "%s: Must be run in a terminal (specify -i to skip this check)\n", + argv[0] + ); + return EX_USAGE; + } + + if (is_term) { + { /* Install signal handler */ + /* There isn't a difference in functionality between the signal(2) + * and sigaction(2) methods. sigaction(2) is vastly preferred for + * portability but some older systems only have signal(2). */ + /* Errors aren't terminating because the worst that happens is some + * terminal phooeyness if things go awry. */ #if defined _POSIX_C_SOURCE - struct sigaction act = { 0 }; + struct sigaction act = { 0 }; - act.sa_handler = restore_echo; - if (sigaction(SIGINT, &act, NULL) != 0) { perror(program_name); } + act.sa_handler = restore_echo; + if (sigaction(SIGINT, &act, NULL) != 0) { perror(program_name); } #else - if (signal(SIGINT, restore_echo) == SIG_ERR) { perror(program_name); } + if (signal(SIGINT, restore_echo) == SIG_ERR) { + perror(program_name); + } #endif - } + } - /* Banish terminal echo; this terminates when it fails, because it's the - * whole point of the program. */ - { - struct termios t; + { /* Banish terminal echo */ + /* This terminates when it fails because it's the whole point of + * the program. */ + struct termios t; - if (tcgetattr(STDIN_FILENO, &t) != 0) { return ioerr(program_name); } - t.c_lflag ^= ECHO; - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) != 0) { - return ioerr(program_name); + if (tcgetattr(STDIN_FILENO, &t) != 0) { + return ioerr(program_name); + } + t.c_lflag ^= ECHO; + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) != 0) { + return ioerr(program_name); + } } } @@ -133,7 +141,7 @@ int main(int argc, char *argv[]){ } } - restore_echo(0); + if (is_term) { restore_echo(0); } return EX_OK; }