4

I'm trying to write stdin to a file, but for some reason, I keed reading zero bytes.

Here's my source:

#include <stdio.h>
#include <stdlib.h>

#define BUF_SIZE 1024

int main(int argc, char* argv[]) {

    if (feof(stdin))
        printf("stdin reached eof\n");

    void *content = malloc(BUF_SIZE);

    FILE *fp = fopen("/tmp/mimail", "w");

    if (fp == 0)
        printf("...something went wrong opening file...\n");

    printf("About to write\n");
    int read;
    while ((read = fread(content, BUF_SIZE, 1, stdin))) {
        printf("Read %d bytes", read);
        fwrite(content, read, 1, fp);
        printf("Writing %d\n", read);
    }
    if (ferror(stdin))
        printf("There was an error reading from stdin");

    printf("Done writing\n");

    fclose(fp);

    return 0;
}

I'm running cat test.c | ./test and the output is just

About to write
Done writing

It seems zero bytes are read, even though I'm piping lots of stuff.

WhyNotHugo
  • 9,423
  • 6
  • 62
  • 70
  • Hi - The problem is the way you're using "read". Check out this link for correct usage - and a solution: [Read from stdin write to stdout in C](http://stackoverflow.com/questions/10129085/read-from-stdin-write-to-stdout-in-c) – paulsm4 May 26 '12 at 19:42
  • The answer below is correct but there are some style (or otherwise somewhat minor) issues. One is that you can just declare `content` as a char array. No need to `malloc` it. Second, `fread` returns `size_t`, not `int`, so your variable `read` has a different type. You should also rename it on order to avoid using the same name as a global function (`read` is a global function, in fact a system call). Your code closes `fp` without checking for failure. It also reads stdin even if `/tmp/mimail' could not be opened. – James Youngman May 26 '12 at 20:25

1 Answers1

5

You've got the two integer arguments to fread() reversed. You're telling it to fill the buffer once, or fail. Instead, you want to tell it to read single characters, up to 1024 times. Reverse the two integer arguments, and it'll work as designed.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • It's instructive to add a long comment to the source to make it longer than BUF_SIZE. Then the `while` loop gets entered once. – gcbenison May 26 '12 at 19:54
  • @gcbenison Using test.c as an input was just a test; it really does need to read any sort of data from stdin. – WhyNotHugo May 27 '12 at 00:49
  • @ernest-friedman-hill Thanks, my bad, I hadn't payed much attention to that. I'll keep en eye out for this sort of thing in future:) – WhyNotHugo May 27 '12 at 00:49