Reputation: 2358
I want to redirect the output of a program to a file. How can I do this? At the moment my file doesn't get created, I can only print the output to my console.
int fd[2];
int processId;
int output;
char filename[] = "output.txt";
if((output = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) == -1){
fprintf(stderr, "Unable to create/open file '%s'\n", filename);
return 1;
}
if(pipe(fd) == -1){
fprintf(stderr, "Error creating pipe\n");
return 2;
}
if((processId = fork()) == -1){
fprintf(stderr, "Error forking\n");
return 3;
}
if(processId == 0){
int newFD = dup(STDOUT_FILENO);
char newFileDescriptor[2];
sprintf(newFileDescriptor, "%d", newFD);
dup2(fd[1], output);
close(fd[0]);
execl("./pipetest", "pipetest", newFileDescriptor, NULL);
}else{
close(fd[1]);
char c[10];
int r = read(fd[0], c, sizeof(char) * 10);
if(r > 0){
fprintf(stderr, "PIPE INPUT = %s", c);
fwrite(c, 1, sizeof(c), output);
}
}
Upvotes: 1
Views: 5854
Reputation: 2863
Here's simples example how to do this:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(void) {
int out = open("/tmp/output.txt", O_WRONLY | O_CREAT, 0644);
if (out == -1) {
perror("open:");
return -1;
}
int r;
r = close(1); /* this closes stdout */
if (r != 0) {
perror("close:");
return -1;
}
r = dup2(out, 1); /* this duplicates your file descriptor to stdout */
if (r == -1) {
perror("dup2:");
return -1;
}
printf("this should go to the output file\n");
return 0;
}
Upvotes: 0
Reputation: 123680
A good start is not ignoring compiler warnings:
test.c: In function ‘main’:
test.c:42:13: warning: passing argument 4 of ‘fwrite’ makes pointer from integer without a cast [enabled by default]
fwrite(c, 1, sizeof(c), output);
^
In file included from test.c:1:0:
/usr/include/stdio.h:715:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘int’
extern size_t fwrite (const void *__restrict __ptr, size_t __size,
^
int
and FILE*
are not interchangable. If you use open
, write with write
. If you use fopen
, write with fwrite
.
Additionally, you never modify stdout of your process. Instead you modify output
, which doesn't make sense. Here are the minimum changes to your code to make it work:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd[2];
int processId;
int output;
char filename[] = "output.txt";
if((output = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) == -1){
fprintf(stderr, "Unable to create/open file '%s'\n", filename);
return 1;
}
if(pipe(fd) == -1){
fprintf(stderr, "Error creating pipe\n");
return 2;
}
if((processId = fork()) == -1){
fprintf(stderr, "Error forking\n");
return 3;
}
if(processId == 0){
int newFD = dup(STDOUT_FILENO);
char newFileDescriptor[2];
sprintf(newFileDescriptor, "%d", newFD);
dup2(fd[1], STDOUT_FILENO); // You want to modify STDOUT_FILENO
close(fd[0]);
execl("/bin/echo", "echo", newFileDescriptor, NULL); // switched to echo
}else{
close(fd[1]);
char c[10];
int r = read(fd[0], c, sizeof(char) * 10);
if(r > 0){
fprintf(stderr, "PIPE INPUT = %s", c);
write(output, c, r); // use write instead of fwrite
}
}
}
Here's the result of running it:
$ gcc test.c -o test
$ ./test
PIPE INPUT = 6
$ cat output.txt
6
Upvotes: 5
Reputation: 3457
You can use freopen
, it's probably the simplest way:
if (!freopen("out.txt", "w", stdout))
{
// failed to open the file stream, handle the error
}
You can then just use printf
to write to that file. You can do the same with stderr
, but that's probably a bad idea - by definition stderr
is used to report errors, and from what I know the convention is to have it output to console.
Upvotes: 1
Reputation: 6136
The easiest way is to do this at the bash by calling:
./myprogram > output.txt
This will redirect all of the outputs to output.txt
Upvotes: 1