I would like to print a big matrix of data which I have in a linked list. It doesn't fit into a terminal (80 lines), so it is inconvenient to print it with standard printing functions; and less
is already invented, so I wouldn't want to be reinventing it using ncurses; so I want to pass some printf
d lines to less
.
My first guess would be to write to a file, and then system("less -S file");
, and then delete the file.
A more complicated solution would be to rewrite less so that its main()
is converted to a less()
function that I can call from C, and instead of a filename string I could provide it with a file descriptor or a stream.
Is there any way that doesn't involve needing to create a file and also not needing to rewrite (part of) less?
You could consider using POSIX functions popen()
and pclose()
.
You'd use:
FILE *fp = popen("less", "w");
if (fp != NULL)
{
…write output to fp…
pclose(fp);
}
else
…report error…
Note that the pclose()
will wait for less
to exit. If you want to, you can capture the return value from pclose()
and analyze it. See How to detect if shell failed to execute a command after popen()
? for discussion of this.
For those who read this question in the future: there is one little difference to shell
| less
in this code. Apparently, "you can't use Ctrl+C to stop skipping to the end of the output without killing both less and the original program". Source: Piping into pager (less) from C program. It may or may not be a problem.Use
q
instead of Control-C (or whatever your interrupt key is) to exit fromless
. You could consider adding signal handling to your program, but it isn't trivial to get right — you probably end up simulatingpopen()
andpclose()
rather than using them.Actually that's not a problem for me, but after reading your answer, I googled it and found that difference. As I understood it, it's not a problem about closing
less
, but about stopping it from something that it's doing. Fromman less
: "Normally, an interrupt character causes less to stop whatever it is doing and return to its command prompt.". I have never used that command in less before, however. For my usage,popen()
is just perfect. I guess, as you said, that catching the signal in the program and passing the interrupt character through the stream would solve that.