C - fgets weird behaviour - c

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

Related

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);
}

C programming: Reading from file and printing to console

Good evening,
I know there's similar questions, which I have been sifting through, but this particular issue seems to be unique.
I am attempting to figure out how to simply read a text file into a string, and then write the string to standard output. I tried this code, but nothing is happening in the console when I call puts(). The file.txt generates properly with "hello" written, but the last if statement doesn't seem to work for some reason since it does not reach my test condition. How can I make this functional?
This was the code given by many, many examples online, only slightly modified:
#include <stdio.h>
int main()
{
FILE *fp;
char str[60];
fp = fopen("file.txt","w+");
fprintf(fp,"%s","hello");
if(fp==NULL){
perror("Error opening file");
return(-1);
}
if (fgets (str, 60, fp)!=NULL)
puts(str);
printf("%s","test");
fclose(fp);
return 0;
}
By the time you call fgets(), the file pointer is already at end of file. Add a call to rewind(fp) before your fgets().
Oh, also when you're opening the file, put your check for fp==NULL before the call to fprintf().
After you have written the file, you have to fclose() the fp and re-fopen() the file for reading.

Reading a C file, read an extra line, why?

I don't know exactly why a file pointer reads an extra line from a file, specifically the last line, here is the code:
FILE *fp ;
fp = fopen ("mac_ip.txt", "r") ;
int mac;
char *ip = (char *) malloc(15);
while(!feof(fp)){
fscanf(fp,"%i",&mac);
fscanf(fp,"%s",ip);
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
and the file has exactly 20 lines, but the line 20, is printed twice.
Which is the error?
Thanks in advance.
Because after reading the last two values, you still haven't hit EOF. So the loop goes on. In the next pass of the loop, fscanf actually does not read the last line for the second time like it appears, the fscanfs fail, but the printfs print out the values from the previous pass of the loop.
feof does not "know" it's at the end of file until you try to read some more. Since fscanf tells you how many items it got, you can use this simple trick:
for(;;){
if (fscanf(fp,"%i%s", &mac, ip) != 2) break;
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
After you have done the two reads on the twentieth line, you have got to the end of the file but the system doesn't know this. feof will only trigger when you try to get past the end of the file, not when you are exactly on it ...
Also, you may have a line-end (CR or CR-LF) on the 20th line which it will only get past with another attempted read.
The solution is to read the line in one go (there is a specific C command for this) and then parse that to get your data. If the whole-line read fails, then you've got to the end.
Your code resembles to the following example
#include <stdio.h>
int main(void)
{
char buffer[256];
FILE * myfile;
myfile = fopen("some.txt","r");
while (!feof(myfile))
{
fgets(buffer,256,myfile);
printf("%s",buffer);
}
fclose(myfile);
return 0;
}
from
http://www.friedspace.com/feof.html
You better test for fscanf return value before printing result. I bet that in the last iteration of your loop, fscanf calls fail and you print the last returned results.
FILE *fp ;
int mac;
char ip[15];
fp = fopen ("mac_ip.txt", "r") ;
if (!fp) return;
while(1){
if (fscanf(fp,"%i",&mac) < 1) break;
if (fscanf(fp,"%s",ip) < 1) break;
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
fclose (fp);
fscanf() returns the number of assignments it mad (or -1 on eof). By using the return value, you don't need the eof() function. BTW I don't think you can read a MAC address into an int. Maybe you need to read that into a string, too ?
Explanation: feof() does not do what the OP expects. feof() should only be inspected after one of the file operations failed. In most cases you don't need feof().

Can I parse ngrep's output with popen()?

I tried running this code, but nothing is ever shown. (Yes, I ran it as root) If I can't get ngrep's output I guess I'll try to figure out how to use libpcap with c++ although I haven't been able to find any good examples.
int main(void)
{
FILE* fproc = popen("ngrep -d wlan0 GET");
char c;
do {
printf("%c", fgetc(fproc));
} while (c!=EOF);
}
So what about this code causes nothing to be show, and what do you suggest to easily parse ngrep's output, or some other way of capturing GET requests, maybe with libpcap
I see the possible potential problems:
You have no open mode for the popen call? Leaving this off is likely to result in either a core dump or a random value of the stack deciding whether it's a read or write pipe.
The c variable should be an int rather than a char since it has to be able to hold all characters plus an EOF indicator.
And, you're not actually assigning anything to c which would cause the loop to exit.
With that do loop, you're trying to output the EOF to the output stream at the end. Don't know off the top of my head if this is a bad thing but it's certainly not necessary.
Try this:
int main(void) {
int ch;
FILE* fproc;
if ((fproc = popen("ngrep -d wlan0 GET", "r")) < 0) {
fprintf (stderr, "Cannot open pipe\n");
return 1;
}
while ((ch = fgetc (fproc)) != EOF) {
printf ("%c", ch);
};
pclose (fproc);
return 0;
}
You should also be aware that the pipe is fully buffered by default so you may not get any information until the buffer is full.

problem using fprintf

I'm trying to print to a text file numerous variables yet it doesn't work.
I checked and verified that i write it in the correct syntax.
I also checked the return value and it's positive therefore i know it did write to the file, however when i open the file it's empty.
I would be happy for some help.
This is the code:
I initiate DynsaleDayPtr in the main:
FILE* DynsaleDayPtr = CreateTextFiles("sale_day.txt");
Create function:
FILE* CreateTextFiles (char* fileName)
{
FILE* saleFilePtr=NULL;
if((saleFilePtr=fopen(fileName,"a+"))==NULL)
printf("File couldn't be opened\n");
return saleFilePtr;
}
The call to the function TextAddSale is done from a function that is called in the main:
TextAddSale(DynSaleDayPtr,dynNumOfRecords);
Bool TextAddSale (FILE* DynsaleDayPtr, int* dynNumOfRecords)
{
char id[6];
char name [50];
char priceChar[20];
char* tmp = NULL;
int price=-1;
DynamicRecord * newRec=NULL;
scanf("%s%s%s",id,name,priceChar);
newRec = (DynamicRecord *)malloc(sizeof(DynamicRecord));
if (newRec == NULL)
return False;
tmp = (char*)malloc(strlen(name)+1);
if (tmp == NULL)
{
free (newRec);
return False;
}
strcpy(tmp,name);
newRec->productName = tmp;
strcpy(newRec->productId, id);
newRec->productPrice=atoi (priceChar);
if (fprintf(DynsaleDayPtr,"%d %s %s %d", strlen(newRec->productName),
newRec->productId, newRec->productName, newRec->productPrice)>0)
{
*dynNumOfRecords=(*dynNumOfRecords)+1;
return True;
}
}
thanks!
You need to flush the stream.
fflush(FILE*);
Of course, you have to close the stream if you have done with it.
fclose(FILE*);
Agree with #pmg - try something like this:
FILE *pFile = fopen("foo.txt","w");
if (pFile==NULL)
bad();
fprintf(pfile,"Hello world\n");
fclose(pfile);
make that work first - then fix whatever's wrong in the big app -
A thought:
scanf("%s%s%s",id,name,priceChar);
the above statement is a bit dodgy since you haven't said how many bytes
should go in each string.
better to use fgets() then parse the string retrieving the individual values
or create a better format specifier.
If the above statement causes a memory overwrite the rest of your program
could malfunction causing things like what you describe.
fprintf() most likely uses buffered output. Therefore, you should either fflush() the DynSaleDayPtr stream or, better yet, print a newline to the file. The latter has the added benefit of making the file contents actually readable...
Also, don't forget to close() the stream when you're finished with writing. This will also render fflush() unnecessary.

Resources