summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2002-11-09 22:27:27 +0000
committerJim Meyering <jim@meyering.net>2002-11-09 22:27:27 +0000
commit85490682b7297846a8258ebc05e409330bb3255d (patch)
tree3c6addada5a6d2fae8bd78c7a5d198b73dc940bd /src
parentcd0013e0eac4a9a15323ace11deb5cdce185c768 (diff)
downloadcoreutils-85490682b7297846a8258ebc05e409330bb3255d.tar.xz
ls --color: restore terminal state (color) upon signal.
Include "full-write.h" and <signal.h>. (restore_default_color, restore_default_color_handler): New functions. (sigtstp_handler, put_indicator_direct): New functions. (main) [print_with_color]: Register signal handlers. Patch mostly by Solar Designer and Stanislav Ievlev.
Diffstat (limited to 'src')
-rw-r--r--src/ls.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/ls.c b/src/ls.c
index 7c7a03b91..e6958b372 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -62,6 +62,7 @@
#include <grp.h>
#include <pwd.h>
#include <getopt.h>
+#include <signal.h>
/* Get MB_CUR_MAX. */
#if HAVE_STDLIB_H
@@ -104,6 +105,7 @@ int wcwidth ();
#include "dirname.h"
#include "dirfd.h"
#include "error.h"
+#include "full-write.h"
#include "hard-locale.h"
#include "hash.h"
#include "human.h"
@@ -268,6 +270,7 @@ static uintmax_t gobble_file PARAMS ((const char *name, enum filetype type,
static void print_color_indicator PARAMS ((const char *name, mode_t mode,
int linkok));
static void put_indicator PARAMS ((const struct bin_str *ind));
+static int put_indicator_direct PARAMS ((const struct bin_str *ind));
static int length_of_file_name_and_frills PARAMS ((const struct fileinfo *f));
static void add_ignore_pattern PARAMS ((const char *pattern));
static void attach PARAMS ((char *dest, const char *dirname, const char *name));
@@ -994,6 +997,28 @@ free_pending_ent (struct pending *p)
free (p);
}
+static void
+restore_default_color (void)
+{
+ if (put_indicator_direct (&color_indicator[C_LEFT]) == 0)
+ put_indicator_direct (&color_indicator[C_RIGHT]);
+}
+
+static void
+restore_default_color_handler (int signum)
+{
+ restore_default_color ();
+ _exit (128 + signum);
+}
+
+static void
+sigtstp_handler (int signum)
+{
+ signal (SIGTSTP, sigtstp_handler);
+ restore_default_color ();
+ raise (SIGSTOP);
+}
+
int
main (int argc, char **argv)
{
@@ -1031,6 +1056,11 @@ main (int argc, char **argv)
|| (color_indicator[C_MISSING].string != NULL
&& format == long_format))
check_symlink_color = 1;
+
+ signal (SIGINT, restore_default_color_handler);
+ signal (SIGTERM, restore_default_color_handler);
+ signal (SIGQUIT, restore_default_color_handler);
+ signal (SIGTSTP, sigtstp_handler);
}
if (dereference == DEREF_UNDEFINED)
@@ -3307,6 +3337,20 @@ put_indicator (const struct bin_str *ind)
putchar (*(p++));
}
+/* Output a color indicator, but don't use stdio, for use from signal handlers.
+ Return zero if the write is successful or if the string length is zero.
+ Return nonzero if the write fails. */
+static int
+put_indicator_direct (const struct bin_str *ind)
+{
+ size_t len;
+ if (ind->len <= 0)
+ return 0;
+
+ len = ind->len;
+ return (full_write (STDOUT_FILENO, ind->string, len) != len);
+}
+
static int
length_of_file_name_and_frills (const struct fileinfo *f)
{