#include "libshell.h" char ** getpaths(void) { char *p; char **q; char *path; size_t path_s; char *path_temp; char **paths; size_t paths_s; if((path_temp = getenv(PATH_NAME)) == NULL){ errno = ENOMEM; /* Cannot allocate memory */ return NULL; } /* How long is path? */ for(path_s = 0; path_temp[path_s] != '\0'; ++path_s); /* path_s has the size of the path string, not including the null * terminator */ /* getenv's return value mustn't be modified so copy it into memory we * control */ if((path = malloc(sizeof(char) * (path_s + 1))) == NULL){ errno = ENOMEM; /* Cannot allocate memory */ return NULL; } memcpy(path, path_temp, path_s + 1); path_temp = NULL; path_s = 0; /* This shouldn't be necessary anymore */ /* How many paths in $PATH? */ for(paths_s = 1, p = path; *p != '\0'; paths_s += *p++ == PATH_DELIMITER); if((paths = malloc(sizeof(char *) * (paths_s + 1))) == NULL){ free(path); errno = ENOMEM; /* Cannot allocate memory */ return NULL; } /* Replace all instances of the path delimiter with 0, and then put the * next path beginning into paths. */ /* This way we can get multiple strings out of one span of memory. */ for(*paths = p = path, q = paths + 1; *p != '\0';) if(*p++ == PATH_DELIMITER){ *(p - 1) = '\0'; *q++ = p; } paths[path_s] = NULL; /* Because paths[0] will always be path, we can just free(*paths) at * the end and discard path */ path = NULL; return paths; }