summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--src/ls.c161
2 files changed, 96 insertions, 68 deletions
diff --git a/NEWS b/NEWS
index 34a969e8a..f4cdf9ecb 100644
--- a/NEWS
+++ b/NEWS
@@ -59,6 +59,9 @@ GNU coreutils NEWS -*- outline -*-
install -Z now also sets the default SELinux context for created directories.
+ ls is now fully responsive to signals until the first escape sequence is
+ written to a terminal.
+
stat and tail now know about "prl_fs" (a parallels file system),
"m1fs" (a Plexistor file system), "wslfs" (Windows Subsystem for Linux),
and "smb2". stat -f --format=%T now reports the file system type, and
diff --git a/src/ls.c b/src/ls.c
index 35720608c..4e50297d4 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -1244,13 +1244,12 @@ process_signals (void)
}
}
-int
-main (int argc, char **argv)
-{
- int i;
- struct pending *thispend;
- int n_files;
+/* Setup signal handlers if INIT is true,
+ otherwise restore to the default. */
+static void
+signal_setup (bool init)
+{
/* The signals that are trapped, and the number of such signals. */
static int const sig[] =
{
@@ -1278,8 +1277,77 @@ main (int argc, char **argv)
enum { nsigs = ARRAY_CARDINALITY (sig) };
#if ! SA_NOCLDSTOP
- bool caught_sig[nsigs];
+ static bool caught_sig[nsigs];
+#endif
+
+ int j;
+
+ if (init)
+ {
+#if SA_NOCLDSTOP
+ struct sigaction act;
+
+ sigemptyset (&caught_signals);
+ for (j = 0; j < nsigs; j++)
+ {
+ sigaction (sig[j], NULL, &act);
+ if (act.sa_handler != SIG_IGN)
+ sigaddset (&caught_signals, sig[j]);
+ }
+
+ act.sa_mask = caught_signals;
+ act.sa_flags = SA_RESTART;
+
+ for (j = 0; j < nsigs; j++)
+ if (sigismember (&caught_signals, sig[j]))
+ {
+ act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
+ sigaction (sig[j], &act, NULL);
+ }
+#else
+ for (j = 0; j < nsigs; j++)
+ {
+ caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
+ if (caught_sig[j])
+ {
+ signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
+ siginterrupt (sig[j], 0);
+ }
+ }
#endif
+ }
+ else /* restore. */
+ {
+#if SA_NOCLDSTOP
+ for (j = 0; j < nsigs; j++)
+ if (sigismember (&caught_signals, sig[j]))
+ signal (sig[j], SIG_DFL);
+#else
+ for (j = 0; j < nsigs; j++)
+ if (caught_sig[j])
+ signal (sig[j], SIG_DFL);
+#endif
+ }
+}
+
+static inline void
+signal_init (void)
+{
+ signal_setup (true);
+}
+
+static inline void
+signal_restore (void)
+{
+ signal_setup (false);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ struct pending *thispend;
+ int n_files;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -1314,46 +1382,6 @@ main (int argc, char **argv)
|| (is_colored (C_EXEC) && color_symlink_as_referent)
|| (is_colored (C_MISSING) && format == long_format))
check_symlink_color = true;
-
- /* If the standard output is a controlling terminal, watch out
- for signals, so that the colors can be restored to the
- default state if "ls" is suspended or interrupted. */
-
- if (0 <= tcgetpgrp (STDOUT_FILENO))
- {
- int j;
-#if SA_NOCLDSTOP
- struct sigaction act;
-
- sigemptyset (&caught_signals);
- for (j = 0; j < nsigs; j++)
- {
- sigaction (sig[j], NULL, &act);
- if (act.sa_handler != SIG_IGN)
- sigaddset (&caught_signals, sig[j]);
- }
-
- act.sa_mask = caught_signals;
- act.sa_flags = SA_RESTART;
-
- for (j = 0; j < nsigs; j++)
- if (sigismember (&caught_signals, sig[j]))
- {
- act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
- sigaction (sig[j], &act, NULL);
- }
-#else
- for (j = 0; j < nsigs; j++)
- {
- caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
- if (caught_sig[j])
- {
- signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
- siginterrupt (sig[j], 0);
- }
- }
-#endif
- }
}
if (dereference == DEREF_UNDEFINED)
@@ -1466,32 +1494,21 @@ main (int argc, char **argv)
print_dir_name = true;
}
- if (print_with_color)
+ if (print_with_color && used_color)
{
int j;
- if (used_color)
- {
- /* Skip the restore when it would be a no-op, i.e.,
- when left is "\033[" and right is "m". */
- if (!(color_indicator[C_LEFT].len == 2
- && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0
- && color_indicator[C_RIGHT].len == 1
- && color_indicator[C_RIGHT].string[0] == 'm'))
- restore_default_color ();
- }
+ /* Skip the restore when it would be a no-op, i.e.,
+ when left is "\033[" and right is "m". */
+ if (!(color_indicator[C_LEFT].len == 2
+ && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0
+ && color_indicator[C_RIGHT].len == 1
+ && color_indicator[C_RIGHT].string[0] == 'm'))
+ restore_default_color ();
+
fflush (stdout);
- /* Restore the default signal handling. */
-#if SA_NOCLDSTOP
- for (j = 0; j < nsigs; j++)
- if (sigismember (&caught_signals, sig[j]))
- signal (sig[j], SIG_DFL);
-#else
- for (j = 0; j < nsigs; j++)
- if (caught_sig[j])
- signal (sig[j], SIG_DFL);
-#endif
+ signal_restore ();
/* Act on any signals that arrived before the default was restored.
This can process signals out of order, but there doesn't seem to
@@ -4475,6 +4492,14 @@ put_indicator (const struct bin_str *ind)
if (! used_color)
{
used_color = true;
+
+ /* If the standard output is a controlling terminal, watch out
+ for signals, so that the colors can be restored to the
+ default state if "ls" is suspended or interrupted. */
+
+ if (0 <= tcgetpgrp (STDOUT_FILENO))
+ signal_init ();
+
prep_non_filename_text ();
}