-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
regression: piped less swallows keystrokes meant for next shell command #557
Comments
Hm, the idea of typing input for the next command before knowing the outcome of a potentially interactive command seems strange to me. If the output of less happened to be more than a screenful, then less would NOT exit due to the -F flag, and any input typed in would be interpreted as less commands, doing something entirely unintended. The change in behavior is probably due to support for ^X to interrupt a blocked read, but I'm not convinced that it's a regression. |
I guess not necessarily a regression, but a change in a long-term old behavior. Here's an example: Mercurial uses |
I do this all the time (type the next command ahead of time before current command finishes, in anticipation of the prompt), but usually only with commands that don't process terminal input themselves. Since That said, I can see where the old behavior could be useful for specific scenarios. And I can remember instances where I did rely on "knowing" the behavior of an interactive program and typing ahead of time. But that would only be when the behavior was known in advance. I don't think running under Note that earlier ^X support still had the old behavior. I can reproduce the OP-desired behavior with less-590 (Ubuntu22) which seems to work fine to start/stop Follow with F/^X. I bisected, and the new behavior first appears in v611. |
The issue is less needs to read input characters received while reading file input in order to check whether a ctrl-X has been entered. I guess if -F is given, less could defer checking for ctrl-X until after the first screen has been displayed, but that would mean that while reading a slow pipe, it would be impossible to interrupt the input during that first screen (except via ctrl-C which could kill the piping program). It seems to me that retaining the ctrl-X functionality is more important that allowing this problematic typeahead feature. Another approach would be to read the characters but push them back on the tty if they are not ctrl-X, but I don't know of any way to do that, and even if possible it seems that that might cause other problems. |
If CTRL-C were used to cancel, the user probably intends for the whole process group to get SIGINT anyways (like normally in a shell pipeline), so that may not be an actual problem. But deferring seems like a lot of trouble. It would be good to know if any others were relying on this behavior... |
TIOCSTI doesn't seem usable. It returns EIO unless I run it as root. Even as root, it doesn't return an error, but the characters don't appear in the shell after less exits. There are obvious security concerns in having a program inject tty input that is read by the shell, so I'd be surprised if there's a way to do this. |
That's interesting, I don't get that (ubuntu22). I'm not advocating for or against this btw, and don't anticipate using it myself. But just as an exercise: #include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
void
main (void)
{
int i, ret, fd, inchar;
char *toinject = "ls";
size_t len = strlen(toinject);
struct termios saved, attrs;
fd = open("/dev/tty", O_RDWR);
tcgetattr(fd, &attrs);
memcpy(&saved, &attrs, sizeof(attrs));
attrs.c_lflag &= ~ICANON;
attrs.c_cc[VMIN] = 1;
attrs.c_cc[VTIME] = 0;
if ((ret = tcsetattr(fd, TCSANOW, &attrs)) == -1)
perror("tcsetattr");
puts("enter a character:");
read(fd, &inchar, 1);
printf("\nread a char: %c\n", inchar);
for (i = 0; i < len; i++)
if ((ret = ioctl(fd, TIOCSTI, toinject + i)) == -1)
perror("ioctl");
tcsetattr(fd, TCSADRAIN, &saved);
} $ ./testinject
enter a character:
a
read a char: a
ls
$ ls This was just as an unprivileged user. Worked first try so I didn't try fiddling with flags or anything to see what parts are necessary...
I don't think it matters, because any program running with the user's privileges can already do stuff as the user like run |
Interesting. Running it on my Fedora system (Linux 6.9.9-200.fc40.x86_64), I get this:
And if I run it as root, I get
Unlike in your output, I don't see "ls" appear after the prompt. Pressing ENTER at that point does not actually execute an "ls" command. Does it in your case?
Yeah, good point. |
Yes it definitely queues it on my ubuntu22 system (6.5.0 kernel) and I can just press enter after it exits, and get a listing. That's interesting... I noticed my /dev/tty permissions are 0666, I wonder if yours are? But not working even as root is really interesting. Must be some more paranoid setting on Fedora kernels or something. Obviously it can't be used if not broadly applicable... well, worth the discussion anyways, and here for posterity now. |
I just encountered this with I was also able to reproduce with In the cases where the pager is started by the tool (instead of via explicit user action like I don't know how common it is for tools other than these VCS tools to start the pager themselves, especially with the |
Yes, I get a different result from that command:
If I change it to 1 and then run the test program, it now works as you describe. I installed this system (Fedora) less than a month ago and I'm certain that I never manually changed that value to 1, so it must have been the default for this system. I see that the help for that sysctl entry (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=83efeeeb3d04b22aaed1df99bc70a48fe9d22c4d) says
So it seems that it would not be safe to assume that legacy_tiocsti is set on an arbitrary system. |
Is there anything we can do to work around this issue, such as an environment variable that |
+1 to the XKCD comment; a lot of developer workflows involve chaining several commands together in rapid-fire, and some of those commands display informational outputs that I don't need. Seeing this information in an information-only manner quickly would be nice, and having a flag we can pass to specify "Don't eat characters or else" would be nice, otherwise we'll have to use something other than |
I've added the --no-poll option in 4e516a1. Let me know if that does what you want. Note that |
Thank you! The concern I have with this being a CLI option, however, is that we need to either version-detect |
You can use the LESSKEY_CONTENT environment variable to conditionally set command line options based on the version. Unfortunately the post659 branch doesn't yet have a version number, but suppose the --no-poll option appears in the master branch in version 670. Then you could put this in your environment:
|
With earlier versions of
less
(e.g.608
):With version
643
:Many users type in the next command while waiting for the previous one to complete. This is especially painful when using source control commands which paginate most of their output. The current workaround is to turn off paging by default.
The text was updated successfully, but these errors were encountered: