Move get_runtime_path() to env.cpp and expose it in env.h

It was previously a file-local static function in env_universal.cpp.
This commit is contained in:
Mahmoud Al-Qudsi 2018-09-28 10:14:27 -05:00
parent 5cc92ffd70
commit e045b045da
4 changed files with 68 additions and 57 deletions

View file

@ -1631,6 +1631,68 @@ maybe_t<env_var_t> env_vars_snapshot_t::get(const wcstring &key) const {
return iter->second;
}
#if !defined(__APPLE__) && !defined(__CYGWIN__)
/// Check, and create if necessary, a secure runtime path. Derived from tmux.c in tmux
/// (http://tmux.sourceforge.net/).
static int check_runtime_path(const char *path) {
// Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
// OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
struct stat statpath;
uid_t uid = geteuid();
if (mkdir(path, S_IRWXU) != 0 && errno != EEXIST) return errno;
if (lstat(path, &statpath) != 0) return errno;
if (!S_ISDIR(statpath.st_mode) || statpath.st_uid != uid ||
(statpath.st_mode & (S_IRWXG | S_IRWXO)) != 0)
return EACCES;
return 0;
}
#endif
/// Return the path of an appropriate runtime data directory.
wcstring env_get_runtime_path() {
wcstring result;
const char *dir = getenv("XDG_RUNTIME_DIR");
// Check that the path is actually usable. Technically this is guaranteed by the fdo spec but in
// practice it is not always the case: see #1828 and #2222.
int mode = R_OK | W_OK | X_OK;
if (dir != NULL && access(dir, mode) == 0 && check_runtime_path(dir) == 0) {
result = str2wcstring(dir);
} else {
// Don't rely on $USER being set, as setup_user() has not yet been called.
// See https://github.com/fish-shell/fish-shell/issues/5180
const char *uname = getpwuid(geteuid())->pw_name;
// /tmp/fish.user
std::string tmpdir = "/tmp/fish.";
tmpdir.append(uname);
#if !defined(__APPLE__) && !defined(__CYGWIN__)
if (check_runtime_path(tmpdir.c_str()) != 0) {
debug(0, L"Runtime path not available.");
debug(0, L"Try deleting the directory %s and restarting fish.", tmpdir.c_str());
return result;
}
#endif
result = str2wcstring(tmpdir);
}
return result;
}
const wchar_t *const env_vars_snapshot_t::highlighting_keys[] = {L"PATH", L"CDPATH",
L"fish_function_path", NULL};

View file

@ -197,4 +197,7 @@ extern bool term_has_xn; // does the terminal have the "eat_newline_glitch"
/// Returns true if we think the terminal supports setting its title.
bool term_supports_setting_title();
/// Gets a path appropriate for runtime storage
wcstring env_get_runtime_path();
#endif

View file

@ -101,71 +101,15 @@ static maybe_t<wcstring> default_vars_path() {
return none();
}
#if !defined(__APPLE__) && !defined(__CYGWIN__)
/// Check, and create if necessary, a secure runtime path. Derived from tmux.c in tmux
/// (http://tmux.sourceforge.net/).
static int check_runtime_path(const char *path) {
// Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
// OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
struct stat statpath;
uid_t uid = geteuid();
if (mkdir(path, S_IRWXU) != 0 && errno != EEXIST) return errno;
if (lstat(path, &statpath) != 0) return errno;
if (!S_ISDIR(statpath.st_mode) || statpath.st_uid != uid ||
(statpath.st_mode & (S_IRWXG | S_IRWXO)) != 0)
return EACCES;
return 0;
}
/// Return the path of an appropriate runtime data directory.
static wcstring get_runtime_path() {
wcstring result;
const char *dir = getenv("XDG_RUNTIME_DIR");
// Check that the path is actually usable. Technically this is guaranteed by the fdo spec but in
// practice it is not always the case: see #1828 and #2222.
int mode = R_OK | W_OK | X_OK;
if (dir != NULL && access(dir, mode) == 0 && check_runtime_path(dir) == 0) {
result = str2wcstring(dir);
} else {
// Don't rely on $USER being set, as setup_user() has not yet been called.
// See https://github.com/fish-shell/fish-shell/issues/5180
const char *uname = getpwuid(geteuid())->pw_name;
// /tmp/fish.user
std::string tmpdir = "/tmp/fish.";
tmpdir.append(uname);
if (check_runtime_path(tmpdir.c_str()) != 0) {
debug(0, L"Runtime path not available.");
debug(0, L"Try deleting the directory %s and restarting fish.", tmpdir.c_str());
} else {
result = str2wcstring(tmpdir);
}
}
return result;
}
/// Returns a "variables" file in the appropriate runtime directory. This is called infrequently and
/// so does not need to be cached.
static wcstring default_named_pipe_path() {
wcstring result = get_runtime_path();
wcstring result = env_get_runtime_path();
if (!result.empty()) {
result.append(L"/fish_universal_variables");
}
return result;
}
#endif
/// Test if the message msg contains the command cmd.
static bool match(const wchar_t *msg, const wchar_t *cmd) {

View file

@ -161,6 +161,8 @@ class universal_notifier_t {
virtual bool notification_fd_became_readable(int fd);
};
wcstring get_runtime_path();
// Environment variable for requesting a particular universal notifier. See
// fetch_default_strategy_from_environment for names.
#define UNIVERSAL_NOTIFIER_ENV_NAME "fish_universal_notifier"