LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   string search in C (https://www.linuxquestions.org/questions/programming-9/string-search-in-c-103308/)

h/w 10-13-2003 12:56 AM

string search in C
 
hey all.

im trying to search for a string within another, so i looked up strstr().

Code:

void
chkiwconfig (char *ssid)
{
        printf ("check iwconfig here for %s\n", ssid);
        int ret;
       
        FILE *fp;

        char *temp = "test";

        char iw_result[1024], *cmp;

        // open
        fp = fopen ("iwcfgdump", "w+");
       
        // dump
        system ("/sbin/iwconfig > iwcfgdump 2>/dev/null");

        // read
        while ( (ret = fread (iw_result, 80, 8, fp)) != 0) ;

        // search for ssid in iw_result
        if ( (cmp = strstr (iw_result, temp)) == NULL)
                printf ("OID was not set\n");
        else
                printf ("OID set\n");

        fclose (fp);

        //delete dump
        unlink ("./iwcfgdump");

}

so, im looking for the string "test" within the string passed to this function (ssid). it doesnt seem to work (yes the string being compared with has the "test" string in it)m, and the else{} is never taken.

why would this be?

thanks in advance.

Hko 10-13-2003 02:46 AM

Re: string search in C
 
Quote:

Originally posted by h/w
Code:

        // open
        fp = fopen ("iwcfgdump", "w+");
       
        // dump
        system ("/sbin/iwconfig > iwcfgdump 2>/dev/null");


Not sure this is the problem, but try to create the file before opening it.

SaTaN 10-13-2003 07:56 AM

Re: string search in C
 
Quote:

Originally posted by h/w

so, im looking for the string "test" within the string passed to this function (ssid). it doesnt seem to work (yes the string being compared with has the "test" string in it)m, and the else{} is never taken.

Code:

if ( (cmp = strstr (iw_result, temp)) == NULL)
I think the problem is that you aren't checking if the char array ssid contains "test" or not , but some other variable iw_result
which contains some other variables

Code:

system ("/sbin/iwconfig > iwcfgdump 2>/dev/null");
What does this command do ??

h/w 10-13-2003 09:41 AM

first up, thanks you two.

satan :
umm, yes, i meant that im checking to see if there is a "test" string within the string variable 'iw_result'. i wanted to try it before searching for the ssid variable (neither works - and iw_result contains both). the system() just outputs the result of /sbin/iwconfig to the file iwcfgdump and does not print any message on std_err.

Hko:
the file is created. i checked it everytime i run the program, and sure enough, the strrings im searching for are there.

Again, my intention is to search for the string for the string in variable 'temp' within the variable 'iw_result'.

thanks.

h/w 10-13-2003 09:46 AM

also, if i print out the 'iw_result' variable, i have the strings im trying to match in it - so thats not a problem.

h/w 10-13-2003 01:39 PM

any ideas?

orgcandman 10-13-2003 01:48 PM

I haven't really used the fopen and fread/fwrite stuff (I just go with plain open read and write calls) but from the looks of it, your code declares iwcfgdump as write only
Code:

p = fopen ("iwcfgdump", "w+");
Perhaps, try changing things around:

Code:


        int ret;
       
        int fp;

        char *temp = "test";

        char iw_result[1024], *cmp;

        // open
        fp = open ("iwcfgdump", O_RDWR | O_CREAT);
       
        // dump
        system ("/sbin/iwconfig > iwcfgdump 2>/dev/null");

        // read
        while ( (ret = read(fp, iw_result, 1024)) != 0) ;

        // search for ssid in iw_result
        if ( (cmp = strstr (iw_result, temp)) == NULL)
                printf ("OID was not set\n");
        else
                printf ("OID set\n");

        close (fp);

        //delete dump
        unlink ("./iwcfgdump"); /* I guess */

see if that helps at all

Hko 10-13-2003 02:11 PM

Quote:

Code:

// read
while ( (ret = fread (iw_result, 80, 8, fp)) != 0) ;


Because you are ending this line with a semicolon, there's nothing in the while-loop except for the fread() call itself.

You are reading 8x80-byte chunks of the file into iw_result. Each call to fread() the previous contents of iw_result are overwritten with the newly read data. This repeats until there's nothing left to read (in which case nothing is overwritten in iw_result). Because you are reading chunks of 8x80 = 640 bytes, depending how much data iwconfig outputs, you are probably reading just 1 chunk, so nothing gets overwritten. So, merely by luck, the text you are looking for is preserved in iw_result.

Though it seems to work, this is not the way to do it. Also, as fread() is for reading binary data, it does not insert a '\0' character. This is more or less ok if your provide for appending a '\0' at the right place yourself, but your program doesn't. Because of this strstr() stops comparing only when it encounters a '\0' by accindent.

This doesn't explain for 100% why it would not find the string you search for, but your program does have severe bugs.

h/w 10-13-2003 02:25 PM

understood. i dont even need to have the data in the file - i only need it in a variable, and do the comparison. very roundabout way to do this - what im doing.
whats the best way to read a syscall output into a variable?

on what i was trying - i havent really understood the problem with the while loop. i wanted to keep reading the data from the file till an EOF was reached, which was what the manpage said it would do. again, whats the right way to do this?

thanks a lot. :)

Hko 10-13-2003 03:33 PM

Quote:

understood. i dont even need to have the data in the file - i only need it in a variable, and do the comparison. very roundabout way to do this - what im doing.
whats the best way to read a syscall output into a variable?
The file will (probably) be cached by the kernel, so when you read it the kernel still provides the data from memory. It's not too much of a "very roundabout way".

