Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
984 views
in Technique[技术] by (71.8m points)

c - Parse $PATH variable and save the directory names into an array of strings

I want to parse the $PATH variable of Linux, and then save the directory names that are getting separated with ':' into an array of strings.

I know it's a simple task but I am stuck and any help would be nice.

My code so far is something like this but something ain't right.

char **array;
char *path_string;
char *path_var = getenv("PATH");
int size_of_path_var = strlen(path_var);

path_string = strtok(path_var, ":");
while (path_string != NULL) {
    ss = strlen(path_string)
    array[i] = (char *)malloc(ss + 1);
    array[i] = path_string; //this is actually all i want to do for every path
    i++;
    path_string = strtok(NULL, ":");
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

2 main things wrong with your code, pretty much summarized by the comments:

  • you strtok a public buffer (returned by getenv)
  • you don't know how many variables will be in the buffer so you don't allocate the array of arrays at all!

Let me propose a working implementation not using strtok, and thus allowing to detect empty path (and replace it by . as Jonathan hinted). Compiles without any warnings using gcc -Wall -Wwrite-strings:

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

int main()
{
    const char **array;
    const char *orig_path_var = getenv("PATH");
    char *path_var = strdup(orig_path_var ? orig_path_var : ""); // just in case PATH is NULL, very unlikely
    const char *the_dot = ".";
    int j;
    int len=strlen(path_var);
    int nb_colons=0;
    char pathsep = ':';
    int current_colon = 0;

    // first count how many paths we have, and "split" almost like strtok would do
    for (j=0;j<len;j++)
    {
        if (path_var[j]==pathsep)
        {
            nb_colons++;
            path_var[j] = '';
        }       
    }

    // allocate the array of strings
    array=malloc((nb_colons+1) * sizeof(*array));

    array[0] = path_var;  // first path

    // rest of paths
    for (j=0;j<len;j++)
    {
        if (path_var[j]=='')
        {
            current_colon++;
            array[current_colon] = path_var+j+1;
            if (array[current_colon][0]=='')
            {
                // special case: add dot if path is empty
                array[current_colon] = the_dot;
            }

        }
    }

    for (j=0;j<nb_colons+1;j++)
    {
        printf("Path %d: <%s>
",j,array[j]);
    }

    return(0);
}

Details of the operations:

  • make a copy of the env string to avoid butchering it
  • count the colons (to make it work with windows, just replace with ;) and tokenize
  • allocate the array according to number of colons + 1 (1 more token than number of separators!)
  • second pass to go through the string again and fill it with parts of the tokenized string (no need to allocate again, the original string is already allocated)
  • special case: empty path: replace by .. Could display a warning to tell the user that this is not safe.
  • print the result

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...