const char *S_pathname_impl(const char *inpath, char *buffer) { if (*inpath != '~') { return inpath; } else { #define setp(c) if (p > buffer + PATH_MAX) return NULL; else *p++ = (c) static char path[PATH_MAX]; char *p; const char *ip, *dir; if (buffer == NULL) buffer = path; ip = inpath + 1; if (*ip == 0 || DIRMARKERP(*ip)) { if (!(dir = S_homedir())) return NULL; } else { #ifdef WIN32 return inpath; #else struct passwd *pwent; p = buffer; while (*ip != 0 && !DIRMARKERP(*ip)) setp(*ip++); setp(0); if (!(pwent = getpwnam(buffer)) || !(dir = pwent->pw_dir)) return NULL; #endif /* WIN32 */ } p = buffer; while (*dir != 0) setp(*dir++); while (*ip != 0) setp(*ip++); setp(0); return buffer; #undef setp } }
/* raises an exception if insufficient space cannot be malloc'd. otherwise returns a freshly allocated version of inpath with ~ (home directory) prefix expanded, if possible */ char *S_malloc_pathname(const char *inpath) { char *outpath; const char *ip; #ifdef WIN32 if (*inpath == '~' && (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip))) { const char *homedrive, *homepath; size_t n1, n2, n3; if ((homedrive = getenv("HOMEDRIVE")) != NULL && (homepath = getenv("HOMEPATH")) != NULL) { n1 = strlen(homedrive); n2 = strlen(homepath); n3 = strlen(ip) + 1; if ((outpath = malloc(n1 + n2 + n3)) == NULL) S_error("expand_pathname", "malloc failed"); memcpy(outpath, homedrive, n1); memcpy(outpath + n1, homepath, n2); memcpy(outpath + n1 + n2, ip, n3); return outpath; } } #else /* WIN32 */ if (*inpath == '~') { const char *dir; size_t n1, n2; struct passwd *pwent; if (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip)) { if ((dir = getenv("HOME")) == NULL) if ((pwent = getpwuid(getuid())) != NULL) dir = pwent->pw_dir; } else { char *userbuf; const char *user_start = ip; do { ip += 1; } while (*ip != 0 && !DIRMARKERP(*ip)); if ((userbuf = malloc(ip - user_start + 1)) == NULL) S_error("expand_pathname", "malloc failed"); memcpy(userbuf, user_start, ip - user_start); userbuf[ip - user_start] = 0; dir = (pwent = getpwnam(userbuf)) != NULL ? pwent->pw_dir : NULL; free(userbuf); } if (dir != NULL) { n1 = strlen(dir); n2 = strlen(ip) + 1; if ((outpath = malloc(n1 + n2)) == NULL) S_error("expand_pathname", "malloc failed"); memcpy(outpath, dir, n1); memcpy(outpath + n1, ip, n2); return outpath; } } #endif /* WIN32 */ /* if no ~ or tilde dir can't be found, copy inpath */ { size_t n = strlen(inpath) + 1; outpath = (char *)malloc(n); memcpy(outpath, inpath, n); return outpath; } }