1

I have written a program to practice using fread. I am passing a command to popen and reading the output using fread and storing into an uninitialised char array. Finally I am printing the contents of the array as well as writing it into another file. The print (output in the stdout) works fine but when I check the contents of the file, it has so many junk things after the actual output. Any reason why it works well in stdout? Here is my code:

#include <stdio.h>

void fread_s(char *res, int res_size,char *cmd)
{
    char *r;
    int size;
    FILE *fp=popen(cmd,"r");
    if(fp==NULL)
            return;
    size=fread(res,res_size,1,fp);
    pclose(fp);
}

int main()
{
    char cmd[500];
    fread_s(cmd,sizeof(cmd),"ls -lh i*");
    puts(cmd);
    FILE *fp=fopen("opfile","a+");
    if(fp==NULL)
            return;
    fwrite(cmd,sizeof(cmd),1,fp);
}
3
  • 1
    fgetss -> fread_s? Commented Sep 2, 2016 at 16:59
  • @md5 sorry typo. Edited it.Thanks Commented Sep 2, 2016 at 17:02
  • @md5 fgets() wouldn't work if ls output has newlines in it. Commented Sep 2, 2016 at 17:23

3 Answers 3

4

You are seeing the unwanted side effects of a char array that is not null terminated. Change:

size=fread(res,res_size,1,fp);

to

size=fread(res,res_size,1,fp);
res[size] = '\0';

Also, make sure that res_size is one less than sizeof(cmd). Otherwise, you take the chance that size is sizeof(cmd) and hence,

res[size] = '\0';

will modify the array using an out of bounds index.

Change

fread_s(cmd,sizeof(cmd),"ls -lh i*");

to

fread_s(cmd,sizeof(cmd)-1,"ls -lh i*");

or change

size=fread(res,res_size,1,fp);

to

size=fread(res,res_size-1,1,fp);
Sign up to request clarification or add additional context in comments.

1 Comment

size=fread(res,res_size-1,1,fp); seems correct, it would make fread_s() a pretty inconsistent function to expect: fread_s(cmd,sizeof(cmd)-1,"ls -lh i*"); meaning it would overwrite the end of the size passed in by 1 char.
2

Code has size=fread(res,res_size,1,fp), but does not use size, which indicates the number of elements read.

The following works even if the data read contains embedded null characters.

// Return the number of elements read
size_t fread_s(char *res, int res_size,char *cmd) {
  char *r;
  size_t size;
  FILE *fp = popen(cmd,"r");
  if (fp == NULL) {
    return 0;
  }
  size = fread(res,res_size,1,fp);
  pclose(fp);
  return size;
}

Only write valid number of elements.

int main(void) {
    char cmd[500];
    size_t size = fread_s(cmd,sizeof(cmd),"ls -lh i*");

    // puts(cmd);
    fwrite(cmd, size, 1, stdout);

    FILE *fp=fopen("opfile","a+");
    if(fp==NULL) {
            return -1; // Add value to return
    }
    fwrite(cmd, size, 1, fp);
    fclose(fp); // add fclose
}

Comments

1

When you write in standard output, you write a string using puts. The string is not null terminated, but there's a strong probability that puts encournters a null char in the junk chars. Some junk may be printed, but not all, since a zero can be encoutered.

(this question looks very much like that one, just saw that: C Language: popen() with fread()?)

When you write to your file, you will the whole 500 chars, including junk chars all the way (500 chars)

To get the same behaviour (but still some probable junk):

fwrite(cmd,strlen(cmd),1,fp);

or

fputs(cmd,fp);

but you have to null terminate your string after reading the output of popen.

4 Comments

The null termination ensure that no junk chars are printed afterwards. where is it null terminated? The suggestions won't because cmd isn't null terminated either.
In this case cmd is not null-terminated since fread() doesn't null terminate the binary bytes written.
Okay, you're right. But if there's a null char just after puts or not that far, output will stop. Some junk may be visible or not depending how far the zero is.
I have updated my answer. That could explain the junk not being displayed, but that's mere luck.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.