save stderr with _popen to a variable in C on Windows 10 - c

When I use something like
char result[1000] = "";
char psBuffer[1000];
FILE* pPipe = _popen(command, "rt");
while(fgets(psBuffer, 1000, pPipe) != NULL)
{
strcat(result, psBuffer);
}
printf(result);
Either when command = "echo 123" or command = "ErrorCommand" result only gets the value of the stdout, it never gets the stderr. At first it looks like it does since you get the error printed on your CMD but if you'll save the output and print it or save it to a file you'll see that it only contains the stdout.
Is there a way to make result also include the stderr?

Related

how to echo std output exactly in C

I'm making essentially a terminal wrapper. I want my program to read from stdin, and for any inputs that come in, echo it EXACTLY the way it is, even if it's wrong.
Right now, I'm doing:
FILE *output = popen(buffer, "r");
memset(buffer, '\0', BUFF_SIZE * 2);
while (fgets(buffer, sizeof(buffer), output) != 0)
{
printf("%s", buffer);
memset(buffer, '\0', BUFF_SIZE * 2);
}
pclose(output);
}
where I'm calling shell commands using popen, but in certain situations, for example, when the command is not found, the output returned by using popen won't be exactly the same compared to when using the terminal without the wrapper. For example, if I input $ asd, linux terminal will return
No command 'asd' found, but there are 24 similar ones
asd: command not found
whereas popen will return:
sh: 1: asd not found
I would like to have the default terminal response rather than what popen returns, would this be possible? If so, how?

get the text printed due to executing cmd command in c

I have a binary file which prints the result instead of returning the value, if I execute it using cmd I am getting printed text, I managed to execute it from C code but it seems like I can not get the text it usually prints to be stored in a variable I can use later for further decisions.
I do not have that much of experience in C and I googled a lot.
I came across the idea of using clip but my cmd is saying that clip command can not be found.
any help or ideas would be appreciated.
The correct function pair to use on POSIX systems is popen() and
pclose(). You can perhaps use Microsoft's _popen() and
_pclose() unless the warning 'This API cannot be used in applications that execute in the Windows Runtime' matters to you.
You would use it more or less like this. I've had to invent the name of the command you wish to execute since the question doesn't specify that. I chose ./example.exe as the name — and I'm assuming it needs no arguments.
char cmd[] = "./example.exe";
FILE *fp = popen(cmd, "r");
if (fp != NULL)
{
char buffer[4096];
size_t nbytes;
while ((nbytes = fread(buffer, sizeof(buffer), sizeof(char), fp)) != 0)
{
…process nbytes of data…
…it is not a null-terminated string unless you add the null byte…
}
pclose(fp);
}
else
{
…report error for failure to execute command…
}
You can use the system function from <stdlib.h> to run the command you want. To get the command's output, you modify your command like in this question to save the command's output to a file. Then you can use the file I/O functions in <stdio.h> to process the command output.
In Linux, you may do command substitution and pass its result as arguments to the program, Something like this
./your_program "$(/path/to/your/binary/file)"
Suppose your main is
int main(int argc,char* argv[]){
.
.
return 0;
}
Acess the arguments like argv[1] and so.
Here the $(command) does the substitution and it passes the printed values from the binary as arguments to the pgm. Hope this helps.
Use snprintf function. For e.g.
snprintf(cmdbuff, BUFFER_LEN, "dmidecode --type 17 | grep -i Size | grep -o '\\<[0-9]*\\>' | paste -sd+ | bc");
Here cmdbuff is character array where command will be stored , BUFFER_LEN is a size of the character array
Then use popen and fgets to get the output of command into some buffer as shown below
if((fd = popen(cmdbuff,"r")) != NULL)
{
fgets(buffer, BUFFER_LEN, fd);
sprintf(vnfc_configured_memory, "%s", buffer);
vnfc_configured_totalRAM = atof(vnfc_configured_memory);
}

Redirect in Shell (C)

I'm trying to write a simple shell, it all works except the redirect with '>'. I was advised to parse my input string from the user using a delimiter of ">". The output string then has two elements, output[0] will be the entire command that user enters including the arguments. output[1] will be the filename.
My issue is that it creates the file specified by output[1], however it writes nothing to it! Even if I put a printf to stdout, it writes to the terminal instead.
else if(*delim == '>'){
int f = open(output_str[1], O_WRONLY|O_CREAT|O_TRUNC, 0666);
int stdout_sv = dup(1); // Saving the current stdout descriptor for restoring later.
if(errno != 0){
perror("");
}
dup2(f,1);
execvp(output_str[0], output_str);
printf("Sample Line to file.");
dup2(stdout_sv, 1); // Restoring stdout
close(f);
}
This results in the following output:
[04/04 15:55]# ls > test.txt
output_str[0] = ls
output_str[1] = test.txt
Sample Line to file.[04/04 15:55]#
I'm really confused as to why the stdout isn't being redirected towards the output file(test.txt). I mean the output file is correct.
Note: I realise there is a space before test.txt, I have tried parsing with " >" which removes the space in the output_str[1], the file still ends up empty.

It possible to replace file to buffer while pass input to an exe as shell command?

I'm using "system" API calls to run shell commands in my C program, now
there is case where I want to redirect the output generated by an executableto a buffer instead of a file (named recv.mail)
An example of how I write the output to the file:
cmd[] = "mda "/bin/sh -c 'cat > recv.mail'";
system (cmd);
Similarly I want to replace input taken from the file (send.mail) with input taken from a buffer.
An example of how I take input from a file:
cmd[] = "msmtp < cat send.mail";
system (cmd);
NOTE: The send.mail and recv.mail files have formatted data.
Are pipes a better replacement?
Can anyone suggest another alternative?
popen/pclose may do what you want:
FILE *f = popen("program to execute", "r");
if (NULL != f)
{
char buffer[128];
while (fgets(buffer, sizeof buffer, f)
{
printf("Read from program: '%s'\n", buffer);
}
pclose (f);
}
popen/pclose again:
FILE *f = popen("program to execute", "w");
...

How to redirect stdin back within C program (under Windows)

I have a simple C program called a.exe, with main loop like this:
void input_console()
{
printf(">>");
char in_string[256] = {0};
fgets(in_string, 256, stdin);
parse(in_string);
}
It works like this when I start it and enter commands from my keyboard:
>>say_hello
Hello!
>>say_goodbye
Goodbye!
>>
no command found
>>blablablabla
Command blablablabla not recognized
>>
no command found
etc.
Now I would like to read input from file instead of the keyboard so I prepared in.txt like this:
say_hello
say_goodbye
blablabla
After running a.exe < in.txt (this is Windows) I get:
>>Hello!
>>Goodbye!
>>Command blablabla not recognized
>>no command found
>>no command found
>>no command found
... (infinite loop)
I guess fgets keeps getting EOF here and my parser reaction to EOF is to print no command found message.
What I would like to do is to be able to return the input stream back to stdin once the input file I used with "<" redirection is over so I can use keyboard again. Something like:
if (in_string[0] == EOF)
stop_using_a_file_as_stdin_and_go_back_to_normal();
Is there any way to do that ?
EDIT:
Answer given by Harry Johnston in the comments works:
freopen("CON", "r", stdin);
or:
freopen("CONIN$", "r", stdin);
Instead of using input redirection, you could pass the filename as a command-line argument and open it yourself.
int main (int argc, char **argv){
FILE *input = stdin;
if (argc > 2){
input = fopen(argv[1], "r");
}
// ...
Then you can switch back easily.
input = stdin;

Resources