Merge branch 'hostname'

This addresses the discussion regarding the dependency on `hostname` and
the addition of a `$hostname` variable to replace it.

`$hostname` is a read-only, GLOBAL_ENV, non-electrified, lowercased,
non-exported variable that is read once at the start of a fish session.
The finer points of this can be debated endlessly, but this is a shared
starting point that any changes can build on (ref #4422).

Regarding performance: @krader1961 brought up some good points in #4422
regarding potential DNS timeouts (but they really don't apply except if
the host name is not hardcoded in resolv.conf, which quickly manifests
with a cascade of errors on most *nix systems in all cases), but note
that gethostname() was already being called by fish so that would be
more of a future optimization than a "must" at this point.
This commit is contained in:
Mahmoud Al-Qudsi 2018-03-09 15:13:27 -06:00
commit 5cf67e20a5
6 changed files with 19 additions and 17 deletions

View File

@ -45,6 +45,7 @@ This section is for changes merged to the `major` branch that are not also merge
- Wrapping completions (from `complete -w` or `function -w`) can now inject arguments. For example, `complete gco -w 'git checkout'` now works properly (#1976). The `alias` function has been updated to respect this behavior.
- The `jobs` builtin now has a `-q` and `--quiet` option to silence the output.
- fish now supports `&&`, `||`, and `!` (#4620).
- The machine hostname, where available, is now exposed as `$hostname` which is now a reserved variable. This drops the dependency on the `hostname` executable (#4422).
## Other significant changes
- Command substitution output is now limited to 10 MB by default (#3822).

View File

@ -76,7 +76,6 @@ Running fish requires:
* `awk`
* `find`
* `grep`
* `hostname`
* `kill`
* `ps`
* `sed`

View File

@ -1,10 +1,3 @@
# Fetching the host name can be expensive if there is a problem with DNS or whatever subsystem the
# hostname command uses. So cache the answer so including it in the prompt doesn't make fish seem
# slow.
if not set -q __fish_prompt_hostname
set -g __fish_prompt_hostname (hostname | string split '.')[1]
end
function prompt_hostname
echo $__fish_prompt_hostname
echo $hostname;
end

View File

@ -322,7 +322,7 @@ bool string_set_contains(const T &set, const wchar_t *val) {
/// Check if a variable may not be set using the set command.
static bool is_read_only(const wchar_t *val) {
const string_set_t env_read_only = {L"PWD", L"SHLVL", L"_", L"history", L"status", L"version", L"pid"};
const string_set_t env_read_only = {L"PWD", L"SHLVL", L"_", L"history", L"status", L"version", L"pid", L"hostname"};
return string_set_contains(env_read_only, val);
}
@ -972,6 +972,11 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
// Set the $pid variable (%self replacement)
env_set_one(L"pid", ENV_GLOBAL, to_string<long>(getpid()));
// Set the $hostname variable
wcstring hostname = L"fish";
get_hostname_identifier(hostname);
env_set_one(L"hostname", ENV_GLOBAL, hostname);
// Set up SHLVL variable. Not we can't use env_get because SHLVL is read-only, and therefore was
// not inherited from the environment.
wcstring nshlvl_str = L"1";

View File

@ -44,6 +44,7 @@
#include "utf8.h"
#include "util.h" // IWYU pragma: keep
#include "wutil.h"
#include "wcstringutil.h"
#if __APPLE__
#define FISH_NOTIFYD_AVAILABLE 1
@ -76,7 +77,6 @@
"changes will be overwritten.\n"
static wcstring get_machine_identifier();
static bool get_hostname_identifier(wcstring *result);
static wcstring vars_filename_in_directory(const wcstring &wdir) {
if (wdir.empty()) return L"";
@ -495,7 +495,7 @@ bool env_universal_t::load(callback_data_list_t &callbacks) {
// Silently "upgraded."
tried_renaming = true;
wcstring hostname_id;
if (get_hostname_identifier(&hostname_id)) {
if (get_hostname_identifier(hostname_id)) {
const wcstring hostname_path = wdirname(vars_path) + L'/' + hostname_id;
if (0 == wrename(hostname_path, vars_path)) {
// We renamed - try again.
@ -911,11 +911,14 @@ static bool get_mac_address(unsigned char macaddr[MAC_ADDRESS_MAX_LEN]) { return
#endif
/// Function to get an identifier based on the hostname.
static bool get_hostname_identifier(wcstring *result) {
bool get_hostname_identifier(wcstring &result) {
//The behavior of gethostname if the buffer size is insufficient differs by implementation and libc version
//Work around this by using a "guaranteed" sufficient buffer size then truncating the result.
bool success = false;
char hostname[HOSTNAME_LEN + 1] = {};
if (gethostname(hostname, HOSTNAME_LEN) == 0) {
result->assign(str2wcstring(hostname));
char hostname[256] = {};
if (gethostname(hostname, sizeof(hostname)) == 0) {
result.assign(str2wcstring(hostname));
result.assign(truncate(result, HOSTNAME_LEN));
success = true;
}
return success;
@ -931,7 +934,7 @@ wcstring get_machine_identifier() {
for (size_t i = 0; i < MAC_ADDRESS_MAX_LEN; i++) {
append_format(result, L"%02x", mac_addr[i]);
}
} else if (!get_hostname_identifier(&result)) {
} else if (!get_hostname_identifier(result)) {
result.assign(L"nohost"); // fallback to a dummy value
}
return result;

View File

@ -28,6 +28,7 @@ struct callback_data_t {
typedef std::vector<struct callback_data_t> callback_data_list_t;
bool get_hostname_identifier(wcstring &result);
/// Class representing universal variables.
class env_universal_t {
var_table_t vars; // current values