How do I retrieve the contents of POPEN in C? - c

I have code that looks like this:
char* buff = malloc(strlen(argv[1])+200);
if (!buff)
{
printf("%s\n", "Error allocating memory!");
return -1;
}
sprintf(buff, "%s%s%s%s", "gcc ", argv[1], " -o ", findChars(argv[1], '.'));
FILE* command = popen(buff, "r");
// NEED TO RETRIEVE OUTPUT OF POPEN
pclose(command);
And this works, but I need to save the output of the POPEN to a char* so I can read it.
(This is in C)

An open pipe is just a FILE*, so any function that can read from a FILE* can do this. For example:
fgets(some_buffer, sizeof(some_buffer), command);
Error handling, repeated reads in case the buffer is too small, all the usual stuff about reading files in C also applies here.

Related

Run a system command with system() and send output

So what I am trying to do is to invoke a system command with system() function and then whatever its output is I would like to take it and send it over to the client (socket connection).
Client can send various messages. It can be ls but it might be even qwerty. I would like to take the ouput and place it in the write() function as a const void* buffer argument. I have seen this topic but I can get it done to work. So far I thought it could go somewhere of these lines but whatever I tried it did not work.
/* buffer is message from the client: ls, ls -l, whatever*/
system(buffer)
fp = popen(buffer, "r");
if(fp == NULL)
printf("Failed ot run command\n");
while(fgets(path, sizeof(path), fp) != NULL) {
//modify output here?
}
pclose(fp);
write(socket_fd, output, strlen(buffer));
You should only use popen() and not system() as it describes in the question you linked.
The path variable in the question you linked seems to be misnamed. It contains the output of the system call. You can rename it to output if you wish.
write() takes the length of the buffer you are sending it. In this case, that will be the length of output, not the length of buffer.
Putting this all together gives the following:
char output[1035];
fp = popen(buffer, "r");
if(fp == NULL)
printf("Failed ot run command\n");
while(fgets(output, sizeof(output), fp) != NULL) {
write(socket_fd, output, strlen(output));
}
pclose(fp);

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");
...

C: Linux command executed by popen() function not showing results

I have the code below that I refer the thread on here to use the popen function
int main(int argc,char *argv[]){
FILE* file = popen("ntpdate", "r");
char buffer[100];
fscanf(file, "%100s", buffer);
pclose(file);
printf("buffer is :%s\n", buffer);
return 0;
}
It outputs:
21 Apr 03:03:03 ntpdate[4393]: no server can be used, exiting
buffer is:
why printf does not output anything? If I use ls as a command, then printf outputs the ls output. what am I doing wrong ntpdate executing?
If I execute the code below (referring the webpage)
#define COMMAND_LEN 8
#define DATA_SIZE 512
int main(int argc,char *argv[]){
FILE *pf;
char command[COMMAND_LEN];
char data[DATA_SIZE];
// Execute a process listing
sprintf(command, "ntpdate");
// Setup our pipe for reading and execute our command.
pf = popen(command,"r");
if(!pf){
fprintf(stderr, "Could not open pipe for output.\n");
return;
}
// Grab data from process execution
fgets(data, DATA_SIZE , pf);
// Print grabbed data to the screen.
fprintf(stdout, "-%s-\n",data);
if (pclose(pf) != 0)
fprintf(stderr," Error: Failed to close command stream \n");
return 0;
}
I get
21 Apr 03:15:45 ntpdate[5334]: no servers can be used, exiting
-�2}�����"|�4#|�-
Error: Failed to close command stream
what are wrongs on the codes above?
Since the output is going to stderr you need to redirect stderr like so:
FILE* file = popen("ntpdate 2>&1", "r");
this will redirect stderr to stdout and so you will see output from both. Second issue fscanf will stop at the first space so you can replace with fgets:
fgets(buffer, 100, file);
As Shafik Yaghmour correctly diagnosed, the output you see from ntpdate is written (correctly) to its standard error, which is the same as your programs standard error.
To get the error messages sent down the pipe, use:
FILE *file = popen("ntpdate 2>&1", "r");
That sends the standard error output from ntpdate to the standard output of the command, which is the pipe you're reading from.
Of course, it looks like using ntpdate isn't going to work well until you've configured something.

Problems reading a binary file with fread function

What I want to do is to read the contents of a '.d' binary file and store them in an array.
So I wrote the following codes:
void viewFile()
{
unsigned char inFileData[SIZE];
char fileName[SIZE];
int numRead;
FILE *inBinFile;
printf("Enter the file name:");
scanf("%s", fileName);
inBinFile = fopen( fileName, "rb");
if(( inBinFile = fopen(fileName, "rb")) == NULL )
{
fprintf( stderr, "Error opening %s\n", fileName );
clearStdin();/*a function to clear stdin*/
mainMenu();/*a function to prompt user input*/
}
numRead = fread( inFileData, sizeof(unsigned char), SIZE, inBinFile );
inFileData[SIZE] = '\0';
printf("U coded data:\n%s\n", inFileData);
printf("%d\n", numRead);
fclose(inBinFile);
return;
}
the output is an unreadable pile of junk. Which part did I do wrong? I don't get it.
also, I wrote my clearStdin function as below:
void clearStdin(void)
{
scanf("%*[^\n]");
scanf("%*1[\n]");
return;
}
compiler reported no errors, but somehow the function call doesn't seem to work exactly the way I wanted. It did clear stdin, but there are always errors closely following wherever this function is called, eg., the mainmenu function to prompt user input.
Please help!! thanks in advance.
"the output is an unreadable pile of junk" - yes, it will be. It's a binary file, it's not meant to be readable as text.
If you want to see binary information in a readable form, think about doing a hex dump of it.
See here for a way to do this.

Is it legal to use freopen and after it fopen ?

Suppose I have a string char* str.
I print it to the buffer in the following way:
char buf[MAX_LEN];
freopen("tmp","w",stdout);
printf("%s\n",str);
fflush(stdout);
fp = fopen(tmp,"r");
if (fp == NULL) return;
fgets(buf,MAX_LEN,fp);
fclose(fp);
fclose(stdout);
May this code cause invalid stream buffer handle?
Is it legal to use freopen and after it fopen?
Based on constrains of my system I can't use fprintf and sprintf.
In theory, it's perfectly legal and works fine. It's even its main use case, according to its man page :
The freopen() function opens the file whose name is the string
pointed to by path and associates the stream pointed to by stream with
it. The original stream (if it exists) is closed. The mode argument
is used just as in the fopen() function. The primary use of the
freopen() function is to change the file associated with a standard
text stream (stderr, stdin, or stdout)
In practice, your code won't work : there are some mistake mainly between "tmp" and tmp & missing headers. This code will work:
#include <stdio.h>
#define MAX_LEN 512
int main() {
const char* str = "data\n";
FILE* fp;
char buf[MAX_LEN];
freopen("tmp","w",stdout);
printf("%s\n",str);
fflush(stdout);
fp = fopen("tmp","r");
if (fp == NULL) return;
fgets(buf,MAX_LEN,fp);
// here, buf gets str's content
fclose(fp);
fclose(stdout);
return 0;
}

Resources