0

I'm trying to make a code in C that can get environment variable and then search for a specific word from that result using strstr. I'm using UBUNTU OS and gcc compiler. Here is the code that I've written. The comment are what I expected to happen.

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

extern char **environ;
extern char **tmp;
extern char **tmp2;

char *search_string(char *tmp,int x)
{
      char string[]="ABC";          //I'm looking for ABC in the environment variable
      char *pointer;
      pointer=strstr(tmp,string);   //pointer will point to the result of strstr
      if(pointer != NULL)
      {       printf("%s ,",tmp);
              printf("data found : %s \n",pointer);
      } else  {
              //hope to do something
      }
      return (pointer);
}

int main(char *tmp2)
{
      int x = 0;
      for(x=0;environ[x]!='\0';x++){   //I'm expecting it to keep looping until finish
      tmp2=search_string(environ[x],x); //tmp2 will point to the function return value
      printf("%s\n",tmp2);             //print the return value
      }  //If the search_string return NULL, does it consider string or something else?
      return 0;
}

After running the code, it crashes because of core dump. Here are the output.

ABC=/tmp ,data found : ABC=/tmp 
ABC=/tmp
Segmentation fault (core dumped)

From what I see, it can only do the search_string for only 1 time. Then it crashes. Then I use gdb to find out at what line does it actually crash and here are the result:

Starting program: /home/fikrie/a.out 
ABC=/tmp ,data found : ABC=/tmp 
ABC=/tmp

Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99  ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.

What I dont understand from the debug is that it's receiving error because of SEGV signal. Can someone point me on how to solve this problem? Is it because the search_string returns a NULL value?

Mohd Fikrie
  • 197
  • 4
  • 21
  • What does `environ[x]` contain? The argument list in `main` is non-standard. `environ` s pointer-to-pointer to char -maybe the issue is there. – Sadique Oct 29 '13 at 03:00
  • I am surprised that you can loop over `environ[x]` until you find a NULL - and note you should really test for NULL not '\0' since this is a pointer... – Floris Oct 29 '13 at 03:09
  • @Acme the environ[x] contain pointer that can get the environment variable. by printing environ[x], I should get the environtment variable in /etc/profile. – Mohd Fikrie Oct 29 '13 at 04:10
  • @Floris I can loop because as far as I know, it is an array of pointer that will end after collecting all the data. As far as I know, an array will end with a '/0' right? – Mohd Fikrie Oct 29 '13 at 04:12
  • A _string_ will end in `'\0'`, but there is no reason why the last element of an array of _pointers_ should contain `NULL`. Although it would be a nice thing to do - it means you don't have to pass the size of the array explicitly. But I'm not aware of any part of the C standard that says it shall be so. – Floris Oct 29 '13 at 12:17

2 Answers2

2

The problem is that if search_string() doesn't find the string, it returns NULL. You then pass that NULL to printf(), which crashes.

In main(), you need something like:

if (tmp2)
    printf("%s\n", tmp2);

Also, the tmp2 variable should be of type char *, not char **. And there's no reason not to declare it local to main().

caf
  • 233,326
  • 40
  • 323
  • 462
  • Yes!you are totally correct. It core dumped because the search_string return a NULL after the second search, which is the output of strstr if it doesnt find the words that I specified. Thus, printf cannot print a NULL result. – Mohd Fikrie Oct 29 '13 at 04:15
  • You suggestion is good. It does work. When applying 'if(tmp2)' in the code, it will search in the environ[x] for 1 time. But in my case, I would like to check the entire environment variable, that is why i use 'for(x=0;environ[x]!='\0';x++)' to search. I just need to know how to avoid returning 'NULL' if 'strstr' doesnt find any result. Is my method wrong? – Mohd Fikrie Oct 29 '13 at 04:45
  • @MohdFikrie: Adding the `if (tmp2)` *does* mean that it's still searching the entire environment - it's just that it will only execute the `printf()` when the target string is found. To see this, create more than one environment variable that contains the search string (eg. `ABCx=1` `ABCy=1`). – caf Oct 29 '13 at 05:12
  • I have tried your suggestion and it is not behaving properly. I added 'ABC=/home','ABCx=/etc', & 'ABCy=/home/fikrie'. By using the command 'env'.I found that 'ABC=/home' is at the top and the other 2 are at the bottom. When I ran the code, it only found 'ABC/home' and not the other 2. I'm assuming that it will stop searching if it found 'NULL' in environment eventhough there are still 'ABC' at the lower part of it. Does it sound correct? – Mohd Fikrie Oct 29 '13 at 07:32
  • @MohdFikrie: It will not stop searching because your code says to keep going until the end of the environment is reached, regardless of if a match is found. You may not have exported the extra environment variables. – caf Oct 29 '13 at 09:08
  • I did export, and all 3 environment were found when I use command 'env'. Anyway, I manage to solved it by making an if condition in the search_string which is 'if(pointer != NULL)' do something, 'else ( pointer = 0)', and the I maintained the loop to use 'for(x=0;environ[x]!='\0';x++' in main. My problem now is to make an array of pointer to store all the value that is returned from 'search_string()'. Thank you for your time and shared knowledge. – Mohd Fikrie Oct 29 '13 at 09:32
0

A very simple change to your main loop stops the program from crashing:

int main(char *tmp2)
{
      int x = 0;
      for(x=0;environ[x]!='\0';x++){   //I'm expecting it to keep looping until finish
      tmp2=search_string(environ[x],x); //tmp2 will point to the function return value
// >>>>> change these next two lines:
      if(tmp2 != NULL) printf("%s\n",tmp2);             //print the return value
      else printf("%s does not contain ABC\n", environ[x]);
// <<<<< end of change
      }  //If the search_string return NULL, does it consider string or something else?
      return 0;
}

Note that if you only expect one match, you could add a break; when you print the match. The above code prints out all the environment variables - you can see it doesn't stop...

Floris
  • 45,857
  • 6
  • 70
  • 122