summaryrefslogtreecommitdiff
path: root/src/login/loginctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/login/loginctl.c')
-rw-r--r--src/login/loginctl.c216
1 files changed, 100 insertions, 116 deletions
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index be55fdbfd8..ab1b56201a 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -18,9 +18,12 @@
#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"
@@ -37,7 +40,7 @@ static char **arg_property = NULL;
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;
@@ -47,6 +50,8 @@ static bool arg_ask_password = true;
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
@@ -96,7 +101,10 @@ static int show_table(Table *table, const char *word) {
table_set_header(table, arg_legend);
- r = table_print(table, NULL);
+ if (OUTPUT_MODE_IS_JSON(arg_output))
+ r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO);
+ else
+ r = table_print(table, NULL);
if (r < 0)
return log_error_errno(r, "Failed to show table: %m");
}
@@ -121,7 +129,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(
bus,
@@ -138,7 +146,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- table = table_new("SESSION", "UID", "USER", "SEAT", "TTY");
+ table = table_new("session", "uid", "user", "seat", "tty");
if (!table)
return log_oom();
@@ -202,7 +210,7 @@ static int list_users(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(
bus,
@@ -219,7 +227,7 @@ static int list_users(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- table = table_new("UID", "USER");
+ table = table_new("uid", "user");
if (!table)
return log_oom();
@@ -259,7 +267,7 @@ static int list_seats(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(
bus,
@@ -276,7 +284,7 @@ static int list_seats(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- table = table_new("SEAT");
+ table = table_new("seat");
if (!table)
return log_oom();
@@ -346,7 +354,7 @@ typedef struct SessionStatusInfo {
uid_t uid;
const char *name;
struct dual_timestamp timestamp;
- unsigned int vtnr;
+ unsigned vtnr;
const char *seat;
const char *tty;
const char *display;
@@ -723,15 +731,7 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
return 0;
}
-#define property(name, fmt, ...) \
- do { \
- if (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, bool value, bool all) {
+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;
@@ -755,7 +755,7 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool
return bus_log_parse_error(r);
if (all || !isempty(s))
- property(name, "%s", s);
+ bus_print_property_value(name, expected_value, value, "%s", s);
return 1;
@@ -766,12 +766,12 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool
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);
+ bus_print_property_value(name, expected_value, value, UID_FMT, uid);
return 1;
}
break;
@@ -843,7 +843,7 @@ static int show_session(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (argc <= 1) {
const char *session, *p = "/org/freedesktop/login1/session/self";
@@ -856,10 +856,9 @@ static int show_session(int argc, char *argv[], void *userdata) {
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;
}
@@ -868,10 +867,8 @@ static int show_session(int argc, char *argv[], void *userdata) {
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);
@@ -895,7 +892,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -912,7 +909,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
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]);
@@ -924,10 +921,8 @@ static int show_user(int argc, char *argv[], void *userdata) {
"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)
@@ -955,7 +950,7 @@ static int show_seat(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -979,10 +974,8 @@ static int show_seat(int argc, char *argv[], void *userdata) {
"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)
@@ -1036,10 +1029,8 @@ static int activate(int argc, char *argv[], void *userdata) {
"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;
@@ -1068,10 +1059,8 @@ static int kill_session(int argc, char *argv[], void *userdata) {
"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;
@@ -1108,7 +1097,7 @@ static int enable_linger(int argc, char *argv[], void *userdata) {
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]);
}
@@ -1121,10 +1110,8 @@ static int enable_linger(int argc, char *argv[], void *userdata) {
"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;
@@ -1143,7 +1130,7 @@ static int terminate_user(int argc, char *argv[], void *userdata) {
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]);
@@ -1155,10 +1142,8 @@ static int terminate_user(int argc, char *argv[], void *userdata) {
"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;
@@ -1180,7 +1165,7 @@ static int kill_user(int argc, char *argv[], void *userdata) {
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]);
@@ -1192,10 +1177,8 @@ static int kill_user(int argc, char *argv[], void *userdata) {
"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;
@@ -1222,10 +1205,8 @@ static int attach(int argc, char *argv[], void *userdata) {
&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;
@@ -1250,9 +1231,9 @@ static int flush_devices(int argc, char *argv[], void *userdata) {
&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) {
@@ -1274,9 +1255,9 @@ 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) {
@@ -1299,16 +1280,22 @@ 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"
@@ -1329,7 +1316,8 @@ static int help(int argc, char *argv[], void *userdata) {
" -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"
@@ -1356,7 +1344,10 @@ static int help(int argc, char *argv[], void *userdata) {
" 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;
}
@@ -1401,8 +1392,7 @@ static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
- help(0, NULL, NULL);
- return 0;
+ return help(0, NULL, NULL);
case ARG_VERSION:
return version();
@@ -1432,10 +1422,9 @@ static int parse_argv(int argc, char *argv[]) {
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':
@@ -1445,14 +1434,17 @@ static int parse_argv(int argc, char *argv[]) {
}
arg_output = output_mode_from_string(optarg);
- if (arg_output < 0) {
- log_error("Unknown output '%s'.", optarg);
- return -EINVAL;
- }
+ if (arg_output < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Unknown output '%s'.", optarg);
+
+ if (OUTPUT_MODE_IS_JSON(arg_output))
+ arg_legend = false;
+
break;
case ARG_NO_PAGER:
- arg_no_pager = true;
+ arg_pager_flags |= PAGER_DISABLE;
break;
case ARG_NO_LEGEND:
@@ -1474,10 +1466,9 @@ static int parse_argv(int argc, char *argv[]) {
}
arg_signal = signal_from_string(optarg);
- if (arg_signal < 0) {
- log_error("Failed to parse signal string %s.", optarg);
- return -EINVAL;
- }
+ if (arg_signal < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse signal string %s.", optarg);
break;
case 'H':
@@ -1533,37 +1524,30 @@ static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
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);