5

I'm trying to execute a command line from my C code, but when I get to the fgets() function, I got a NULL error.

void executeCommand(char* cmd, char* output) {
    FILE *fcommand;
    char command_result[1000];
    fcommand = popen(cmd, "r");
    if (fcommand == NULL) {
        printf("Fail: %s\n", cmd);
    } else {
        if (fgets(command_result, (sizeof(command_result)-1), fcommand) == NULL)
             printf("Error !");
        strcpy(output, command_result);
    }
    pclose(fcommand);
}

And my command is:

java -jar <parameters>

Why do I have a NULL result from fgets, despite that when I try to execute the same command in a terminal, it works as expected.

hyde
  • 60,639
  • 21
  • 115
  • 176
TheForbidden
  • 1,533
  • 4
  • 22
  • 30

1 Answers1

4

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A '\0' is stored after the last character in the buffer.

In short, the popen() is doing a fork() and you're trying to read from the pipe before the program evoked by cmd has produced output, therefor there is no data on the pipe and the first read on the pipe will return EOF, so fgets() returns without getting data. You either need to sleep, do a poll or do a blocking read.

K Scott Piel
  • 4,320
  • 14
  • 19
  • a sleep? where? between the popen and the fgets ? – TheForbidden Apr 08 '13 at 15:23
  • 2
    Yes... but a sleep is the worst solution because it is either (a) at risk of waking up before the output is ready or (b) keeping the user waiting long after the output was ready. The best answer is to do a blocking read on the pipe. – K Scott Piel Apr 08 '13 at 15:25
  • 1
    Are you sure? My understanding is that the read would block until there is data in the pipe. And the read will only return EOF when the other program closes its end of the pipe. I thought that was the whole point of pipes? I could be wrong though. For the original question. I suspect the exec is failing. Does you program have the same environment as the command line? No messing with path etc? – Sodved Apr 08 '13 at 15:40
  • fgets() is a non-blocking read... regardless of the stream it is reading from. – K Scott Piel Apr 08 '13 at 15:42
  • @Sodved yeah it works perfectly in another standalone c file, even on a terminal. – TheForbidden Apr 08 '13 at 15:45
  • @KScottPiel No the sleep didn't work, actually popen returns a success return code, so there is no trouble with reading the command and executing it. The blocking read either didn't work. – TheForbidden Apr 09 '13 at 11:52