However, you can use the popen() syscall to make it more clean, and maybe a little bit faster.
popen("<command>", "r") starts the command just like system(), but it connects the standard output (stdout) to the FILE* it returns. This works the same way as "iwconfig | your_prog". After popen(), you can read from the FILE* returned by popen() just like you would read from the temp file. You also don't have to delete/unlink anything afterwards, just close the pipe with pclose().

Quote:

on what i was trying - i havent really understood the problem with the while loop. i wanted to keep reading the data from the file till an EOF was reached, which was what the manpage said it would do. again, whats the right way to do this?
Your while loop reads 640 bytes, which it stores in iw_result.
If the file is larger than 640 bytes, the while loop will run a second time executing the same fread() call again, storing the next 640 in the same place: iw_result. Thus overwriting the first 640 bytes.

One solution is to have a while loop that reads one line from iwconfig, scans the line for some string, say "test". And then read the next line, and scan again. Until the end-of-file is reached. something like:
Code:

while (read next line) {
    strstr(one_line, "test");
}

instead of your while loop (effectively like this, because your while statement ends with ';' ):
Code:

while (read 640 bytes)  {
    /* nothing  */
}
strstr(iw_result, "test");

I rewrote your program, using line-by-line reading from a pipe. But I used ifconfig, because I don't have iwconfig at hand. This program tests if an IP-address was assigned to my ethernet card "eth1", by searching for "inet addr" in the output of "ifconfig eth1". If the ethernet card doesn't have an IP-address, the string "inet addr" will not be in the output. If you want to use this code for your purpose, you'll have to rewrite it for "iwconfig".
Code:

#include <stdio.h>
#include <string.h>

#define MAXLEN 80

int main()
{
    int found;
    FILE *fp;
    char one_line[MAXLEN + 1];
    char *temp = "inet addr";

    printf ("check if eth1 is assigned an IP address.\n");
    fp = popen ("/sbin/ifconfig eth1", "r");
       
    /* read line by line from the ifconfig pipe */
    found = 0;
    while (fgets(one_line, MAXLEN, fp) != NULL) {
          if (strstr(one_line, temp) != NULL) {
              found = 1;
              break;    /* no need to read more */
          }
    }
    if (found) printf ("IP address set.\n");
    else printf ("IP addres NOT set\n");
    pclose (fp);
    return 0;
}


h/w 10-13-2003 03:40 PM

thanks Hko, satan and orgcandman - a lot!

h/w 10-13-2003 04:12 PM

i tried the code snippet of ur Hko, it works fine.
but...
problem persists. when i give the value of temp = "test", and search using temp, it matches correctly.
but if i passed the same string from some other function into this one, and try to compare, it doesnt work. and both the temp, and the parsed string, when i output, look the same to me.

Code:

void
chkiwconfig (char *ssid)
{
    #define MAXLEN 80

    int found;
    FILE *fp;
    char one_line[MAXLEN + 1];
    char *temp = "snooper trooper";

    printf ("temp=%s-ssid=%s-\n", temp, ssid);

    printf ("check if eth1 is assigned an IP address.\n");
    fp = popen ("/sbin/iwconfig eth1 2>/dev/null", "r");
       
    /* read line by line from the ifconfig pipe */
    found = 0;
    while (fgets(one_line, MAXLEN, fp) != NULL) {
          if (strstr(one_line, temp) != NULL) {
              found = 1;
              break;    /* no need to read more */
          }
    }
    if (found) printf ("IP address set.\n");
    else printf ("IP addres NOT set\n");
    pclose (fp);

}

it works fine with the above. but if i change it to :
Code:

if (strstr(one_line, ssid) != NULL) {
it doesnt work.

as i said, when i print out temp, and ssid, they both look the same. i wonder whats the issue.

h/w 10-13-2003 04:47 PM

i tried to compare the two using strcmp(), and they dont match. and i cant seem to figure out what the problem is, cos if i print them out, theyre the same. could it have anything to do with an \0 character or something?

tia.

Hko 10-13-2003 04:55 PM

I don't understand what the problem is. This works:
Code:

#include <stdio.h>
#include <string.h>

#define MAXLEN 80
#define MAXSEARCHLEN 20

int chkifconfig(char *str)
{
    FILE *fp;
    char one_line[MAXLEN + 1];

    printf ("check if \"%s\" is in output of \"ifconfig eth1\".\n", str);
    fp = popen ("/sbin/ifconfig eth1", "r");
       
    /* read line by line from the ifconfig pipe */
    while (fgets(one_line, MAXLEN, fp) != NULL) {
          if (strstr(one_line, str) != NULL) {
              pclose (fp);
              return 1;
          }
    }
    pclose (fp);
    return 0;
}


int main(void)
{
    int found;
    char searchstr[MAXSEARCHLEN + 1];
   
    printf("Enter a string to search for in output of \"ifconfig eth1\": ");
    fgets(searchstr, MAXSEARCHLEN, stdin);

    /* searchstr will contain the return. Remove it: */
    searchstr[strlen(searchstr) - 1] = '\0';

    found = chkifconfig(searchstr);
    if (found) printf ("\"%s\" found.\n", searchstr);
    else printf ("\"%s\" NOT Found.\n", searchstr);
    return 0;
}


h/w 10-13-2003 05:06 PM

there seems to be a problem with the string im passing - like i said, the strcmp() does not give me a 0, although if i print them out, they look the same.
im sooo lost now. :)


All times are GMT -5. The time now is 12:52 AM.