Converting output from _popen to a string

New to C++ so please be gentle. I am trying to write a function that runs a command (such as ipconfig) using popen and then saves the output to a string. I can get the command to execute and display the results correctly, however, all attempts to convert psBuffer to a string so I can return the output are failing. A non-printable ascii character is displayed instead. I thought this may be due to not setting the array to be null (blank?) so I have tried that as well but same result. Everything I have read said it is as easy as doing something like std::string str(s) where s is something like char* s, but not sure that is applicable in this case. Any help provided would be much appreciated at this point.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
std::string runCmd(std::string command)
{
	
	const char* execute = command.c_str();
	char psBuffer[1024] = { 0 };
	FILE   *pPipe;

	if ((pPipe = _popen(execute, "rt")) == NULL)
		exit(1);

	/* Read pipe until end of file, or an error occurs. */
	while (!feof(pPipe))
	{
		if (fgets(psBuffer, sizeof(psBuffer), pPipe) != NULL)
		{
			printf(psBuffer);

		}
	}


	/* Close pipe and print return value of pPipe. */
	_pclose(pPipe);

	printf("before conversion\n");
	printf(psBuffer);
	
	std::string cmdResult(psBuffer);
	printf("after conversion: %s\n", cmdResult);
	
	return cmdResult;

}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
std::string runCmd(std::string command)
{
    // ...

    std::string cmdResult ;	

    /* Read pipe until end of file, or an error occurs. */
    while (!feof(pPipe))
    {
        if (fgets(psBuffer, sizeof(psBuffer), pPipe) != NULL)
        {
            // printf(psBuffer); // ideally, do not do this (possible vulnerability)
            printf( "%s", psBuffer ) ; // safer

            cmdResult += psBuffer ;
        }
    }

    // ...

    // std::string cmdResult(psBuffer); // *** remove

    // ...

    return cmdResult;
}
printf("after conversion: %s\n", cmdResult); cmdResult is std::string. It cannot be passed to printf.

Additionally, if there is an error when reading from pipe, you will have an infinite loop as eof is never set.

Also you need to take into account if command output does not fit into buffer: you will lose everything, but last read results.

printf(psBuffer); — a lot of woe if result happens to contain percent sign.

Try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::string runCmd(const std::string& command)
{
    char psBuffer[256];
    FILE*   pPipe;
    std::string result;

    if ((pPipe = _popen(command.c_str(), "rt")) == NULL) {
        std::cerr << "Cannot start command\n";
        return "";
    }
    while (fgets(psBuffer, sizeof(psBuffer), pPipe) != NULL)
        result += psBuffer;

    if(!feof(pPipe))
        std::cerr << "Error executing command\n";

    _pclose(pPipe);
    return result;
}
Last edited on
Thanks guys, this was really informative and solved the issue. Appreciate it.
Topic archived. No new replies allowed.