mirror of
https://github.com/systemd/systemd.git
synced 2024-11-27 12:13:33 +08:00
sd-login: add SetTTY session object #26611
This commit is contained in:
parent
4d26b2277a
commit
092e6cd19a
@ -1083,6 +1083,7 @@ node /org/freedesktop/login1/session/1 {
|
||||
ReleaseControl();
|
||||
SetType(in s type);
|
||||
SetDisplay(in s display);
|
||||
SetTTY(in h tty_fd);
|
||||
TakeDevice(in u major,
|
||||
in u minor,
|
||||
out h fd,
|
||||
@ -1182,6 +1183,8 @@ node /org/freedesktop/login1/session/1 {
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="SetDisplay()"/>
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="SetTTY()"/>
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="TakeDevice()"/>
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="ReleaseDevice()"/>
|
||||
@ -1283,6 +1286,11 @@ node /org/freedesktop/login1/session/1 {
|
||||
controller. If <function>TakeControl()</function> has not been called, this method will fail. The only argument
|
||||
<varname>display</varname> is the new display name.</para>
|
||||
|
||||
<para><function>SetTTY()</function> allows the device name of the session to be changed. This is
|
||||
useful if the tty device is only known after authentication. It can only be called by session's
|
||||
current controller. If <function>TakeControl()</function> has not been called, this method will fail.
|
||||
The only argument <varname>tty_fd</varname> is a file handle to the new tty device.</para>
|
||||
|
||||
<para><function>TakeDevice()</function> allows a session controller to get a file descriptor for a
|
||||
specific device. Pass in the major and minor numbers of the character device and
|
||||
<filename>systemd-logind</filename> will return a file descriptor for the device. Only a limited set of
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "path-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
static int property_get_user(
|
||||
@ -421,6 +422,41 @@ static int method_set_display(sd_bus_message *message, void *userdata, sd_bus_er
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int method_set_tty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Session *s = ASSERT_PTR(userdata);
|
||||
int fd, r, flags;
|
||||
_cleanup_free_ char *q = NULL;
|
||||
|
||||
assert(message);
|
||||
|
||||
r = sd_bus_message_read(message, "h", &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!session_is_controller(s, sd_bus_message_get_sender(message)))
|
||||
return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set tty");
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags < 0)
|
||||
return -errno;
|
||||
if ((flags & O_ACCMODE) != O_RDWR)
|
||||
return -EACCES;
|
||||
if (FLAGS_SET(flags, O_PATH))
|
||||
return -ENOTTY;
|
||||
|
||||
r = getttyname_malloc(fd, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = session_set_tty(s, q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Session *s = ASSERT_PTR(userdata);
|
||||
uint32_t major, minor;
|
||||
@ -909,6 +945,11 @@ static const sd_bus_vtable session_vtable[] = {
|
||||
SD_BUS_NO_RESULT,
|
||||
method_set_display,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD_WITH_ARGS("SetTTY",
|
||||
SD_BUS_ARGS("h", tty_fd),
|
||||
SD_BUS_NO_RESULT,
|
||||
method_set_tty,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD_WITH_ARGS("TakeDevice",
|
||||
SD_BUS_ARGS("u", major, "u", minor),
|
||||
SD_BUS_RESULT("h", fd, "b", inactive),
|
||||
|
@ -1132,6 +1132,23 @@ int session_set_display(Session *s, const char *display) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int session_set_tty(Session *s, const char *tty) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(tty);
|
||||
|
||||
r = free_and_strdup(&s->tty, tty);
|
||||
if (r <= 0) /* 0 means the strings were equal */
|
||||
return r;
|
||||
|
||||
session_save(s);
|
||||
|
||||
session_send_changed(s, "TTY", NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
||||
Session *s = ASSERT_PTR(userdata);
|
||||
|
||||
@ -1349,6 +1366,9 @@ error:
|
||||
static void session_restore_vt(Session *s) {
|
||||
int r;
|
||||
|
||||
if (s->vtfd < 0)
|
||||
return;
|
||||
|
||||
r = vt_restore(s->vtfd);
|
||||
if (r == -EIO) {
|
||||
int vt, old_fd;
|
||||
|
@ -140,6 +140,7 @@ int session_get_locked_hint(Session *s);
|
||||
void session_set_locked_hint(Session *s, bool b);
|
||||
void session_set_type(Session *s, SessionType t);
|
||||
int session_set_display(Session *s, const char *display);
|
||||
int session_set_tty(Session *s, const char *tty);
|
||||
int session_create_fifo(Session *s);
|
||||
int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error);
|
||||
int session_stop(Session *s, bool force);
|
||||
|
@ -350,6 +350,10 @@
|
||||
send_interface="org.freedesktop.login1.Session"
|
||||
send_member="SetDisplay"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.login1"
|
||||
send_interface="org.freedesktop.login1.Session"
|
||||
send_member="SetTTY"/>
|
||||
|
||||
<allow receive_sender="org.freedesktop.login1"/>
|
||||
</policy>
|
||||
|
||||
|
@ -6,10 +6,16 @@
|
||||
* ./test-session-properties /org/freedesktop/login1/session/_32
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-locator.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
static BusLocator session;
|
||||
@ -94,6 +100,32 @@ TEST(set_display) {
|
||||
assert_se(isempty(display));
|
||||
}
|
||||
|
||||
/* Tests org.freedesktop.logind.Session SetTTY */
|
||||
TEST(set_tty) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus* bus = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_free_ char *tty = NULL;
|
||||
const char *path = "/dev/tty2"; /* testsuite uses tty2 */
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
assert_se(sd_bus_open_system(&bus) >= 0);
|
||||
|
||||
/* tty can only be set by the session controller (which we're not ATM) */
|
||||
assert_se(bus_call_method(bus, &session, "SetTTY", &error, NULL, "h", fd) < 0);
|
||||
assert_se(sd_bus_error_has_name(&error, BUS_ERROR_NOT_IN_CONTROL));
|
||||
|
||||
assert_se(bus_call_method(bus, &session, "TakeControl", NULL, NULL, "b", true) >= 0);
|
||||
|
||||
/* tty can be set */
|
||||
assert_se(bus_call_method(bus, &session, "SetTTY", NULL, NULL, "h", fd) >= 0);
|
||||
tty = mfree(tty);
|
||||
assert_se(bus_get_property_string(bus, &session, "TTY", NULL, &tty) >= 0);
|
||||
assert_se(streq(tty, "tty2"));
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
if (saved_argc <= 1)
|
||||
return EXIT_FAILURE;
|
||||
|
Loading…
Reference in New Issue
Block a user