1

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);
        }
    }
Andrei Olar
  • 2,270
  • 1
  • 15
  • 34
  • You can either redirect simply using `bash`, or you could use `freopen` to redirect `stdout` inside your program. – user4520 Jan 20 '16 at 19:22
  • The most glaring issue is you using `100` as your buffer to `fwrite` (the only correct parameter in that call seems to be the `1`). Is there a reason why you're trying to do this with pipes instead of opening the file as fd 1 like a shell would? – that other guy Jan 20 '16 at 19:22
  • Sorry, typing mistake, but also using this, it does not write to file. It is a task to use pipes. – Andrei Olar Jan 20 '16 at 19:26

4 Answers4

5

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
that other guy
  • 116,971
  • 11
  • 170
  • 194
1

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

Pooya
  • 6,083
  • 3
  • 23
  • 43
  • I'm creating a program that should do what the ">" does. Not use it. – Andrei Olar Jan 20 '16 at 19:23
  • is this helpful? http://stackoverflow.com/questions/584868/rerouting-stdin-and-stdout-from-c – Pooya Jan 20 '16 at 19:26
  • @OlarAndrei, it sounds like what your want is simply to write all of your output routines with `fprintf (fp, "....");` Then in your code, if you read `>` (or `>>`) as input, use `fopen` or `freopen` with the appropriate `mode` and take the file name as the next input following `>` or `>>`. (or `stdout` by default). – David C. Rankin Jan 20 '16 at 19:32
  • `./pipetest` has two `printf()` which I want to redirect to a file and not to my stdout. – Andrei Olar Jan 20 '16 at 19:34
1

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.

user4520
  • 3,401
  • 1
  • 27
  • 50
0

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;
}
nsilent22
  • 2,763
  • 10
  • 14