/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 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 <getopt.h>
#include "bus-util.h"
#include "cgroup-show.h"
#include "cgroup-util.h"
+#include "format-table.h"
#include "log.h"
#include "logs-show.h"
#include "macro.h"
+#include "main-func.h"
#include "pager.h"
#include "parse-util.h"
+#include "pretty-print.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "sigbus.h"
#include "signal-util.h"
#include "spawn-polkit-agent.h"
+#include "string-table.h"
#include "strv.h"
#include "sysfs-show.h"
#include "terminal-util.h"
static bool arg_all = false;
static bool arg_value = false;
static bool arg_full = false;
-static bool arg_no_pager = false;
+static PagerFlags arg_pager_flags = 0;
static bool arg_legend = true;
static const char *arg_kill_who = NULL;
static int arg_signal = SIGTERM;
static unsigned arg_lines = 10;
static OutputMode arg_output = OUTPUT_SHORT;
+STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
+
static OutputFlags get_output_flags(void) {
return
return 0;
}
+static int show_table(Table *table, const char *word) {
+ int r;
+
+ assert(table);
+ assert(word);
+
+ if (table_get_rows(table) > 1) {
+ r = table_set_sort(table, (size_t) 0, (size_t) -1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to sort table: %m");
+
+ table_set_header(table, arg_legend);
+
+ r = table_print(table, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to show table: %m");
+ }
+
+ if (arg_legend) {
+ if (table_get_rows(table) > 1)
+ printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word);
+ else
+ printf("No %s.\n", word);
+ }
+
+ return 0;
+}
+
static int list_sessions(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *id, *user, *seat, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
- uint32_t uid;
int r;
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(
bus,
"org.freedesktop.login1.Manager",
"ListSessions",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list sessions: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list sessions: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(susso)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%10s %10s %-16s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT", "TTY");
+ table = table_new("SESSION", "UID", "USER", "SEAT", "TTY");
+ if (!table)
+ return log_oom();
- while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
- _cleanup_(sd_bus_error_free) sd_bus_error error2 = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply2 = NULL;
- _cleanup_free_ char *path = NULL;
- const char *tty = NULL;
+ /* Right-align the first two fields (since they are numeric) */
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(1), 100);
- r = get_session_path(bus, id, &error2, &path);
+ for (;;) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_tty = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_tty = NULL;
+ const char *id, *user, *seat, *object, *tty = NULL;
+ uint32_t uid;
+
+ r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = sd_bus_get_property(
+ bus,
+ "org.freedesktop.login1",
+ object,
+ "org.freedesktop.login1.Session",
+ "TTY",
+ &error_tty,
+ &reply_tty,
+ "s");
if (r < 0)
- log_warning("Failed to get session path: %s", bus_error_message(&error, r));
+ log_warning_errno(r, "Failed to get TTY for session %s: %s", id, bus_error_message(&error_tty, r));
else {
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.login1.Session",
- "TTY",
- &error2,
- &reply2,
- "s");
+ r = sd_bus_message_read(reply_tty, "s", &tty);
if (r < 0)
- log_warning("Failed to get TTY for session %s: %s",
- id, bus_error_message(&error2, r));
- else {
- r = sd_bus_message_read(reply2, "s", &tty);
- if (r < 0)
- return bus_log_parse_error(r);
- }
+ return bus_log_parse_error(r);
}
- printf("%10s %10"PRIu32" %-16s %-16s %-16s\n", id, uid, user, seat, strna(tty));
- k++;
+ r = table_add_many(table,
+ TABLE_STRING, id,
+ TABLE_UINT32, uid,
+ TABLE_STRING, user,
+ TABLE_STRING, seat,
+ TABLE_STRING, strna(tty));
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u sessions listed.\n", k);
-
- return 0;
+ return show_table(table, "sessions");
}
static int list_users(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *user, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
- uint32_t uid;
int r;
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(
bus,
"org.freedesktop.login1.Manager",
"ListUsers",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list users: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list users: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(uso)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%10s %-16s\n", "UID", "USER");
+ table = table_new("UID", "USER");
+ if (!table)
+ return log_oom();
+
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
+
+ for (;;) {
+ const char *user;
+ uint32_t uid;
+
+ r = sd_bus_message_read(reply, "(uso)", &uid, &user, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
- while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
- printf("%10"PRIu32" %-16s\n", uid, user);
- k++;
+ r = table_add_many(table,
+ TABLE_UINT32, uid,
+ TABLE_STRING, user);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u users listed.\n", k);
-
- return 0;
+ return show_table(table, "users");
}
static int list_seats(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *seat, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
int r;
+
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(
bus,
"org.freedesktop.login1.Manager",
"ListSeats",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list seats: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list seats: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(so)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%-16s\n", "SEAT");
+ table = table_new("SEAT");
+ if (!table)
+ return log_oom();
+
+ for (;;) {
+ const char *seat;
+
+ r = sd_bus_message_read(reply, "(so)", &seat, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
- while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
- printf("%-16s\n", seat);
- k++;
+ r = table_add_cell(table, NULL, TABLE_STRING, seat);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u seats listed.\n", k);
-
- return 0;
+ return show_table(table, "seats");
}
static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
}
typedef struct SessionStatusInfo {
- char *id;
+ const char *id;
uid_t uid;
- char *name;
+ const char *name;
struct dual_timestamp timestamp;
- unsigned int vtnr;
- char *seat;
- char *tty;
- char *display;
- int remote;
- char *remote_host;
- char *remote_user;
- char *service;
+ unsigned vtnr;
+ const char *seat;
+ const char *tty;
+ const char *display;
+ bool remote;
+ const char *remote_host;
+ const char *remote_user;
+ const char *service;
pid_t leader;
- char *type;
- char *class;
- char *state;
- char *scope;
- char *desktop;
+ const char *type;
+ const char *class;
+ const char *state;
+ const char *scope;
+ const char *desktop;
} SessionStatusInfo;
typedef struct UserStatusInfo {
uid_t uid;
- int linger;
- char *name;
+ bool linger;
+ const char *name;
struct dual_timestamp timestamp;
- char *state;
+ const char *state;
char **sessions;
- char *display;
- char *slice;
+ const char *display;
+ const char *slice;
} UserStatusInfo;
typedef struct SeatStatusInfo {
- char *id;
- char *active_session;
+ const char *id;
+ const char *active_session;
char **sessions;
} SeatStatusInfo;
-static void session_status_info_clear(SessionStatusInfo *info) {
- if (info) {
- free(info->id);
- free(info->name);
- free(info->seat);
- free(info->tty);
- free(info->display);
- free(info->remote_host);
- free(info->remote_user);
- free(info->service);
- free(info->type);
- free(info->class);
- free(info->state);
- free(info->scope);
- free(info->desktop);
- zero(*info);
- }
-}
-
static void user_status_info_clear(UserStatusInfo *info) {
if (info) {
- free(info->name);
- free(info->state);
strv_free(info->sessions);
- free(info->display);
- free(info->slice);
zero(*info);
}
}
static void seat_status_info_clear(SeatStatusInfo *info) {
if (info) {
- free(info->id);
- free(info->active_session);
strv_free(info->sessions);
zero(*info);
}
if (r < 0)
return r;
- if (IN_SET(contents[0], 's', 'o')) {
- const char *s;
- char **p = (char **) userdata;
-
- r = sd_bus_message_read_basic(m, contents[0], &s);
- if (r < 0)
- return r;
-
- r = free_and_strdup(p, s);
- if (r < 0)
- return r;
- } else {
- r = sd_bus_message_read_basic(m, contents[0], userdata);
- if (r < 0)
- return r;
- }
+ r = sd_bus_message_read_basic(m, contents[0], userdata);
+ if (r < 0)
+ return r;
r = sd_bus_message_skip(m, contents+1);
if (r < 0)
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
- _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2;
+ SessionStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2;
_cleanup_(user_status_info_clear) UserStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
return 0;
}
-#define property(name, fmt, ...) \
- do { \
- if (arg_value) \
- printf(fmt "\n", __VA_ARGS__); \
- else \
- printf("%s=" fmt "\n", name, __VA_ARGS__); \
- } while (0)
-
-static int print_property(const char *name, sd_bus_message *m, const char *contents) {
+static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
+ char type;
+ const char *contents;
int r;
assert(name);
assert(m);
- assert(contents);
- if (arg_property && !strv_find(arg_property, name))
- /* skip what we didn't read */
- return sd_bus_message_skip(m, contents);
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
- switch (contents[0]) {
+ switch (type) {
- case SD_BUS_TYPE_STRUCT_BEGIN:
+ case SD_BUS_TYPE_STRUCT:
- if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
+ if (contents[0] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
const char *s;
r = sd_bus_message_read(m, "(so)", &s, NULL);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(s))
- property(name, "%s", s);
+ if (all || !isempty(s))
+ bus_print_property_value(name, expected_value, value, "%s", s);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
+ } else if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
uint32_t uid;
r = sd_bus_message_read(m, "(uo)", &uid, NULL);
if (r < 0)
return bus_log_parse_error(r);
- if (!uid_is_valid(uid)) {
- log_error("Invalid user ID: " UID_FMT, uid);
- return -EINVAL;
- }
+ if (!uid_is_valid(uid))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid user ID: " UID_FMT,
+ uid);
- property(name, UID_FMT, uid);
- return 0;
+ bus_print_property_value(name, expected_value, value, UID_FMT, uid);
+ return 1;
}
-
break;
case SD_BUS_TYPE_ARRAY:
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
+ if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
const char *s;
bool space = false;
if (r < 0)
return bus_log_parse_error(r);
- if (!arg_value)
+ if (!value)
printf("%s=", name);
while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
space = true;
}
- if (space || !arg_value)
+ if (space || !value)
printf("\n");
if (r < 0)
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
}
-
break;
}
- r = bus_print_property(name, m, arg_value, arg_all);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (r == 0) {
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (arg_all)
- printf("%s=[unprintable]\n", name);
- }
-
return 0;
}
static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(path);
assert(new_line);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "");
- if (r < 0)
- return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
if (*new_line)
printf("\n");
*new_line = true;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *name, *contents;
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_peek_type(reply, NULL, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = print_property(name, reply, contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
+ r = bus_print_all_properties(bus, "org.freedesktop.login1", path, print_property, arg_property, arg_value, arg_all, NULL);
if (r < 0)
return bus_log_parse_error(r);
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (argc <= 1) {
const char *session, *p = "/org/freedesktop/login1/session/self";
session = getenv("XDG_SESSION_ID");
if (session) {
r = get_session_path(bus, session, &error, &path);
- if (r < 0) {
- log_error("Failed to get session path: %s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get session path: %s", bus_error_message(&error, r));
+
p = path;
}
for (i = 1; i < argc; i++) {
r = get_session_path(bus, argv[i], &error, &path);
- if (r < 0) {
- log_error("Failed to get session path: %s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get session path: %s", bus_error_message(&error, r));
if (properties)
r = show_properties(bus, path, &new_line);
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (argc <= 1) {
/* If not argument is specified inspect the manager
const char *path = NULL;
uid_t uid;
- r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
"GetUser",
&error, &reply,
"u", (uint32_t) uid);
- if (r < 0) {
- log_error("Failed to get user: %s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get user: %s", bus_error_message(&error, r));
r = sd_bus_message_read(reply, "o", &path);
if (r < 0)
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (argc <= 1) {
/* If not argument is specified inspect the manager
"GetSeat",
&error, &reply,
"s", argv[i]);
- if (r < 0) {
- log_error("Failed to get seat: %s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get seat: %s", bus_error_message(&error, r));
r = sd_bus_message_read(reply, "o", &path);
if (r < 0)
"ActivateSession",
&error, NULL,
"s", argv[i]);
- if (r < 0) {
- log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r));
}
return 0;
"KillSession",
&error, NULL,
"ssi", argv[i], arg_kill_who, arg_signal);
- if (r < 0) {
- log_error("Could not kill session: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not kill session: %s", bus_error_message(&error, -r));
}
return 0;
if (isempty(argv[i]))
uid = UID_INVALID;
else {
- r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
}
"SetUserLinger",
&error, NULL,
"ubb", (uint32_t) uid, b, true);
- if (r < 0) {
- log_error("Could not enable linger: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not enable linger: %s", bus_error_message(&error, -r));
}
return 0;
for (i = 1; i < argc; i++) {
uid_t uid;
- r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
"TerminateUser",
&error, NULL,
"u", (uint32_t) uid);
- if (r < 0) {
- log_error("Could not terminate user: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not terminate user: %s", bus_error_message(&error, -r));
}
return 0;
for (i = 1; i < argc; i++) {
uid_t uid;
- r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
"KillUser",
&error, NULL,
"ui", (uint32_t) uid, arg_signal);
- if (r < 0) {
- log_error("Could not kill user: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not kill user: %s", bus_error_message(&error, -r));
}
return 0;
&error, NULL,
"ssb", argv[1], argv[i], true);
- if (r < 0) {
- log_error("Could not attach device: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not attach device: %s", bus_error_message(&error, -r));
}
return 0;
&error, NULL,
"b", true);
if (r < 0)
- log_error("Could not flush devices: %s", bus_error_message(&error, -r));
+ return log_error_errno(r, "Could not flush devices: %s", bus_error_message(&error, -r));
- return r;
+ return 0;
}
static int lock_sessions(int argc, char *argv[], void *userdata) {
&error, NULL,
NULL);
if (r < 0)
- log_error("Could not lock sessions: %s", bus_error_message(&error, -r));
+ return log_error_errno(r, "Could not lock sessions: %s", bus_error_message(&error, -r));
- return r;
+ return 0;
}
static int terminate_seat(int argc, char *argv[], void *userdata) {
"TerminateSeat",
&error, NULL,
"s", argv[i]);
- if (r < 0) {
- log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not terminate seat: %s", bus_error_message(&error, -r));
}
return 0;
}
static int help(int argc, char *argv[], void *userdata) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ (void) pager_open(arg_pager_flags);
+
+ r = terminal_urlify_man("loginctl", "1", &link);
+ if (r < 0)
+ return log_oom();
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the login manager.\n\n"
" -o --output=STRING Change journal output mode (short, short-precise,\n"
" short-iso, short-iso-precise, short-full,\n"
" short-monotonic, short-unix, verbose, export,\n"
- " json, json-pretty, json-sse, cat)\n"
+ " json, json-pretty, json-sse, json-seq, cat,\n"
+ " with-unit)\n"
"Session Commands:\n"
" list-sessions List sessions\n"
" session-status [ID...] Show session status\n"
" attach NAME DEVICE... Attach one or more devices to a seat\n"
" flush-devices Flush all device associations\n"
" terminate-seat NAME... Terminate all sessions on one or more seats\n"
- , program_invocation_short_name);
+ "\nSee the %s for details.\n"
+ , program_invocation_short_name
+ , link
+ );
return 0;
}
switch (c) {
case 'h':
- help(0, NULL, NULL);
- return 0;
+ return help(0, NULL, NULL);
case ARG_VERSION:
return version();
break;
case 'n':
- if (safe_atou(optarg, &arg_lines) < 0) {
- log_error("Failed to parse lines '%s'", optarg);
- return -EINVAL;
- }
+ if (safe_atou(optarg, &arg_lines) < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse lines '%s'", optarg);
break;
case 'o':
- arg_output = output_mode_from_string(optarg);
- if (arg_output < 0) {
- log_error("Unknown output '%s'.", optarg);
- return -EINVAL;
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
}
+
+ arg_output = output_mode_from_string(optarg);
+ if (arg_output < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Unknown output '%s'.", optarg);
break;
case ARG_NO_PAGER:
- arg_no_pager = true;
+ arg_pager_flags |= PAGER_DISABLE;
break;
case ARG_NO_LEGEND:
break;
case 's':
- arg_signal = signal_from_string_try_harder(optarg);
- if (arg_signal < 0) {
- log_error("Failed to parse signal string %s.", optarg);
- return -EINVAL;
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
}
+
+ arg_signal = signal_from_string(optarg);
+ if (arg_signal < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse signal string %s.", optarg);
break;
case 'H':
return dispatch_verb(argc, argv, verbs, bus);
}
-int main(int argc, char *argv[]) {
- sd_bus *bus = NULL;
+static int run(int argc, char *argv[]) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
+
+ /* The journal merging logic potentially needs a lot of fds. */
+ (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
+
sigbus_install();
r = parse_argv(argc, argv);
if (r <= 0)
- goto finish;
+ return r;
r = bus_connect_transport(arg_transport, arg_host, false, &bus);
- if (r < 0) {
- log_error_errno(r, "Failed to create bus connection: %m");
- goto finish;
- }
-
- sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
-
- r = loginctl_main(argc, argv, bus);
-
-finish:
- /* make sure we terminate the bus connection first, and then close the
- * pager, see issue #3543 for the details. */
- sd_bus_flush_close_unref(bus);
- pager_close();
- polkit_agent_close();
+ if (r < 0)
+ return log_error_errno(r, "Failed to create bus connection: %m");
- strv_free(arg_property);
+ (void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return loginctl_main(argc, argv, bus);
}
+
+DEFINE_MAIN_FUNCTION(run);