version 1.198, 2020/04/20 13:25:36 |
version 1.199, 2020/05/16 14:26:33 |
|
|
} |
} |
|
|
static char * |
static char * |
|
expand_path(const char *path, const char *home) |
|
{ |
|
char *expanded, *name; |
|
const char *end; |
|
struct environ_entry *value; |
|
|
|
if (strncmp(path, "~/", 2) == 0) { |
|
if (home == NULL) |
|
return (NULL); |
|
xasprintf(&expanded, "%s%s", home, path + 1); |
|
return (expanded); |
|
} |
|
|
|
if (*path == '$') { |
|
end = strchr(path, '/'); |
|
if (end == NULL) |
|
name = xstrdup(path + 1); |
|
else |
|
name = xstrndup(path + 1, end - path - 1); |
|
value = environ_find(global_environ, name); |
|
free(name); |
|
if (value == NULL) |
|
return (NULL); |
|
if (end == NULL) |
|
end = ""; |
|
xasprintf(&expanded, "%s%s", value->value, end); |
|
return (expanded); |
|
} |
|
|
|
return (xstrdup(path)); |
|
} |
|
|
|
void |
|
expand_paths(const char *s, char ***paths, u_int *n) |
|
{ |
|
const char *home = find_home(); |
|
char *copy, *next, *tmp, resolved[PATH_MAX], *expanded; |
|
u_int i; |
|
|
|
*paths = NULL; |
|
*n = 0; |
|
|
|
copy = tmp = xstrdup(s); |
|
while ((next = strsep(&tmp, ":")) != NULL) { |
|
expanded = expand_path(next, home); |
|
if (expanded == NULL) { |
|
log_debug("%s: invalid path: %s", __func__, next); |
|
continue; |
|
} |
|
if (realpath(expanded, resolved) == NULL) { |
|
log_debug("%s: realpath(\"%s\") failed: %s", __func__, |
|
expanded, strerror(errno)); |
|
free(expanded); |
|
continue; |
|
} |
|
free(expanded); |
|
for (i = 0; i < *n; i++) { |
|
if (strcmp(resolved, (*paths)[i]) == 0) |
|
break; |
|
} |
|
if (i != *n) { |
|
log_debug("%s: duplicate path: %s", __func__, resolved); |
|
continue; |
|
} |
|
*paths = xreallocarray(*paths, (*n) + 1, sizeof *paths); |
|
(*paths)[(*n)++] = xstrdup(resolved); |
|
} |
|
free(copy); |
|
} |
|
|
|
static char * |
make_label(const char *label, char **cause) |
make_label(const char *label, char **cause) |
{ |
{ |
char *base, resolved[PATH_MAX], *path, *s; |
char **paths, *path, *base; |
struct stat sb; |
u_int i, n; |
uid_t uid; |
struct stat sb; |
|
uid_t uid; |
|
|
*cause = NULL; |
*cause = NULL; |
|
|
if (label == NULL) |
if (label == NULL) |
label = "default"; |
label = "default"; |
uid = getuid(); |
uid = getuid(); |
|
|
if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0') |
expand_paths(TMUX_SOCK, &paths, &n); |
xasprintf(&base, "%s/tmux-%ld", s, (long)uid); |
if (n == 0) { |
else |
xasprintf(cause, "no suitable socket path"); |
xasprintf(&base, "%s/tmux-%ld", _PATH_TMP, (long)uid); |
return (NULL); |
if (realpath(base, resolved) == NULL && |
|
strlcpy(resolved, base, sizeof resolved) >= sizeof resolved) { |
|
errno = ERANGE; |
|
free(base); |
|
goto fail; |
|
} |
} |
free(base); |
path = paths[0]; /* can only have one socket! */ |
|
for (i = 1; i < n; i++) |
|
free(paths[i]); |
|
free(paths); |
|
|
if (mkdir(resolved, S_IRWXU) != 0 && errno != EEXIST) |
xasprintf(&base, "%s/tmux-%ld", path, (long)uid); |
|
if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST) |
goto fail; |
goto fail; |
if (lstat(resolved, &sb) != 0) |
if (lstat(base, &sb) != 0) |
goto fail; |
goto fail; |
if (!S_ISDIR(sb.st_mode)) { |
if (!S_ISDIR(sb.st_mode)) { |
errno = ENOTDIR; |
errno = ENOTDIR; |
|
|
errno = EACCES; |
errno = EACCES; |
goto fail; |
goto fail; |
} |
} |
xasprintf(&path, "%s/%s", resolved, label); |
xasprintf(&path, "%s/%s", base, label); |
|
free(base); |
return (path); |
return (path); |
|
|
fail: |
fail: |
xasprintf(cause, "error creating %s (%s)", resolved, strerror(errno)); |
xasprintf(cause, "error creating %s (%s)", base, strerror(errno)); |
|
free(base); |
return (NULL); |
return (NULL); |
} |
} |
|
|