mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
terminal-util: introduce terminal_{new,detach}_session helpers (#35811)
This commit is contained in:
@@ -498,6 +498,22 @@ int release_terminal(void) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int terminal_new_session(void) {
|
||||
|
||||
/* Make us the new session leader, and set stdin tty to be our controlling terminal.
|
||||
*
|
||||
* Why stdin? Well, the ctty logic is relevant for signal delivery mostly, i.e. if people hit C-c
|
||||
* or the line is hung up. Such events are basically just a form of input, via a side channel
|
||||
* (that side channel being signal delivery, i.e. SIGINT, SIGHUP et al). Hence we focus on input,
|
||||
* not output here. */
|
||||
|
||||
if (!isatty_safe(STDIN_FILENO))
|
||||
return -ENXIO;
|
||||
|
||||
(void) setsid();
|
||||
return RET_NERRNO(ioctl(STDIN_FILENO, TIOCSCTTY, 0));
|
||||
}
|
||||
|
||||
int terminal_vhangup_fd(int fd) {
|
||||
assert(fd >= 0);
|
||||
return RET_NERRNO(ioctl(fd, TIOCVHANGUP));
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "time-util.h"
|
||||
@@ -64,18 +65,11 @@ typedef enum AcquireTerminalFlags {
|
||||
int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout);
|
||||
int release_terminal(void);
|
||||
|
||||
/* Limits the use of ANSI colors to a subset. */
|
||||
typedef enum ColorMode {
|
||||
COLOR_OFF, /* No colors, monochrome output. */
|
||||
COLOR_16, /* Only the base 16 colors. */
|
||||
COLOR_256, /* Only 256 colors. */
|
||||
COLOR_24BIT, /* For truecolor or 24bit color support, no restriction. */
|
||||
_COLOR_MODE_MAX,
|
||||
_COLOR_MODE_INVALID = -EINVAL,
|
||||
} ColorMode;
|
||||
|
||||
const char* color_mode_to_string(ColorMode m) _const_;
|
||||
ColorMode color_mode_from_string(const char *s) _pure_;
|
||||
int terminal_new_session(void);
|
||||
static inline void terminal_detach_session(void) {
|
||||
(void) setsid();
|
||||
(void) release_terminal();
|
||||
}
|
||||
|
||||
int terminal_vhangup_fd(int fd);
|
||||
int terminal_vhangup(const char *tty);
|
||||
@@ -117,15 +111,29 @@ void reset_terminal_feature_caches(void);
|
||||
bool on_tty(void);
|
||||
bool getenv_terminal_is_dumb(void);
|
||||
bool terminal_is_dumb(void);
|
||||
ColorMode get_color_mode(void);
|
||||
bool underline_enabled(void);
|
||||
bool dev_console_colors_enabled(void);
|
||||
|
||||
/* Limits the use of ANSI colors to a subset. */
|
||||
typedef enum ColorMode {
|
||||
COLOR_OFF, /* No colors, monochrome output. */
|
||||
COLOR_16, /* Only the base 16 colors. */
|
||||
COLOR_256, /* Only 256 colors. */
|
||||
COLOR_24BIT, /* For truecolor or 24bit color support, no restriction. */
|
||||
_COLOR_MODE_MAX,
|
||||
_COLOR_MODE_INVALID = -EINVAL,
|
||||
} ColorMode;
|
||||
|
||||
const char* color_mode_to_string(ColorMode m) _const_;
|
||||
ColorMode color_mode_from_string(const char *s) _pure_;
|
||||
|
||||
ColorMode get_color_mode(void);
|
||||
static inline bool colors_enabled(void) {
|
||||
/* Returns true if colors are considered supported on our stdout. */
|
||||
return get_color_mode() != COLOR_OFF;
|
||||
}
|
||||
|
||||
bool underline_enabled(void);
|
||||
bool dev_console_colors_enabled(void);
|
||||
|
||||
int get_ctty_devnr(pid_t pid, dev_t *ret);
|
||||
int get_ctty(pid_t, dev_t *ret_devnr, char **ret);
|
||||
|
||||
|
||||
@@ -2971,12 +2971,9 @@ static void setup_console_terminal(bool skip_setup) {
|
||||
if (arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)
|
||||
return;
|
||||
|
||||
/* Become a session leader if we aren't one yet. */
|
||||
(void) setsid();
|
||||
|
||||
/* If we are init, we connect stdin/stdout/stderr to /dev/null and make sure we don't have a
|
||||
* controlling tty. */
|
||||
(void) release_terminal();
|
||||
terminal_detach_session();
|
||||
|
||||
/* Reset the console, but only if this is really init and we are freshly booted */
|
||||
if (!skip_setup)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "tests.h"
|
||||
@@ -314,4 +315,36 @@ TEST(pty_open_peer) {
|
||||
assert(buf[1] == x[1]);
|
||||
}
|
||||
|
||||
TEST(terminal_new_session) {
|
||||
_cleanup_close_ int pty_fd = -EBADF, peer_fd = -EBADF;
|
||||
int r;
|
||||
|
||||
ASSERT_OK(pty_fd = openpt_allocate(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK, NULL));
|
||||
ASSERT_OK(peer_fd = pty_open_peer(pty_fd, O_RDWR|O_NOCTTY|O_CLOEXEC));
|
||||
|
||||
r = safe_fork_full("test-term-session",
|
||||
(int[]) { peer_fd, peer_fd, peer_fd },
|
||||
NULL, 0,
|
||||
FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT|FORK_REARRANGE_STDIO,
|
||||
NULL);
|
||||
ASSERT_OK(r);
|
||||
if (r == 0) {
|
||||
ASSERT_OK(terminal_new_session());
|
||||
ASSERT_OK(get_ctty_devnr(0, NULL));
|
||||
|
||||
terminal_detach_session();
|
||||
ASSERT_ERROR(get_ctty_devnr(0, NULL), ENXIO);
|
||||
|
||||
ASSERT_OK(terminal_new_session());
|
||||
ASSERT_OK(get_ctty_devnr(0, NULL));
|
||||
|
||||
terminal_detach_session();
|
||||
ASSERT_OK(rearrange_stdio(-EBADF, STDOUT_FILENO, STDERR_FILENO));
|
||||
ASSERT_ERROR(get_ctty_devnr(0, NULL), ENXIO);
|
||||
ASSERT_ERROR(terminal_new_session(), ENXIO);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
@@ -725,15 +725,10 @@ static int run(int argc, char *argv[]) {
|
||||
*/
|
||||
return ask_on_consoles(argv);
|
||||
|
||||
if (arg_device) {
|
||||
/*
|
||||
* Later on, a controlling terminal will be acquired,
|
||||
* therefore the current process has to become a session
|
||||
* leader and should not have a controlling terminal already.
|
||||
*/
|
||||
(void) setsid();
|
||||
(void) release_terminal();
|
||||
}
|
||||
if (arg_device)
|
||||
/* Later on, a controlling terminal will be acquired, therefore the current process has to
|
||||
* become a session leader and should not have a controlling terminal already. */
|
||||
terminal_detach_session();
|
||||
|
||||
return process_and_watch_password_files(!IN_SET(arg_action, ACTION_QUERY, ACTION_LIST));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "process-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "udev-config.h"
|
||||
#include "udev-manager.h"
|
||||
#include "udevd.h"
|
||||
@@ -74,7 +75,7 @@ int run_udevd(int argc, char *argv[]) {
|
||||
return 0;
|
||||
|
||||
/* child */
|
||||
(void) setsid();
|
||||
terminal_detach_session();
|
||||
}
|
||||
|
||||
return manager_main(manager);
|
||||
|
||||
Reference in New Issue
Block a user