Reputation: 2671
So I wanted to make a program that accepts input from stdin
through re-direction or interactive input. getline
can achieve the re-direction read, but I wanted to have all the nice features of readline
for the interactive input. The program's purpose is to manipulate text through a language and output the results to stdout (similar to what sed does). The issue, is that I cannot do my_prog > output.txt
with readline
because whatever was entered into readline
the output of readline goes into that file, and I cannot even see it. Currently, I have a workaround where I just send the output of readline
to stderr
using rl_outstream
. This gives me the behavior I am looking for, but feels like a hack when there is probably a more straight-forward solution. A good example of what I am looking for is what python does.
python > output.txt
>>> print 'hello'
>>> exit()
cat output.txt
hello
Here is some code to demonstrate what I'm doing...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "readline/readline.h"
int main(int argc, char** argv)
{
char* from_stdin = malloc(512);
char* line = NULL;
rl_outstream = stderr;
if(isatty(STDIN_FILENO)) {
do {
line = readline("");
if(line) {
strcat(from_stdin, line);
strcat(from_stdin, "\n");
} else {
break;
}
} while(1);
} else {
size_t n = 0;
while(getline(&line, &n, stdin) != -1)
strcat(from_stdin, line);
}
puts(from_stdin);
}
Patch for accepted solution:
--rl_outstream = stderr;
++FILE* more_hacky = fopen("/dev/tty", "w");
++rl_outstream = more_hacky;
I agree about this being more hacky. I will probably leave my code as is, but this would leave stderr more "pure" for errors if I choose.
Upvotes: 3
Views: 693
Reputation: 133859
For what it is worth, CPython does use STDERR_FILENO
as the output file descriptor for Readline iff !isatty(STDOUT_FILENO)
a fact which you can verify with strace
and alike.
Without redirection we get
% strace -o strace.out python3 && grep '>>>' strace.out
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
write(1, ">>> ", 4) = 4
and with redirection
% strace -o strace.out python3 > python.out && grep '>>>' strace.out
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
write(2, ">>> ", 4) = 4
The alternative would be opening /dev/tty
for the output stream but I feel that that would be more, not less, hacky.
Upvotes: 2