]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/terminal-util.c
terminal-util: introduce openpt_allocate()
[thirdparty/systemd.git] / src / basic / terminal-util.c
index a2ea3212431549cad1dfc03fe9b8602a3072ffbc..aa69bede6f5fb63e133f6c38ae22c73d46c7ce6f 100644 (file)
@@ -1049,7 +1049,34 @@ int ptsname_malloc(int fd, char **ret) {
         }
 }
 
-int ptsname_namespace(int pty, char **ret) {
+int openpt_allocate(int flags, char **ret_slave) {
+        _cleanup_close_ int fd = -1;
+        _cleanup_free_ char *p = NULL;
+        int r;
+
+        fd = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return -errno;
+
+        if (ret_slave) {
+                r = ptsname_malloc(fd, &p);
+                if (r < 0)
+                        return r;
+
+                if (!path_startswith(p, "/dev/pts/"))
+                        return -EINVAL;
+        }
+
+        if (unlockpt(fd) < 0)
+                return -errno;
+
+        if (ret_slave)
+                *ret_slave = TAKE_PTR(p);
+
+        return TAKE_FD(fd);
+}
+
+static int ptsname_namespace(int pty, char **ret) {
         int no = -1, r;
 
         /* Like ptsname(), but doesn't assume that the path is
@@ -1068,8 +1095,8 @@ int ptsname_namespace(int pty, char **ret) {
         return 0;
 }
 
-int openpt_in_namespace(pid_t pid, int flags) {
-        _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
+int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_slave) {
+        _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1, fd = -1;
         _cleanup_close_pair_ int pair[2] = { -1, -1 };
         pid_t child;
         int r;
@@ -1088,18 +1115,13 @@ int openpt_in_namespace(pid_t pid, int flags) {
         if (r < 0)
                 return r;
         if (r == 0) {
-                int master;
-
                 pair[0] = safe_close(pair[0]);
 
-                master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
-                if (master < 0)
-                        _exit(EXIT_FAILURE);
-
-                if (unlockpt(master) < 0)
+                fd = openpt_allocate(flags, NULL);
+                if (fd < 0)
                         _exit(EXIT_FAILURE);
 
-                if (send_one_fd(pair[1], master, 0) < 0)
+                if (send_one_fd(pair[1], fd, 0) < 0)
                         _exit(EXIT_FAILURE);
 
                 _exit(EXIT_SUCCESS);
@@ -1113,7 +1135,17 @@ int openpt_in_namespace(pid_t pid, int flags) {
         if (r != EXIT_SUCCESS)
                 return -EIO;
 
-        return receive_one_fd(pair[0], 0);
+        fd = receive_one_fd(pair[0], 0);
+        if (fd < 0)
+                return fd;
+
+        if (ret_slave) {
+                r = ptsname_namespace(fd, ret_slave);
+                if (r < 0)
+                        return r;
+        }
+
+        return TAKE_FD(fd);
 }
 
 int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
@@ -1249,12 +1281,36 @@ int vt_default_utf8(void) {
         return parse_boolean(b);
 }
 
+int vt_verify_kbmode(int fd) {
+        int curr_mode;
+
+        /*
+         * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
+         * Otherwise we would (likely) interfere with X11's processing of the
+         * key events.
+         *
+         * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
+         */
+
+        if (ioctl(fd, KDGKBMODE, &curr_mode) < 0)
+                return -errno;
+
+        return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
+}
+
 int vt_reset_keyboard(int fd) {
-        int kb;
+        int kb, r;
 
         /* If we can't read the default, then default to unicode. It's 2017 after all. */
         kb = vt_default_utf8() != 0 ? K_UNICODE : K_XLATE;
 
+        r = vt_verify_kbmode(fd);
+        if (r == -EBUSY) {
+                log_debug_errno(r, "Keyboard is not in XLATE or UNICODE mode, not resetting: %m");
+                return 0;
+        } else if (r < 0)
+                return r;
+
         if (ioctl(fd, KDSKBMODE, kb) < 0)
                 return -errno;
 
@@ -1267,8 +1323,7 @@ int vt_restore(int fd) {
         };
         int r, q = 0;
 
-        r = ioctl(fd, KDSETMODE, KD_TEXT);
-        if (r < 0)
+        if (ioctl(fd, KDSETMODE, KD_TEXT) < 0)
                 q = log_debug_errno(errno, "Failed to set VT in text mode, ignoring: %m");
 
         r = vt_reset_keyboard(fd);
@@ -1278,18 +1333,17 @@ int vt_restore(int fd) {
                         q = r;
         }
 
-        r = ioctl(fd, VT_SETMODE, &mode);
-        if (r < 0) {
+        if (ioctl(fd, VT_SETMODE, &mode) < 0) {
                 log_debug_errno(errno, "Failed to set VT_AUTO mode, ignoring: %m");
                 if (q >= 0)
                         q = -errno;
         }
 
-        r = fchown(fd, 0, (gid_t) -1);
+        r = fchmod_and_chown(fd, TTY_MODE, 0, (gid_t) -1);
         if (r < 0) {
-                log_debug_errno(errno, "Failed to chown VT, ignoring: %m");
+                log_debug_errno(r, "Failed to chmod()/chown() VT, ignoring: %m");
                 if (q >= 0)
-                        q = -errno;
+                        q = r;
         }
 
         return q;
@@ -1310,3 +1364,41 @@ int vt_release(int fd, bool restore) {
 
         return 0;
 }
+
+void get_log_colors(int priority, const char **on, const char **off, const char **highlight) {
+        /* Note that this will initialize output variables only when there's something to output.
+         * The caller must pre-initalize to "" or NULL as appropriate. */
+
+        if (priority <= LOG_ERR) {
+                if (on)
+                        *on = ANSI_HIGHLIGHT_RED;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT;
+
+        } else if (priority <= LOG_WARNING) {
+                if (on)
+                        *on = ANSI_HIGHLIGHT_YELLOW;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT;
+
+        } else if (priority <= LOG_NOTICE) {
+                if (on)
+                        *on = ANSI_HIGHLIGHT;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT_RED;
+
+        } else if (priority >= LOG_DEBUG) {
+                if (on)
+                        *on = ANSI_GREY;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT_RED;
+        }
+}