chiark / gitweb /
terminal-util: use getenv_bool for $SYSTEMD_COLORS
[elogind.git] / src / basic / terminal-util.c
index 20c4df74dfefffabc290d47c2ec9926620c4bea1..215b764882b95dbde54dc09b599b0a948776de1f 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <assert.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <sys/socket.h>
+#include <sys/sysmacros.h>
+#include <sys/time.h>
 #include <linux/kd.h>
 #include <linux/tiocl.h>
 #include <linux/vt.h>
 #include <poll.h>
 #include <signal.h>
 #include <sys/ioctl.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 #include <termios.h>
-#include <time.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "io-util.h"
+#include "log.h"
+#include "macro.h"
 #include "parse-util.h"
-#include "path-util.h"
 #include "process-util.h"
 #include "socket-util.h"
 #include "stat-util.h"
 #include "string-util.h"
+#include "strv.h"
 #include "terminal-util.h"
 #include "time-util.h"
 #include "util.h"
@@ -74,6 +83,7 @@ int chvt(int vt) {
         return 0;
 }
 
+#if 0 /// UNNEEDED by elogind
 int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
         struct termios old_termios, new_termios;
         char c, line[LINE_MAX];
@@ -120,7 +130,7 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
 
         errno = 0;
         if (!fgets(line, sizeof(line), f))
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         truncate_nl(line);
 
@@ -134,8 +144,6 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
         return 0;
 }
 
-/// UNNEEDED by elogind
-#if 0
 int ask_char(char *ret, const char *replies, const char *text, ...) {
         int r;
 
@@ -148,14 +156,14 @@ int ask_char(char *ret, const char *replies, const char *text, ...) {
                 char c;
                 bool need_nl = true;
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_HIGHLIGHT, stdout);
 
                 va_start(ap, text);
                 vprintf(text, ap);
                 va_end(ap);
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_NORMAL, stdout);
 
                 fflush(stdout);
@@ -192,21 +200,21 @@ int ask_string(char **ret, const char *text, ...) {
                 char line[LINE_MAX];
                 va_list ap;
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_HIGHLIGHT, stdout);
 
                 va_start(ap, text);
                 vprintf(text, ap);
                 va_end(ap);
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_NORMAL, stdout);
 
                 fflush(stdout);
 
                 errno = 0;
                 if (!fgets(line, sizeof(line), stdin))
-                        return errno ? -errno : -EIO;
+                        return errno > 0 ? -errno : -EIO;
 
                 if (!endswith(line, "\n"))
                         putchar('\n');
@@ -226,7 +234,6 @@ int ask_string(char **ret, const char *text, ...) {
                 }
         }
 }
