Is there any analog of PHP's system in C?
man system says, that system return status of the command, but I need the output (like in PHP).
Of course, I can use pipes for this, but is there any standard way?
You can make use of popen and related function as:
// command to be run.
char *cmd = "date";
// open pipe stream.
FILE *fp = popen(cmd,"r");
int ch;
// error checking.
if(!fp) {
fprintf(stderr,"Error popen with %s\n",cmd);
exit(1);
}
// read from the process and print.
while((ch = fgetc(fp)) != EOF) {
putchar(ch);
}
// close the stream.
pclose(fp);
Ideone link
If you need the output of the command, you'd use popen() on Unix (with "r" to indicate that you want to read from the command).
FILE *fp = popen("some -convoluted command", "r");
...check for validity...
...read data from command...
pclose(fp);
Related
I was reading "C: How to program" on chapter 11 (File handling) and came with this algorithm, to append a string to a file named info.txt but it isn't working at all. What am I doing wrong?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{
FILE *fp = fopen("info.txt","w");
char buff[100];
if(fp == NULL){
fprintf(stdout,"Error opening file\n");
exit(1);
}
while(!feof(stdin)){
fprintf(stdout,"Type a string/\nEOF ends input\n");
if(!fgets(buff,sizeof buff,stdin)){
fprintf(stderr,"Error reading string");
exit(2);
}
buff[strcspn(buff,"\n")] = 0;
fprintf(fp,"%s",buff);
}
fclose(fp);
}
I guess you are inserting EOF wrongly. As it is answered here, EOF is inserted using CTRL+D in Unix systems and using CTRL+Z in Windows.
Using exactly your code it works for me, so I guess you are trying to insert EOF using CTRL+C, or another command, which closes the application and leaves the file empty.
Also, if you want it to append always, even if you close the program and open it again, you should use the mode append "a" instead of write "w" [reference]
FILE *fp = fopen("info.txt","a");
No matter what "cmd" string is passed in popen(), it is never FAILING for me
So fp is never NULL even for random "cmd" string.
FILE *fp;
char path[1035];
char cmd = "randomrandomrandom";
fp = popen(cmd, "r");
if (fp == NULL) {
//Handle Error
exit(1);
}
while (fgets(path, sizeof(path)-1, fp) != NULL) {
printf("%s", path);
}
pclose(fp);
popen runs an instance of the shell. Starting a shell normally succeeds. You need to determine if it has terminated successfully. popen itself cannot do that, but pclose can: it returns the status of the child process (or -1 if another error has occurred).
So in order to verify that the command has been executed successfully, one needs to check return values of both popen and pclose.
It seems to be behaving as expected:
http://pubs.opengroup.org/onlinepubs/009695399/functions/popen.html
As you can see, popen only fails when its internal pipe command fails--the stream cannot be opened. For example, all the file descriptors are in use
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);
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");
...
Why does fprintf give different results in the following example programs?
Example 1:
int main(){
FILE *f;
char buf[512];
char name[128] = {"filename"};
f = fopen(name, "w");
fprintf(f, "asdas\n");
fprintf(f, "asdas\n");
while(1){}
return 0;
}
If I terminate this program using CTRL+C, I get an empty file named filename.
However, using
Example 2:
int main(){
FILE *f;
char buf[512];
char name[128] = {"wpa_supplicant.conf"};
f = fopen(name,"w");
while(1){
fprintf(f, "asdas\n");
}
return 0;
}
If I terminate this program using CTRL+C, I get file named filename, and it contains many lines with the string asdas.
Why are the strings not written to the file in the first example, but they are written to the file in the second example?
In the second case, there are enough fprintf calls for the internal buffers to be flushed to disk.
With the first program, if you put a fflush(f) before the while loop, the strings will be written to the file.
#include <stdio.h>
int main(void) {
FILE *f = fopen("filename", "w");
if (!f) {
perror("Failed to open 'filename' for writing");
exit(EXIT_FAILURE);
}
fprintf(f, "asdas\n");
fprintf(f, "asdas\n");
if ( fflush(f) != 0 ) {
perror("Flushing output failed");
exit(EXIT_FAILURE);
}
while(1){}
return 0;
}
Output:
C:\...\Temp> cl file.c
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x64
...
/out:file.exe
C:\...\Temp> file
^C
C:\...\Temp> type filename
asdas
asdas
Keep in mind:
Upon successful completion, fflush() shall return 0; otherwise, it shall set the error indicator for the stream, return EOF, and set errno to indicate the error.
As mentioned in the answer by #SinanÜnür this is indeed an issue with the buffering of data in internal buffers. You need to flush manually in the first case to get that data actually written into the file.
However, FWIW, I just want to add here, you see this behavior because of the abnormal termination of the program by a signal (generated by CTRL+C).
If your program would have ended normally, (for example, by calling exit(), after a large-enough but controlled while() loop), then both the cases would have shown the same behavior, as in that scenario, all the open streams would have been flushed automatically.
The exit() function shall then flush all open streams with unwritten buffered data and close all open streams. Finally, the process shall be terminated ...