diff options
author | Aaron Gyes <me@aaron.gy> | 2016-06-18 22:21:15 -0700 |
---|---|---|
committer | Aaron Gyes <me@aaron.gy> | 2016-06-18 22:21:15 -0700 |
commit | 4b0f1cf85ba987b09351b4bfe3df3ed9bd59e4de (patch) | |
tree | 5d6bd4d28532035c92724964c51be2c2c00af54e | |
parent | 7ac32e45cb90118ebbb4d4fe2024fc1751a3b65b (diff) | |
parent | 8e21d5de92c4c85f55bbef34b6ffadd40a37e3db (diff) |
Merge branch 'master' of https://github.com/fish-shell/fish-shell
-rw-r--r-- | src/common.cpp | 2 | ||||
-rw-r--r-- | src/common.h | 11 | ||||
-rw-r--r-- | src/fish.cpp | 31 | ||||
-rw-r--r-- | src/screen.cpp | 10 |
4 files changed, 52 insertions, 2 deletions
diff --git a/src/common.cpp b/src/common.cpp index fcbb2465..b0e96789 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -71,6 +71,8 @@ static rwlock_t termsize_rwlock; static char *wcs2str_internal(const wchar_t *in, char *out); static void debug_shared(const wchar_t msg_level, const wcstring &msg); +bool has_working_tty_timestamps = true; + #ifdef HAVE_BACKTRACE_SYMBOLS // This function produces a stack backtrace with demangled function & method names. It is based on // https://gist.github.com/fmela/591333 but adapted to the style of the fish project. diff --git a/src/common.h b/src/common.h index b8791279..0c1b77d4 100644 --- a/src/common.h +++ b/src/common.h @@ -21,6 +21,13 @@ #include "fallback.h" // IWYU pragma: keep #include "signal.h" // IWYU pragma: keep +// Define a symbol we can use elsewhere in our code to determine if we're being built on MS Windows +// under Cygwin. +#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(__CYGWIN__) || \ + defined(__WIN32__) +#define OS_IS_CYGWIN +#endif + /// Avoid writing the type name twice in a common "static_cast-initialization". Caveat: This doesn't /// work with type names containing commas! #define CAST_INIT(type, dst, src) type dst = static_cast<type>(src) @@ -188,6 +195,10 @@ extern const wchar_t *program_name; void read_ignore(int fd, void *buff, size_t count); void write_ignore(int fd, const void *buff, size_t count); +/// Set to false at run-time if it's been determined we can't trust the last modified timestamp on +/// the tty. +extern bool has_working_tty_timestamps; + /// This macro is used to check that an input argument is not null. It is a bit lika a non-fatal /// form of assert. Instead of exit-ing on failure, the current function is ended at once. The /// second parameter is the return value of the current function on failure. diff --git a/src/fish.cpp b/src/fish.cpp index 45899866..9482bd3f 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -407,6 +407,36 @@ static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *cmds) return optind; } +/// Various things we need to initialize at run-time that don't really fit any of the other init +/// routines. +static void misc_init() { +#ifdef OS_IS_CYGWIN + // MS Windows tty devices do not have either a read or write timestamp. Those respective fields + // of `struct stat` are always the current time. Which means we can't use them. So we assume no + // external program has written to the terminal behind our back. This makes multiline prompts + // usable. See issue #2859. + has_working_tty_timestamps = false; +#else + // This covers Windows Subsystem for Linux (WSL). + int fd = open("/proc/sys/kernel/osrelease", O_RDONLY); + if (fd != -1) { + const char *magic_suffix = "Microsoft"; + int len_magic_suffix = strlen(magic_suffix); + char osrelease[128] = {0}; + int len_osrelease = read(fd, osrelease, sizeof(osrelease) - 1); + if (osrelease[len_osrelease - 1] == '\n') { + osrelease[len_osrelease - 1] = '\0'; + len_osrelease--; + } + if (len_osrelease >= len_magic_suffix && + strcmp(magic_suffix, osrelease + len_osrelease - len_magic_suffix) == 0) { + has_working_tty_timestamps = false; + } + close(fd); + } +#endif // OS_IS_MS_WINDOWS +} + int main(int argc, char **argv) { int res = 1; int my_optind = 0; @@ -452,6 +482,7 @@ int main(int argc, char **argv) { history_init(); // For set_color to support term256 in config.fish (issue #1022). update_fish_color_support(); + misc_init(); parser_t &parser = parser_t::principal_parser(); diff --git a/src/screen.cpp b/src/screen.cpp index fc5c927c..a9d9ddcf 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -347,12 +347,18 @@ static void s_save_status(screen_t *s) { static void s_check_status(screen_t *s) { fflush(stdout); fflush(stderr); + if (!has_working_tty_timestamps) { + // We can't reliably determine if the terminal has been written to behind our back so we + // just assume that hasn't happened and hope for the best. This is important for multi-line + // prompts to work correctly. + return; + } fstat(1, &s->post_buff_1); fstat(2, &s->post_buff_2); - int changed = (s->prev_buff_1.st_mtime != s->post_buff_1.st_mtime) || - (s->prev_buff_2.st_mtime != s->post_buff_2.st_mtime); + bool changed = (s->prev_buff_1.st_mtime != s->post_buff_1.st_mtime) || + (s->prev_buff_2.st_mtime != s->post_buff_2.st_mtime); #if defined HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC changed = changed || |