Bash – How to run a program in its own tty

bashioctlshellterminaltty

I'm messing with TIOCSTI which shoves data into the terminal's input buffer. I want to be able to capture this data before it arrives at the shell or redirects it to a file.

To better illustrate what I'm trying to do:

gcc -x c -o pusher.bin - <<PUSHER
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>

int main() {
  char *c = "echo 'Catch me if you can'\n";
  while(*c) ioctl(0, TIOCSTI, c++);
}
PUSHER
./pusher.bin

If running in my terminal, ./pusher.bin will inject echo 'Catch me if you can'\n in my tty which my shell would immediately execute. If I run setsid ./pusher.bin, echo won't be injected in my terminal but I also won't be able to capture it.

I want to wrap ./pusher.bin with something that allows me to inspect what pusher would have injected in my tty's input buffer if it was run bare.

Clarification: I'm aware that injected input can be captured after it arrives at my shell's stdin. This approach while effective at capturing the injected input will also capture normal user input. Furthermore, this approach would not work if stdin is closed or if the process is not attached to a tty. These downsides alone make capturing stdin unviable as a general solution.

Best Answer

It seems script is the solution, as mentioned by A.B. With -e you even get the return code of the program. cat -vet shows more explicitly the carriage return ^M and newline $.

$ script -q -e out -c ./pusher.bin >/dev/null; echo $?
0
$ cat -vet out
Script started on Mon Dec 21 10:54:40 2020$
echo 'Catch me if you can'^M$