}
}
-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
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;
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);
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) {
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;
};
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);
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;
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;
+ }
+}