-1

I have codes to get environment variable name from stand input and call library function getenv() to get the value and output.

Here are codes.

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

#define MAXLEN 256

int main(void)

{
    char *envName;
    char *envValue;
    char *envEntry;
    char *envVar=(char*)malloc(sizeof(char)*MAXLEN);

    while(NULL!=(envName=gets(envVar))){

    envValue=getenv(envName);
    if(envValue){
        printf("%s\n",envValue);

        envEntry=strtok(envValue,";");

        while(envEntry){
            printf("%s\n",envEntry);

            envEntry=strtok(NULL,";");
        }
    }else{
        printf("not found\n");
    }
}

    return 0;
}

If the environment variable "path" contains "a;b;c;d". While it runs,if type a string "path" first time,it works well,but if type "path" again it only gets the first string like"a" or "a;b".

chaox
  • 51
  • 6
  • *Never* use gets. It is utterly deprecated. Use `fgets` instead. Search the web for numerous reasons why. – William Pursell Jan 28 '16 at 03:05
  • 1
    Do you know how strtok works? – user253751 Jan 28 '16 at 03:13
  • @immibis strtok() will keep a pointer to the first parameter after first invoke and will use this pointer if the first parameter is NULL if invoked again – chaox Jan 28 '16 at 03:22
  • 1
    @chaox That's part of how it works, but not the relevant part. What does its return value point to? – user253751 Jan 28 '16 at 03:30
  • @immibis the delimiter will replaced by null in return value – chaox Jan 28 '16 at 03:51
  • @immibis but why it works well first time if I type "path" – chaox Jan 28 '16 at 03:52
  • 1
    @chaox The return value is a pointer, therefore it doesn't contain the delimiter, or a null character, or indeed any characters, because it only contains an address. However, what does it point to? – user253751 Jan 28 '16 at 03:53
  • @immibis it points to the address of first character that delimiters does not contain in source string – chaox Jan 28 '16 at 03:57

1 Answers1

4

You're not allowed to modify the string that getenv() returns. strtok() replaces the delimiter characters with null characters, so you're violating this restriction. Typical implementations of getenv() work by returning a pointer directly into the environment string, so you're affecting how it searches the environment in future calls. Originally, your environment contained

path=a;b;c;d\0

When you called strtok(), it replaced all the semicolons with null bytes:

path=a\0b\0c\0d\0

So when you call getenv("path") the next time, it returns a pointer to this, and the first \0 terminates the environment variable.

You should make a copy of evnValue and use strtok() on this.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Yes,you are right.I make a copy of `envValue` and it works.But why it does not give the correct value when I type "path" again.Does it cache the string which envVal points to and return the address of string cached when `getenv()` invoked again? – chaox Jan 28 '16 at 04:14
  • When you used `strtok`, you modified the environment. – Barmar Jan 28 '16 at 04:31
  • I've added a detailed explanation of why this happens. – Barmar Jan 28 '16 at 04:34