aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Aaron Gyes <me@aaron.gy>2016-06-18 22:21:15 -0700
committerGravatar Aaron Gyes <me@aaron.gy>2016-06-18 22:21:15 -0700
commit4b0f1cf85ba987b09351b4bfe3df3ed9bd59e4de (patch)
tree5d6bd4d28532035c92724964c51be2c2c00af54e
parent7ac32e45cb90118ebbb4d4fe2024fc1751a3b65b (diff)
parent8e21d5de92c4c85f55bbef34b6ffadd40a37e3db (diff)
-rw-r--r--src/common.cpp2
-rw-r--r--src/common.h11
-rw-r--r--src/fish.cpp31
-rw-r--r--src/screen.cpp10
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 ||