/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
#include "stdio-util.h"
#include "string-util.h"
#include "terminal-util.h"
+#include "tmpfile-util.h"
#include "util.h"
-Seat *seat_new(Manager *m, const char *id) {
- Seat *s;
+int seat_new(Seat** ret, Manager *m, const char *id) {
+ _cleanup_(seat_freep) Seat *s = NULL;
+ int r;
+ assert(ret);
assert(m);
assert(id);
- s = new0(Seat, 1);
+ if (!seat_name_is_valid(id))
+ return -EINVAL;
+
+ s = new(Seat, 1);
if (!s)
- return NULL;
+ return -ENOMEM;
+
+ *s = (Seat) {
+ .manager = m,
+ };
s->state_file = strappend("/run/systemd/seats/", id);
if (!s->state_file)
- return mfree(s);
+ return -ENOMEM;
s->id = basename(s->state_file);
- s->manager = m;
- if (hashmap_put(m->seats, s->id, s) < 0) {
- free(s->state_file);
- return mfree(s);
- }
+ r = hashmap_put(m->seats, s->id, s);
+ if (r < 0)
+ return r;
- return s;
+ *ret = TAKE_PTR(s);
+ return 0;
}
-void seat_free(Seat *s) {
- assert(s);
+Seat* seat_free(Seat *s) {
+ if (!s)
+ return NULL;
if (s->in_gc_queue)
LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s);
free(s->positions);
free(s->state_file);
- free(s);
+
+ return mfree(s);
}
int seat_save(Seat *s) {
return 0;
}
-static int vt_allocate(unsigned int vtnr) {
- char p[sizeof("/dev/tty") + DECIMAL_STR_MAX(unsigned int)];
+static int vt_allocate(unsigned vtnr) {
+ char p[sizeof("/dev/tty") + DECIMAL_STR_MAX(unsigned)];
_cleanup_close_ int fd = -1;
assert(vtnr >= 1);
xsprintf(p, "/dev/tty%u", vtnr);
fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
- return -errno;
+ return fd;
return 0;
}
int q;
q = vt_allocate(i);
- if (q < 0) {
- log_error_errno(q, "Failed to preallocate VT %u: %m", i);
- r = q;
- }
+ if (q < 0)
+ r = log_error_errno(q, "Failed to preallocate VT %u: %m", i);
}
return r;
assert(s);
- r = devnode_acl_all(s->manager->udev,
- s->id,
+ r = devnode_acl_all(s->id,
false,
!!old_active, old_active ? old_active->user->uid : 0,
!!s->active, s->active ? s->active->user->uid : 0);
if (r < 0)
- log_error_errno(r, "Failed to apply ACLs: %m");
+ return log_error_errno(r, "Failed to apply ACLs: %m");
- return r;
+ return 0;
}
int seat_set_active(Seat *s, Session *session) {
session_send_changed(old_active, "Active", NULL);
}
- seat_apply_acls(s, old_active);
+ (void) seat_apply_acls(s, old_active);
if (session && session->started) {
session_send_changed(session, "Active", NULL);
return 0;
}
-int seat_switch_to(Seat *s, unsigned int num) {
+int seat_switch_to(Seat *s, unsigned num) {
/* Public session positions skip 0 (there is only F1-F12). Maybe it
* will get reassigned in the future, so return error for now. */
if (num == 0)
}
int seat_switch_to_next(Seat *s) {
- unsigned int start, i;
+ unsigned start, i;
if (s->position_count == 0)
return -EINVAL;
}
int seat_switch_to_previous(Seat *s) {
- unsigned int start, i;
+ unsigned start, i;
if (s->position_count == 0)
return -EINVAL;
return -EINVAL;
}
-int seat_active_vt_changed(Seat *s, unsigned int vtnr) {
+int seat_active_vt_changed(Seat *s, unsigned vtnr) {
Session *i, *new_active = NULL;
int r;
int seat_read_active_vt(Seat *s) {
char t[64];
ssize_t k;
- unsigned int vtnr;
- int r;
+ int vtnr;
assert(s);
k = read(s->manager->console_active_fd, t, sizeof(t)-1);
if (k <= 0) {
- log_error("Failed to read current console: %s", k < 0 ? strerror(-errno) : "EOF");
+ log_error("Failed to read current console: %s", k < 0 ? strerror(errno) : "EOF");
return k < 0 ? -errno : -EIO;
}
t[k] = 0;
truncate_nl(t);
- if (!startswith(t, "tty")) {
- log_error("Hm, /sys/class/tty/tty0/active is badly formatted.");
- return -EIO;
- }
-
- r = safe_atou(t+3, &vtnr);
- if (r < 0)
- return log_error_errno(r, "Failed to parse VT number \"%s\": %m", t+3);
-
- if (!vtnr) {
- log_error("VT number invalid: %s", t+3);
+ vtnr = vtnr_from_tty(t);
+ if (vtnr < 0) {
+ log_error_errno(vtnr, "Hm, /sys/class/tty/tty0/active is badly formatted: %m");
return -EIO;
}
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SEAT_START_STR,
"SEAT_ID=%s", s->id,
- LOG_MESSAGE("New seat %s.", s->id),
- NULL);
+ LOG_MESSAGE("New seat %s.", s->id));
/* Initialize VT magic stuff */
seat_preallocate_vts(s);
}
int seat_stop(Seat *s, bool force) {
- int r = 0;
+ int r;
assert(s);
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SEAT_STOP_STR,
"SEAT_ID=%s", s->id,
- LOG_MESSAGE("Removed seat %s.", s->id),
- NULL);
+ LOG_MESSAGE("Removed seat %s.", s->id));
- seat_stop_sessions(s, force);
+ r = seat_stop_sessions(s, force);
- unlink(s->state_file);
+ (void) unlink(s->state_file);
seat_add_to_gc_queue(s);
if (s->started)
void seat_evict_position(Seat *s, Session *session) {
Session *iter;
- unsigned int pos = session->position;
+ unsigned pos = session->position;
session->position = 0;
}
}
-void seat_claim_position(Seat *s, Session *session, unsigned int pos) {
+void seat_claim_position(Seat *s, Session *session, unsigned pos) {
/* with VTs, the position is always the same as the VTnr */
if (seat_has_vts(s))
pos = session->vtnr;
}
static void seat_assign_position(Seat *s, Session *session) {
- unsigned int pos;
+ unsigned pos;
if (session->position > 0)
return;
if (!s->pending_switch)
return;
- session = s->pending_switch;
- s->pending_switch = NULL;
+ session = TAKE_PTR(s->pending_switch);
seat_set_active(s, session);
}