diff options
Diffstat (limited to 'src/login/loginctl.c')
-rw-r--r-- | src/login/loginctl.c | 216 |
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); |