I have a C program, and I'd like to have it filter all its input with tr. So, I'd like to start up tr as a child process, redirect my stdin to it, then capture tr's stdout and read from that.
Edit: here's the code I have so far, which doesn't work. It segfaults instantly, but I don't understand why:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv){
int ch;
int fd = stripNewlines();
while((ch = getc(fd)) != EOF){
putc(ch, stdout);
}
return 0;
}
int stripNewlines(){
int fd[2], ch;
pipe(fd);
if(!fork()){
close(fd[0]);
while((ch = getc(stdin)) != EOF){
if(ch == '\n'){ continue; }
putc(ch, fd[1]);
}
exit(0);
}else{
close(fd[1]);
return fd[0];
}
}
Edit: Turns out this was two things: one was that my header didn't define stdin and stdout as 0 and 1, so I was actually reading/writing to totally random pipes. The other is that for some reason getc and putc don't work how I'd expect, so I had to use read() and write() instead. If I do that, it's perfect:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv){
int ch;
int fd = stripNewlines();
while(read(fd, &ch, 1) == 1){
write(1, &ch, 1);
}
return 0;
}
int stripNewlines(){
int fd[2];
int ch;
pipe(fd);
if(!fork()){
close(fd[0]);
while(read(0, &ch, 1) == 1){
if(ch == '\n'){ continue; }
write(fd[1], &ch, 1);
}
exit(0);
}else{
close(fd[1]);
return fd[0];
}
}
Reading it from stdin
makes life more difficult. If you can live with reading from another FILE *
, it's pretty easy to use popen()
to spawn tr
, and read from the FILE *
it returns.
Edit: if you can't do that, then you need to get into a bit of ugliness. Start with using popen
to spawn tr
with its output redirected. Then use fileno
to get the file numbers associated with that FILE *
and with stdin
. Finally, use dup2
to associate stdin
's file descriptor with the pipe from tr
.
See popen(3)
. Basically all you need to do is
FILE *in = popen("tr <args>", "r");
and then read from in
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With