I have this C code snippet which runs on a coreOS machine:
char db[512];
snprintf(db, 512, "%s %s", <some command>, <args of the command>);
FILE* pipe = popen(db, "r");
if (!pipe) {
return NULL;
}
char buf[256];
while (fgets(buf, sizeof(buf), pipe) != NULL) {
<DEBUG POINT 1>
<some code utilising buf>
}
<DEBUG POINT 2>
Now the command that is being executed and which is streaming to the Pipe in eventually calling a python code which returns None(Null) with the given argument.
The problem that I'm facing is that fgets is not able to handle the response and the program crashes when it tries to execute fgets() on the Pipe. What I mean is that on reaching while(), my program exits and is not able to reach either DEBUG POINT 1 or 2. I have tried searching for possible solutions but am not able to find anything.
Another interesting thing is when I run the same code on a Amazon Linux Machine, it works fine and I get the desired behaviour.
Can someone please guide me in the right direction.
Related
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);
}
anyone know how I can fix this?
char bash_cmd[256] = "curl";
char buffer[1000];
FILE *pipe;
int len;
pipe = popen(bash_cmd, "r");
if (NULL == pipe) {
perror("pipe");
exit(1);
}
fgets(buffer, sizeof(buffer), pipe);
printf("OUTPUT: %s", buffer);
pclose(pipe);
The above code snippit is returning the following:
OUTPUT: (�3B
instead of what it should be returning which is:
curl: try 'curl --help' or 'curl --manual' for more information
Something is wrong, I can't figure out what. When I replace "curl" with, say, "ls -la" it works fine, but for whatever reason only when I use curl, it doesn't properly save the output into buffer. What could I do to fix this?? thanks in advance
Also, replacing "curl" with the full path to curl, (/usr/bin/curl) doesn't work either. ;(
When I run your code, I find that the output is indeed approximately what you describe, but that the output you expect is also printed immediately previous. It seems highly likely, therefore, that curl is printing the usage message to its stderr rather than to its stdout, as indeed it should do.
You do not check the return value of fgets(); I suspect you would find that it is NULL, indicating that the end of the stream occurred before any data was read. In that case, I do not think fgets() modifies the provided buffer.
If you want to capture curl's stderr in addition to its stdout, then you can apply I/O redirection to the problem:
char bash_cmd[256] = "curl 2>&1";
That would not work (directly) with the execve()-family functions, but popen() runs the given command via a shell, which should handle the redirection operator just fine.
For general purposes, however, combining curl's output and error streams may not be what you want. If both real output and real diagnostics were emitted then they would be intermingled.
The output you expect from curl is going to stderr not stdout. In fact nothing is written to stdout. The output you are printing is the uninitialized contents of the buffer.
Your code should check the return value of fgets, which will be null if no characters were read (or if an error occurred).
It may be a stupid issue but its been a few hours I've been looking around to fix that and it drives me crazy.
That little code works perfectly fine if the fgets line is commentated (as provided).
As soon as I remove the comment the whole function will NOT do anything at all. My process jut freezes - even the printf before the fgets isnt executed.
void RetirerTransaction(char* filePath, char* transaction) {
FILE* f;
FILE* result;
char tempStr[128];
char line[100];
printf(">>%s<<",filePath); // Just to check everything is ok
strcpy(tempStr,"grep -v \"");
strcat(tempStr,transaction);
strcat(tempStr,"\"");
strcat(tempStr,filePath); // tempStr = grep -v "XXX" myfile
result = popen(tempStr, "r");
/*
if (fgets(line,100,result)) {
printf("OK");
}
*/
}
Thank you in advance.
You miss a space between the closing quote of the pattern and the file parameter for grep. That makes the whole thing including the filename be taken as the pattern.
By default, grep reads from standard input. It blocks trying to read from stdin because it doesn't have a file parameter.
Add the space like this and you'll be fine:
strcat(tempStr,"\" ");
Check the code below.Please add check for the popen return value. If popen fails and you are trying to do a fgets() then it might cause crash.
result = popen(tempStr, "r");
if(result == NULL)
return;
else
fgets(line,100,result);
In Linux, I am finding pid of process by opening pipe with "pidof process_name" command and then reading it's output using fgets function. But it fails to find pid once in a while. Below is my code for finding pid of my process.
int FindPidByProcessName(char *pName)
{
int pid = -1;
char line[30] = { 0 };
char buf[64] = { 0 };
sprintf(buf, "pidof %s", pName);
//pipe stream to process
FILE *cmd = popen(buf, "r");
if (NULL != cmd)
{
//get line from pipe stream
fgets(line, 30, cmd);
//close pipe
pclose(cmd); cmd = NULL;
//convert string to unsigned LONG integer
pid = strtoul(line, NULL, 10);
}
return pid;
}
In output sometimes pid=0 comes even though process is available in "ps" command output.
So, I try to find root cause behind this issue and i found something like input/output buffer mechanism is may creating issue in my scenario.
So I try to use sync() function before opening popen() and strangely my function starts working with 100% accuracy.
Now sync() function is taking too much time(approximately 2min sometime) to complete its execution which is not desirable. So i try to use fflush(), fsync() and fdatasync() but these all are not working appropriately.
So please anyone tell me what was the exact root cause behind this issue And how to solve this issue appropriately?
Ok, the root cause of the error is stored in the errno variable (which btw you do not need to initialize). You can get an informative message using the fucntion
perror("Error: ");
If u use perror the variable errno is interpreted and you get a descriptive message.
Another way (the right way!) of finding the root cause is compiling your program with the -g flag and running the binary with gdb.
Edit: I strongly suggest the use of the gdb debugger so that you can look exactly what path does your code follow, so that you can explain the strange behaviour you described.
Second Edit: Errno stores the last error (return value). Instead of calling the functions as you do, you should write, and check errno immediately:
if ((<function>) <0) {
perror("<function>: ");
exit(1);
}
Ok so i am writing a C program. The program is simple enough, when i run the program i give it a few parameter Ex ./proj1 cat hat bat, so then it asks me to input a list of words the program gives counts of how many times "cat", "hat", and "bat" occurs in that list.
I have the program working great.
Example
./pro1 cat hat bat
cat
.
(the program recognized a "." as the end of input)
Result:
cat:1
hat:0
bat:0
ok so my program runs perfectly in every test case i can think of, but I have to pass a series of tests that my professor has mas made.
here is the code of that test.
char *args[] = {"./main", "cat", "hat","bat",NULL};
char *result[] = {"Looking for 3 words\n",
"Result:\n",
"cat:1\n",
"hat:0\n",
"bat:0\n"};
FILE *out;
FILE *test;
test=fopen("test","w");
int i;
char *buffer=malloc(100*sizeof(char));
out = fopen("smp0.in", "w");
fprintf(out, "cat\n");
fprintf(out, ".\n");
fclose(out);
freopen("smp0.in", "r", stdin);
freopen("smp0.out", "w", stdout);
quit_if(main(4, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("smp0.out", "r");
for (i = 0; i < 5; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
ok so sending the quit_if() is the method that makes it fail. specifically
quit_if(strcmp(buffer, result[i]));
My output when i run the program is exactly as described. But between freopen() diverting stdout to a file and then reading it back it has changed somehow.
Result:
cat:1
hat:0
batÿ:0
is what the output becomes, but it is not like that before the file write and read, and for some reason it is always that weird y character.
any advice would be greatly appreciated.
Sorry for not posting more code but it's because it is a school project.
I am confident that it is the test that is wrong in some way and not my code, fixing the test is part of the project as well.
See this answer to a previous question:
https://stackoverflow.com/a/4906442/2009431
It seems that when the dot is read back in from your stdin file, it has an EOF token appended (makes sense) that would not normally be part of the user's input. Then, somehow (not sure since we can't see your code) your main() function is appending that EOF character onto "bat" in the form of that weird y character (see linked answer for details on why).
If I'm right, maybe this could be considered a bug in the test?