#include "io-util.h"
#include "log.h"
#include "macro.h"
+#include "namespace-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
}
int getttyname_malloc(int fd, char **ret) {
- size_t l = 100;
+ char path[PATH_MAX], *c; /* PATH_MAX is counted *with* the trailing NUL byte */
int r;
assert(fd >= 0);
assert(ret);
- for (;;) {
- char path[l];
-
- r = ttyname_r(fd, path, sizeof(path));
- if (r == 0) {
- char *c;
-
- c = strdup(skip_dev_prefix(path));
- if (!c)
- return -ENOMEM;
-
- *ret = c;
- return 0;
- }
-
- if (r != ERANGE)
- return -r;
+ r = ttyname_r(fd, path, sizeof path); /* positive error */
+ assert(r >= 0);
+ if (r == ERANGE)
+ return -ENAMETOOLONG;
+ if (r > 0)
+ return -r;
- l *= 2;
- }
+ c = strdup(skip_dev_prefix(path));
+ if (!c)
+ return -ENOMEM;
+ *ret = c;
return 0;
}
-int getttyname_harder(int fd, char **r) {
- int k;
- char *s = NULL;
+int getttyname_harder(int fd, char **ret) {
+ _cleanup_free_ char *s = NULL;
+ int r;
- k = getttyname_malloc(fd, &s);
- if (k < 0)
- return k;
+ r = getttyname_malloc(fd, &s);
+ if (r < 0)
+ return r;
- if (streq(s, "tty")) {
- free(s);
- return get_ctty(0, NULL, r);
- }
+ if (streq(s, "tty"))
+ return get_ctty(0, NULL, ret);
- *r = s;
+ *ret = TAKE_PTR(s);
return 0;
}
}
free(c);
+
+ if (l > SIZE_MAX / 2)
+ return -ENOMEM;
+
l *= 2;
}
}
-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) {
* (which is the explicit way to turn colors on/off). If that didn't work we turn colors off unless we are on a
* TTY. And if we are on a TTY we turn it off if $TERM is set to "dumb". There's one special tweak though: if
* we are PID 1 then we do not check whether we are connected to a TTY, because we don't keep /dev/console open
- * continously due to fear of SAK, and hence things are a bit weird. */
+ * continuously due to fear of SAK, and hence things are a bit weird. */
if (cached_colors_enabled < 0) {
int val;
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;
+ }
+}