-#endif // 0
 
 int reset_terminal_fd(int fd, bool switch_to_text) {
         struct termios termios;
@@ -305,6 +312,7 @@ int reset_terminal(const char *name) {
 
         return reset_terminal_fd(fd, true);
 }
+#endif // 0
 
 int open_terminal(const char *name, int mode) {
         int fd, r;
@@ -352,6 +360,7 @@ int open_terminal(const char *name, int mode) {
         return fd;
 }
 
+#if 0 /// UNNEEDED by elogind
 int acquire_terminal(
                 const char *name,
                 bool fail,
@@ -499,9 +508,9 @@ fail:
 
         return r;
 }
+#endif // 0
 
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
 int release_terminal(void) {
         static const struct sigaction sa_new = {
                 .sa_handler = SIG_IGN,
@@ -527,7 +536,6 @@ int release_terminal(void) {
 
         return r;
 }
-#endif // 0
 
 int terminal_vhangup_fd(int fd) {
         assert(fd >= 0);
@@ -614,8 +622,6 @@ int vt_disallocate(const char *name) {
         return 0;
 }
 
-/// UNNEEDED by elogind
-#if 0
 int make_console_stdio(void) {
         int fd, r;
 
@@ -676,6 +682,7 @@ int vtnr_from_tty(const char *tty) {
         return i;
 }
 
+#if 0 /// UNNEEDED by elogind
 char *resolve_dev_console(char **active) {
         char *tty;
 
@@ -709,6 +716,64 @@ char *resolve_dev_console(char **active) {
         return tty;
 }
 
+int get_kernel_consoles(char ***consoles) {
+        _cleanup_strv_free_ char **con = NULL;
+        _cleanup_free_ char *line = NULL;
+        const char *active;
+        int r;
+
+        assert(consoles);
+
+        r = read_one_line_file("/sys/class/tty/console/active", &line);
+        if (r < 0)
+                return r;
+
+        active = line;
+        for (;;) {
+                _cleanup_free_ char *tty = NULL;
+                char *path;
+
+                r = extract_first_word(&active, &tty, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                if (streq(tty, "tty0")) {
+                        tty = mfree(tty);
+                        r = read_one_line_file("/sys/class/tty/tty0/active", &tty);
+                        if (r < 0)
+                                return r;
+                }
+
+                path = strappend("/dev/", tty);
+                if (!path)
+                        return -ENOMEM;
+
+                if (access(path, F_OK) < 0) {
+                        log_debug_errno(errno, "Console device %s is not accessible, skipping: %m", path);
+                        free(path);
+                        continue;
+                }
+
+                r = strv_consume(&con, path);
+                if (r < 0)
+                        return r;
+        }
+
+        if (strv_isempty(con)) {
+                log_debug("No devices found for system console");
+
+                r = strv_extend(&con, "/dev/console");
+                if (r < 0)
+                        return r;
+        }
+
+        *consoles = con;
+        con = NULL;
+        return 0;
+}
+
 bool tty_is_vc_resolve(const char *tty) {
         _cleanup_free_ char *active = NULL;
 
@@ -726,12 +791,8 @@ bool tty_is_vc_resolve(const char *tty) {
         return tty_is_vc(tty);
 }
 
-/// UNNEEDED by elogind
-#if 0
 const char *default_term_for_tty(const char *tty) {
-        assert(tty);
-
-        return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
+        return tty && tty_is_vc_resolve(tty) ? "linux" : "vt220";
 }
 #endif // 0
 
@@ -804,8 +865,7 @@ unsigned lines(void) {
 }
 
 /* intended to be used as a SIGWINCH sighandler */
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
 void columns_lines_cache_reset(int signum) {
         cached_columns = 0;
         cached_lines = 0;
@@ -838,9 +898,7 @@ int make_stdio(int fd) {
 
         /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
          * dup2() was a NOP and the bit hence possibly set. */
-        fd_cloexec(STDIN_FILENO, false);
-        fd_cloexec(STDOUT_FILENO, false);
-        fd_cloexec(STDERR_FILENO, false);
+        stdio_unset_cloexec();
 
         return 0;
 }
@@ -855,8 +913,6 @@ int make_null_stdio(void) {
         return make_stdio(null_fd);
 }
 
-/// UNNEEDED by elogind
-#if 0
 int getttyname_malloc(int fd, char **ret) {
         size_t l = 100;
         int r;
@@ -906,7 +962,6 @@ int getttyname_harder(int fd, char **r) {
         *r = s;
         return 0;
 }
-#endif // 0
 
 int get_ctty_devnr(pid_t pid, dev_t *d) {
         int r;
@@ -999,8 +1054,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
         return 0;
 }
 
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
 int ptsname_malloc(int fd, char **ret) {
         size_t l = 100;
 
@@ -1148,3 +1202,39 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
         return receive_one_fd(pair[0], 0);
 }
 #endif // 0
+
+static bool getenv_terminal_is_dumb(void) {
+        const char *e;
+
+        e = getenv("TERM");
+        if (!e)
+                return true;
+
+        return streq(e, "dumb");
+}
+
+bool terminal_is_dumb(void) {
+        if (!on_tty())
+                return true;
+
+        return getenv_terminal_is_dumb();
+}
+
+bool colors_enabled(void) {
+        static int enabled = -1;
+
+        if (_unlikely_(enabled < 0)) {
+                int val;
+
+                val = getenv_bool("SYSTEMD_COLORS");
+                if (val >= 0)
+                        enabled = val;
+                else if (getpid() == 1)
+                        /* PID1 outputs to the console without holding it open all the time */
+                        enabled = !getenv_terminal_is_dumb();
+                else
+                        enabled = !terminal_is_dumb();
+        }
+
+        return enabled;
+}