2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2011-07-07 03:29:56 +02:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <getopt.h>
|
2012-11-12 20:16:07 +01:00
|
|
|
#include <locale.h>
|
2015-09-23 03:01:06 +02:00
|
|
|
#include <unistd.h>
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
#include "sd-bus.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2013-11-07 08:58:23 +01:00
|
|
|
#include "bus-error.h"
|
2019-03-06 19:47:06 +01:00
|
|
|
#include "bus-unit-procs.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "bus-util.h"
|
|
|
|
#include "cgroup-show.h"
|
|
|
|
#include "cgroup-util.h"
|
2018-04-11 21:37:38 +02:00
|
|
|
#include "format-table.h"
|
2011-07-07 03:29:56 +02:00
|
|
|
#include "log.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "logs-show.h"
|
2011-07-07 03:29:56 +02:00
|
|
|
#include "macro.h"
|
2018-11-20 10:15:33 +01:00
|
|
|
#include "main-func.h"
|
2019-03-13 12:02:21 +01:00
|
|
|
#include "memory-util.h"
|
2011-07-07 03:29:56 +02:00
|
|
|
#include "pager.h"
|
2015-10-26 16:18:16 +01:00
|
|
|
#include "parse-util.h"
|
2018-11-20 15:42:57 +01:00
|
|
|
#include "pretty-print.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "process-util.h"
|
2018-10-01 17:44:46 +02:00
|
|
|
#include "rlimit-util.h"
|
2017-11-10 21:04:08 +01:00
|
|
|
#include "sigbus.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "signal-util.h"
|
|
|
|
#include "spawn-polkit-agent.h"
|
2018-05-22 12:10:56 +02:00
|
|
|
#include "string-table.h"
|
2011-07-08 21:39:10 +02:00
|
|
|
#include "strv.h"
|
|
|
|
#include "sysfs-show.h"
|
2015-04-10 23:15:59 +02:00
|
|
|
#include "terminal-util.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "unit-name.h"
|
2015-10-25 22:32:30 +01:00
|
|
|
#include "user-util.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "verbs.h"
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2011-07-08 21:39:10 +02:00
|
|
|
static char **arg_property = NULL;
|
|
|
|
static bool arg_all = false;
|
2016-03-17 17:48:02 +01:00
|
|
|
static bool arg_value = false;
|
2013-01-14 18:16:50 +01:00
|
|
|
static bool arg_full = false;
|
2018-11-11 12:56:29 +01:00
|
|
|
static PagerFlags arg_pager_flags = 0;
|
2013-12-21 20:20:29 +01:00
|
|
|
static bool arg_legend = true;
|
2011-07-08 21:39:10 +02:00
|
|
|
static const char *arg_kill_who = NULL;
|
|
|
|
static int arg_signal = SIGTERM;
|
2013-11-07 08:58:23 +01:00
|
|
|
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
|
2013-06-09 22:54:39 +02:00
|
|
|
static char *arg_host = NULL;
|
2015-01-08 15:33:46 +01:00
|
|
|
static bool arg_ask_password = true;
|
2015-01-08 14:38:52 +01:00
|
|
|
static unsigned arg_lines = 10;
|
|
|
|
static OutputMode arg_output = OUTPUT_SHORT;
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-11-20 10:15:33 +01:00
|
|
|
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
|
|
|
|
|
2015-01-08 14:38:52 +01:00
|
|
|
static OutputFlags get_output_flags(void) {
|
|
|
|
|
|
|
|
return
|
|
|
|
arg_all * OUTPUT_SHOW_ALL |
|
2017-11-10 21:40:47 +01:00
|
|
|
(arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
|
2016-01-19 10:17:19 +01:00
|
|
|
colors_enabled() * OUTPUT_COLOR;
|
2015-01-08 14:38:52 +01:00
|
|
|
}
|
|
|
|
|
2016-10-16 21:13:03 +02:00
|
|
|
static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) {
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
|
|
int r;
|
|
|
|
char *ans;
|
|
|
|
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"GetSession",
|
|
|
|
error, &reply,
|
|
|
|
"s", session_id);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(reply, "o", &ans);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
ans = strdup(ans);
|
|
|
|
if (!ans)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
*path = ans;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
static int show_table(Table *table, const char *word) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(table);
|
|
|
|
assert(word);
|
|
|
|
|
2019-05-07 01:21:24 +02:00
|
|
|
if (table_get_rows(table) > 1 || OUTPUT_MODE_IS_JSON(arg_output)) {
|
2018-04-11 21:37:38 +02:00
|
|
|
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);
|
|
|
|
|
2018-12-03 20:46:33 +01:00
|
|
|
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);
|
2018-04-11 21:37:38 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int list_sessions(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
2018-04-11 21:37:38 +02:00
|
|
|
_cleanup_(table_unrefp) Table *table = NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
|
|
|
|
2018-11-11 12:56:29 +01:00
|
|
|
(void) pager_open(arg_pager_flags);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_call_method(
|
2012-08-08 14:38:05 +02:00
|
|
|
bus,
|
2011-07-07 03:29:56 +02:00
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
2012-08-08 14:38:05 +02:00
|
|
|
"ListSessions",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, &reply,
|
2018-04-11 21:37:38 +02:00
|
|
|
NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to list sessions: %s", bus_error_message(&error, r));
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_message_enter_container(reply, 'a', "(susso)");
|
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-12-03 21:39:12 +01:00
|
|
|
table = table_new("session", "uid", "user", "seat", "tty");
|
2018-04-11 21:37:38 +02:00
|
|
|
if (!table)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
/* 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);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
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;
|
2016-10-16 21:13:03 +02:00
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object);
|
2016-10-16 21:13:03 +02:00
|
|
|
if (r < 0)
|
2018-04-11 21:37:38 +02:00
|
|
|
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_errno(r, "Failed to get TTY for session %s: %s", id, bus_error_message(&error_tty, r));
|
2016-10-16 21:13:03 +02:00
|
|
|
else {
|
2018-04-11 21:37:38 +02:00
|
|
|
r = sd_bus_message_read(reply_tty, "s", &tty);
|
2016-10-16 21:13:03 +02:00
|
|
|
if (r < 0)
|
2018-04-11 21:37:38 +02:00
|
|
|
return bus_log_parse_error(r);
|
2016-10-16 21:13:03 +02:00
|
|
|
}
|
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
r = table_add_many(table,
|
|
|
|
TABLE_STRING, id,
|
2019-08-07 14:50:01 +02:00
|
|
|
TABLE_UID, (uid_t) uid,
|
2018-04-11 21:37:38 +02:00
|
|
|
TABLE_STRING, user,
|
|
|
|
TABLE_STRING, seat,
|
|
|
|
TABLE_STRING, strna(tty));
|
|
|
|
if (r < 0)
|
2020-01-10 10:23:24 +01:00
|
|
|
return table_log_add_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
2018-04-11 21:37:38 +02:00
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(reply);
|
2013-11-07 08:58:23 +01:00
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
return show_table(table, "sessions");
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int list_users(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
2018-04-11 21:37:38 +02:00
|
|
|
_cleanup_(table_unrefp) Table *table = NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
|
|
|
|
2018-11-11 12:56:29 +01:00
|
|
|
(void) pager_open(arg_pager_flags);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_call_method(
|
2012-08-08 14:38:05 +02:00
|
|
|
bus,
|
2011-07-07 03:29:56 +02:00
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
2012-08-08 14:38:05 +02:00
|
|
|
"ListUsers",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, &reply,
|
2018-04-11 21:37:38 +02:00
|
|
|
NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to list users: %s", bus_error_message(&error, r));
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_message_enter_container(reply, 'a', "(uso)");
|
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-12-03 21:39:12 +01:00
|
|
|
table = table_new("uid", "user");
|
2018-04-11 21:37:38 +02:00
|
|
|
if (!table)
|
|
|
|
return log_oom();
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
(void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
|
|
|
|
|
|
|
|
for (;;) {
|
2018-06-19 07:09:13 +02:00
|
|
|
const char *user;
|
2018-04-11 21:37:38 +02:00
|
|
|
uint32_t uid;
|
|
|
|
|
2018-06-19 07:09:13 +02:00
|
|
|
r = sd_bus_message_read(reply, "(uso)", &uid, &user, NULL);
|
2018-04-11 21:37:38 +02:00
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
r = table_add_many(table,
|
2019-08-07 14:50:01 +02:00
|
|
|
TABLE_UID, (uid_t) uid,
|
2018-04-11 21:37:38 +02:00
|
|
|
TABLE_STRING, user);
|
|
|
|
if (r < 0)
|
2020-01-10 10:23:24 +01:00
|
|
|
return table_log_add_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
2018-04-11 21:37:38 +02:00
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(reply);
|
2013-11-07 08:58:23 +01:00
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
return show_table(table, "users");
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int list_seats(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
2018-04-11 21:37:38 +02:00
|
|
|
_cleanup_(table_unrefp) Table *table = NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
2018-04-11 21:37:38 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
|
|
|
|
2018-11-11 12:56:29 +01:00
|
|
|
(void) pager_open(arg_pager_flags);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_call_method(
|
2012-08-08 14:38:05 +02:00
|
|
|
bus,
|
2011-07-07 03:29:56 +02:00
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
2012-08-08 14:38:05 +02:00
|
|
|
"ListSeats",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, &reply,
|
2018-04-11 21:37:38 +02:00
|
|
|
NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to list seats: %s", bus_error_message(&error, r));
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_message_enter_container(reply, 'a', "(so)");
|
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-12-03 21:39:12 +01:00
|
|
|
table = table_new("seat");
|
2018-04-11 21:37:38 +02:00
|
|
|
if (!table)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
for (;;) {
|
2018-06-19 07:09:13 +02:00
|
|
|
const char *seat;
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-06-19 07:09:13 +02:00
|
|
|
r = sd_bus_message_read(reply, "(so)", &seat, NULL);
|
2018-04-11 21:37:38 +02:00
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
r = table_add_cell(table, NULL, TABLE_STRING, seat);
|
|
|
|
if (r < 0)
|
2020-01-10 10:23:24 +01:00
|
|
|
return table_log_add_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
2018-04-11 21:37:38 +02:00
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(reply);
|
2013-11-07 08:58:23 +01:00
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-04-11 21:37:38 +02:00
|
|
|
return show_table(table, "seats");
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
|
2017-02-01 20:30:57 +01:00
|
|
|
_cleanup_free_ char *cgroup = NULL;
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2013-07-11 00:27:54 +02:00
|
|
|
unsigned c;
|
2016-04-20 15:51:33 +02:00
|
|
|
int r;
|
2013-07-11 00:27:54 +02:00
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(unit);
|
|
|
|
|
2017-02-01 20:30:57 +01:00
|
|
|
r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup);
|
2013-11-07 08:58:23 +01:00
|
|
|
if (r < 0)
|
2017-02-01 20:30:57 +01:00
|
|
|
return r;
|
2013-07-11 00:27:54 +02:00
|
|
|
|
2013-07-11 19:14:38 +02:00
|
|
|
if (isempty(cgroup))
|
|
|
|
return 0;
|
|
|
|
|
2013-07-11 00:27:54 +02:00
|
|
|
c = columns();
|
|
|
|
if (c > 18)
|
|
|
|
c -= 18;
|
|
|
|
else
|
|
|
|
c = 0;
|
|
|
|
|
2016-04-20 15:51:33 +02:00
|
|
|
r = unit_show_processes(bus, unit, cgroup, "\t\t ", c, get_output_flags(), &error);
|
|
|
|
if (r == -EBADR) {
|
|
|
|
|
|
|
|
if (arg_transport == BUS_TRANSPORT_REMOTE)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
|
|
|
|
|
|
|
|
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
|
|
|
|
return 0;
|
|
|
|
|
2016-04-20 16:06:58 +02:00
|
|
|
show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags());
|
2016-04-20 15:51:33 +02:00
|
|
|
} else if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r));
|
|
|
|
|
2013-07-11 00:27:54 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-08 21:39:10 +02:00
|
|
|
typedef struct SessionStatusInfo {
|
2018-03-19 15:46:29 +01:00
|
|
|
const char *id;
|
2011-07-08 21:39:10 +02:00
|
|
|
uid_t uid;
|
2018-03-19 15:46:29 +01:00
|
|
|
const char *name;
|
2015-01-08 14:38:52 +01:00
|
|
|
struct dual_timestamp timestamp;
|
2018-10-19 20:00:46 +02:00
|
|
|
unsigned vtnr;
|
2018-03-19 15:46:29 +01:00
|
|
|
const char *seat;
|
|
|
|
const char *tty;
|
|
|
|
const char *display;
|
|
|
|
bool remote;
|
|
|
|
const char *remote_host;
|
|
|
|
const char *remote_user;
|
|
|
|
const char *service;
|
2011-07-08 21:39:10 +02:00
|
|
|
pid_t leader;
|
2018-03-19 15:46:29 +01:00
|
|
|
const char *type;
|
|
|
|
const char *class;
|
|
|
|
const char *state;
|
|
|
|
const char *scope;
|
|
|
|
const char *desktop;
|
2011-07-08 21:39:10 +02:00
|
|
|
} SessionStatusInfo;
|
|
|
|
|
|
|
|
typedef struct UserStatusInfo {
|
|
|
|
uid_t uid;
|
2018-03-19 15:46:29 +01:00
|
|
|
bool linger;
|
|
|
|
const char *name;
|
2015-01-08 14:38:52 +01:00
|
|
|
struct dual_timestamp timestamp;
|
2018-03-19 15:46:29 +01:00
|
|
|
const char *state;
|
2011-07-08 21:39:10 +02:00
|
|
|
char **sessions;
|
2018-03-19 15:46:29 +01:00
|
|
|
const char *display;
|
|
|
|
const char *slice;
|
2011-07-08 21:39:10 +02:00
|
|
|
} UserStatusInfo;
|
|
|
|
|
|
|
|
typedef struct SeatStatusInfo {
|
2018-03-19 15:46:29 +01:00
|
|
|
const char *id;
|
|
|
|
const char *active_session;
|
2011-07-08 21:39:10 +02:00
|
|
|
char **sessions;
|
|
|
|
} SeatStatusInfo;
|
|
|
|
|
2015-06-14 15:08:52 +02:00
|
|
|
static void user_status_info_clear(UserStatusInfo *info) {
|
|
|
|
if (info) {
|
|
|
|
strv_free(info->sessions);
|
|
|
|
zero(*info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seat_status_info_clear(SeatStatusInfo *info) {
|
|
|
|
if (info) {
|
|
|
|
strv_free(info->sessions);
|
|
|
|
zero(*info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
|
|
|
|
const char *contents;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = sd_bus_message_peek_type(m, NULL, &contents);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2018-03-19 15:46:29 +01:00
|
|
|
r = sd_bus_message_read_basic(m, contents[0], userdata);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-07 08:58:23 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_skip(m, contents+1);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
|
|
|
|
const char *name;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(m);
|
|
|
|
|
|
|
|
r = sd_bus_message_enter_container(m, 'a', "(so)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) {
|
|
|
|
r = strv_extend(userdata, name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return sd_bus_message_exit_container(m);
|
|
|
|
}
|
|
|
|
|
2013-12-17 19:42:03 +01:00
|
|
|
static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
|
2013-11-07 08:58:23 +01:00
|
|
|
|
|
|
|
static const struct bus_properties_map map[] = {
|
2015-01-08 14:38:52 +01:00
|
|
|
{ "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
|
|
|
|
{ "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
|
|
|
|
{ "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
|
|
|
|
{ "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
|
|
|
|
{ "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
|
|
|
|
{ "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
|
|
|
|
{ "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
|
|
|
|
{ "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
|
|
|
|
{ "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
|
|
|
|
{ "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
|
|
|
|
{ "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
|
|
|
|
{ "State", "s", NULL, offsetof(SessionStatusInfo, state) },
|
|
|
|
{ "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
|
|
|
|
{ "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
|
|
|
|
{ "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
|
|
|
|
{ "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
|
|
|
|
{ "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
|
|
|
|
{ "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
|
|
|
|
{ "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
|
2013-11-07 08:58:23 +01:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2017-02-08 17:59:58 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2018-03-19 15:46:29 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
2018-05-24 09:36:56 +02:00
|
|
|
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
|
|
|
|
char since2[FORMAT_TIMESTAMP_MAX];
|
|
|
|
const char *s1, *s2;
|
2018-03-19 15:46:29 +01:00
|
|
|
SessionStatusInfo i = {};
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
|
|
|
|
2018-03-28 13:37:27 +02:00
|
|
|
r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
|
2014-11-28 18:50:43 +01:00
|
|
|
if (r < 0)
|
2017-02-08 17:59:58 +01:00
|
|
|
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
|
2013-12-17 19:42:03 +01:00
|
|
|
|
|
|
|
if (*new_line)
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
*new_line = true;
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
printf("%s - ", strna(i.id));
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.name)
|
2016-10-16 20:19:06 +02:00
|
|
|
printf("%s (%"PRIu32")\n", i.name, i.uid);
|
2011-07-08 21:39:10 +02:00
|
|
|
else
|
2016-10-16 20:19:06 +02:00
|
|
|
printf("%"PRIu32"\n", i.uid);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-08 14:38:52 +01:00
|
|
|
s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
|
|
|
|
s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
|
|
|
if (s1)
|
|
|
|
printf("\t Since: %s; %s\n", s2, s1);
|
|
|
|
else if (s2)
|
|
|
|
printf("\t Since: %s\n", s2);
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.leader > 0) {
|
2013-06-20 03:45:08 +02:00
|
|
|
_cleanup_free_ char *t = NULL;
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2016-10-16 20:19:06 +02:00
|
|
|
printf("\t Leader: %"PRIu32, i.leader);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
get_process_comm(i.leader, &t);
|
2013-06-20 03:45:08 +02:00
|
|
|
if (t)
|
2011-07-08 21:39:10 +02:00
|
|
|
printf(" (%s)", t);
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2013-12-21 15:49:46 +01:00
|
|
|
if (!isempty(i.seat)) {
|
2013-11-07 08:58:23 +01:00
|
|
|
printf("\t Seat: %s", i.seat);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.vtnr > 0)
|
2014-12-10 20:24:18 +01:00
|
|
|
printf("; vc%u", i.vtnr);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.tty)
|
|
|
|
printf("\t TTY: %s\n", i.tty);
|
|
|
|
else if (i.display)
|
|
|
|
printf("\t Display: %s\n", i.display);
|
|
|
|
|
|
|
|
if (i.remote_host && i.remote_user)
|
|
|
|
printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host);
|
|
|
|
else if (i.remote_host)
|
|
|
|
printf("\t Remote: %s\n", i.remote_host);
|
|
|
|
else if (i.remote_user)
|
|
|
|
printf("\t Remote: user %s\n", i.remote_user);
|
|
|
|
else if (i.remote)
|
2011-07-08 21:39:10 +02:00
|
|
|
printf("\t Remote: Yes\n");
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.service) {
|
|
|
|
printf("\t Service: %s", i.service);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.type)
|
|
|
|
printf("; type %s", i.type);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.class)
|
|
|
|
printf("; class %s", i.class);
|
2012-02-14 21:33:51 +01:00
|
|
|
|
2011-07-08 21:39:10 +02:00
|
|
|
printf("\n");
|
2013-11-07 08:58:23 +01:00
|
|
|
} else if (i.type) {
|
2013-12-22 06:22:46 +01:00
|
|
|
printf("\t Type: %s", i.type);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.class)
|
|
|
|
printf("; class %s", i.class);
|
2013-12-22 06:22:46 +01:00
|
|
|
|
|
|
|
printf("\n");
|
2013-11-07 08:58:23 +01:00
|
|
|
} else if (i.class)
|
|
|
|
printf("\t Class: %s\n", i.class);
|
2012-02-14 21:33:51 +01:00
|
|
|
|
2014-02-05 20:34:11 +01:00
|
|
|
if (!isempty(i.desktop))
|
|
|
|
printf("\t Desktop: %s\n", i.desktop);
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.state)
|
|
|
|
printf("\t State: %s\n", i.state);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.scope) {
|
|
|
|
printf("\t Unit: %s\n", i.scope);
|
|
|
|
show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
|
2015-01-08 14:38:52 +01:00
|
|
|
|
|
|
|
if (arg_transport == BUS_TRANSPORT_LOCAL) {
|
|
|
|
|
|
|
|
show_journal_by_unit(
|
|
|
|
stdout,
|
|
|
|
i.scope,
|
2019-11-27 12:13:59 +01:00
|
|
|
NULL,
|
2015-01-08 14:38:52 +01:00
|
|
|
arg_output,
|
|
|
|
0,
|
|
|
|
i.timestamp.monotonic,
|
|
|
|
arg_lines,
|
|
|
|
0,
|
|
|
|
get_output_flags() | OUTPUT_BEGIN_NEWLINE,
|
|
|
|
SD_JOURNAL_LOCAL_ONLY,
|
|
|
|
true,
|
|
|
|
NULL);
|
|
|
|
}
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
2013-11-07 08:58:23 +01:00
|
|
|
|
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2013-12-17 19:42:03 +01:00
|
|
|
static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
|
2013-11-07 08:58:23 +01:00
|
|
|
|
|
|
|
static const struct bus_properties_map map[] = {
|
2015-01-08 14:38:52 +01:00
|
|
|
{ "Name", "s", NULL, offsetof(UserStatusInfo, name) },
|
2016-04-13 05:35:45 +02:00
|
|
|
{ "Linger", "b", NULL, offsetof(UserStatusInfo, linger) },
|
2015-01-08 14:38:52 +01:00
|
|
|
{ "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
|
|
|
|
{ "State", "s", NULL, offsetof(UserStatusInfo, state) },
|
|
|
|
{ "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
|
|
|
|
{ "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
|
|
|
|
{ "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
|
|
|
|
{ "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
|
|
|
|
{ "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
|
2013-11-07 08:58:23 +01:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2017-02-08 17:59:58 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2018-03-19 15:46:29 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
2018-05-24 09:36:56 +02:00
|
|
|
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
|
|
|
|
char since2[FORMAT_TIMESTAMP_MAX];
|
|
|
|
const char *s1, *s2;
|
2015-06-14 15:08:52 +02:00
|
|
|
_cleanup_(user_status_info_clear) UserStatusInfo i = {};
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2018-03-28 13:37:27 +02:00
|
|
|
r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
|
2015-06-14 15:08:52 +02:00
|
|
|
if (r < 0)
|
2017-02-08 17:59:58 +01:00
|
|
|
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
|
2013-12-17 19:42:03 +01:00
|
|
|
|
|
|
|
if (*new_line)
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
*new_line = true;
|
2013-11-07 08:58:23 +01:00
|
|
|
|
|
|
|
if (i.name)
|
2016-10-16 20:19:06 +02:00
|
|
|
printf("%s (%"PRIu32")\n", i.name, i.uid);
|
2011-07-08 21:39:10 +02:00
|
|
|
else
|
2016-10-16 20:19:06 +02:00
|
|
|
printf("%"PRIu32"\n", i.uid);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-08 14:38:52 +01:00
|
|
|
s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
|
|
|
|
s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
|
|
|
if (s1)
|
|
|
|
printf("\t Since: %s; %s\n", s2, s1);
|
|
|
|
else if (s2)
|
|
|
|
printf("\t Since: %s\n", s2);
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (!isempty(i.state))
|
|
|
|
printf("\t State: %s\n", i.state);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (!strv_isempty(i.sessions)) {
|
2011-07-08 21:39:10 +02:00
|
|
|
char **l;
|
|
|
|
printf("\tSessions:");
|
|
|
|
|
2016-04-13 05:35:45 +02:00
|
|
|
STRV_FOREACH(l, i.sessions)
|
|
|
|
printf(" %s%s",
|
|
|
|
streq_ptr(*l, i.display) ? "*" : "",
|
|
|
|
*l);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2016-04-13 05:35:45 +02:00
|
|
|
printf("\t Linger: %s\n", yes_no(i.linger));
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (i.slice) {
|
|
|
|
printf("\t Unit: %s\n", i.slice);
|
|
|
|
show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
|
2015-01-08 14:38:52 +01:00
|
|
|
|
|
|
|
show_journal_by_unit(
|
|
|
|
stdout,
|
|
|
|
i.slice,
|
2019-11-27 12:13:59 +01:00
|
|
|
NULL,
|
2015-01-08 14:38:52 +01:00
|
|
|
arg_output,
|
|
|
|
0,
|
|
|
|
i.timestamp.monotonic,
|
|
|
|
arg_lines,
|
|
|
|
0,
|
|
|
|
get_output_flags() | OUTPUT_BEGIN_NEWLINE,
|
|
|
|
SD_JOURNAL_LOCAL_ONLY,
|
|
|
|
true,
|
|
|
|
NULL);
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
2013-11-07 08:58:23 +01:00
|
|
|
|
2015-06-14 15:08:52 +02:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2013-12-17 19:42:03 +01:00
|
|
|
static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
static const struct bus_properties_map map[] = {
|
|
|
|
{ "Id", "s", NULL, offsetof(SeatStatusInfo, id) },
|
2013-11-07 21:06:44 +01:00
|
|
|
{ "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) },
|
|
|
|
{ "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) },
|
2013-11-07 08:58:23 +01:00
|
|
|
{}
|
|
|
|
};
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2017-02-08 17:59:58 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2018-03-19 15:46:29 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
2015-06-14 15:08:52 +02:00
|
|
|
_cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
|
|
|
|
2018-03-28 13:37:27 +02:00
|
|
|
r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i);
|
2015-06-14 15:08:52 +02:00
|
|
|
if (r < 0)
|
2017-02-08 17:59:58 +01:00
|
|
|
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
|
2013-12-17 19:42:03 +01:00
|
|
|
|
|
|
|
if (*new_line)
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
*new_line = true;
|
2013-11-07 08:58:23 +01:00
|
|
|
|
|
|
|
printf("%s\n", strna(i.id));
|
|
|
|
|
|
|
|
if (!strv_isempty(i.sessions)) {
|
2011-07-08 21:39:10 +02:00
|
|
|
char **l;
|
|
|
|
printf("\tSessions:");
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
STRV_FOREACH(l, i.sessions) {
|
|
|
|
if (streq_ptr(*l, i.active_session))
|
2011-07-08 21:39:10 +02:00
|
|
|
printf(" *%s", *l);
|
|
|
|
else
|
|
|
|
printf(" %s", *l);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
if (arg_transport == BUS_TRANSPORT_LOCAL) {
|
2011-07-08 21:39:10 +02:00
|
|
|
unsigned c;
|
|
|
|
|
|
|
|
c = columns();
|
2011-07-09 02:58:05 +02:00
|
|
|
if (c > 21)
|
|
|
|
c -= 21;
|
2011-07-08 21:39:10 +02:00
|
|
|
else
|
|
|
|
c = 0;
|
|
|
|
|
|
|
|
printf("\t Devices:\n");
|
|
|
|
|
2017-11-10 21:44:29 +01:00
|
|
|
show_sysfs(i.id, "\t\t ", c, get_output_flags());
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-06-14 15:08:52 +02:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2018-09-11 10:18:14 +02:00
|
|
|
static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
|
2018-03-19 16:37:00 +01:00
|
|
|
char type;
|
|
|
|
const char *contents;
|
2015-09-11 13:37:59 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(name);
|
|
|
|
assert(m);
|
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
r = sd_bus_message_peek_type(m, &type, &contents);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2015-09-11 13:37:59 +02:00
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
switch (type) {
|
2015-09-11 13:37:59 +02:00
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
case SD_BUS_TYPE_STRUCT:
|
2015-09-11 13:37:59 +02:00
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
if (contents[0] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
|
2015-09-11 13:37:59 +02:00
|
|
|
const char *s;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "(so)", &s, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
if (all || !isempty(s))
|
2019-03-02 15:35:26 +01:00
|
|
|
bus_print_property_value(name, expected_value, value, s);
|
2015-09-11 13:37:59 +02:00
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
return 1;
|
2015-09-11 13:37:59 +02:00
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
} else if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
|
2015-09-11 13:37:59 +02:00
|
|
|
uint32_t uid;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "(uo)", &uid, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
|
2018-11-20 23:40:44 +01:00
|
|
|
if (!uid_is_valid(uid))
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Invalid user ID: " UID_FMT,
|
|
|
|
uid);
|
2015-09-11 13:37:59 +02:00
|
|
|
|
2019-03-02 15:35:26 +01:00
|
|
|
bus_print_property_valuef(name, expected_value, value, UID_FMT, uid);
|
2018-03-19 16:37:00 +01:00
|
|
|
return 1;
|
2015-09-11 13:37:59 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SD_BUS_TYPE_ARRAY:
|
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
|
2015-09-11 13:37:59 +02:00
|
|
|
const char *s;
|
|
|
|
bool space = false;
|
|
|
|
|
|
|
|
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(so)");
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
if (!value)
|
2016-03-17 17:48:02 +01:00
|
|
|
printf("%s=", name);
|
2015-09-11 13:37:59 +02:00
|
|
|
|
|
|
|
while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
|
|
|
|
printf("%s%s", space ? " " : "", s);
|
|
|
|
space = true;
|
|
|
|
}
|
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
if (space || !value)
|
2016-03-17 17:48:02 +01:00
|
|
|
printf("\n");
|
2015-09-11 13:37:59 +02:00
|
|
|
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(m);
|
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
return 1;
|
2015-09-11 13:37:59 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-17 19:42:01 +01:00
|
|
|
static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
|
|
|
|
int r;
|
|
|
|
|
2015-09-11 13:37:59 +02:00
|
|
|
assert(bus);
|
|
|
|
assert(path);
|
|
|
|
assert(new_line);
|
|
|
|
|
2013-12-17 19:42:01 +01:00
|
|
|
if (*new_line)
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
*new_line = true;
|
|
|
|
|
2018-03-19 16:37:00 +01:00
|
|
|
r = bus_print_all_properties(bus, "org.freedesktop.login1", path, print_property, arg_property, arg_value, arg_all, NULL);
|
2015-09-11 13:37:59 +02:00
|
|
|
if (r < 0)
|
|
|
|
return bus_log_parse_error(r);
|
|
|
|
|
|
|
|
return 0;
|
2013-12-17 19:42:01 +01:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int show_session(int argc, char *argv[], void *userdata) {
|
2013-12-17 19:42:01 +01:00
|
|
|
bool properties, new_line = false;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2017-06-01 04:42:14 +02:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
_cleanup_free_ char *path = NULL;
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
assert(bus);
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(argv);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
properties = !strstr(argv[0], "status");
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2018-11-11 12:56:29 +01:00
|
|
|
(void) pager_open(arg_pager_flags);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-09 01:43:53 +01:00
|
|
|
if (argc <= 1) {
|
2019-04-28 18:02:03 +02:00
|
|
|
/* If no argument is specified inspect the manager itself */
|
2015-01-09 01:43:53 +01:00
|
|
|
if (properties)
|
|
|
|
return show_properties(bus, "/org/freedesktop/login1", &new_line);
|
|
|
|
|
2019-04-28 18:02:03 +02:00
|
|
|
return print_session_status_info(bus, "/org/freedesktop/login1/session/auto", &new_line);
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2017-04-13 12:34:59 +02:00
|
|
|
r = get_session_path(bus, argv[i], &error, &path);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to get session path: %s", bus_error_message(&error, r));
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-12-17 19:42:01 +01:00
|
|
|
if (properties)
|
|
|
|
r = show_properties(bus, path, &new_line);
|
2013-11-07 08:58:23 +01:00
|
|
|
else
|
2013-12-17 19:42:03 +01:00
|
|
|
r = print_session_status_info(bus, path, &new_line);
|
|
|
|
|
|
|
|
if (r < 0)
|
2013-11-07 08:58:23 +01:00
|
|
|
return r;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int show_user(int argc, char *argv[], void *userdata) {
|
2013-12-17 19:42:01 +01:00
|
|
|
bool properties, new_line = false;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
assert(bus);
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(argv);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
properties = !strstr(argv[0], "status");
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2018-11-11 12:56:29 +01:00
|
|
|
(void) pager_open(arg_pager_flags);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-09 01:43:53 +01:00
|
|
|
if (argc <= 1) {
|
2019-04-28 18:02:03 +02:00
|
|
|
/* If no argument is specified inspect the manager itself */
|
2015-01-09 01:43:53 +01:00
|
|
|
if (properties)
|
|
|
|
return show_properties(bus, "/org/freedesktop/login1", &new_line);
|
|
|
|
|
|
|
|
return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
|
2013-11-07 08:58:23 +01:00
|
|
|
}
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
|
2013-11-07 08:58:23 +01:00
|
|
|
const char *path = NULL;
|
|
|
|
uid_t uid;
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2018-08-02 18:36:47 +02:00
|
|
|
r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
|
2014-11-28 18:50:43 +01:00
|
|
|
if (r < 0)
|
2015-01-08 23:11:35 +01:00
|
|
|
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"GetUser",
|
|
|
|
&error, &reply,
|
|
|
|
"u", (uint32_t) uid);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to get user: %s", bus_error_message(&error, r));
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_message_read(reply, "o", &path);
|
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-12-17 19:42:01 +01:00
|
|
|
if (properties)
|
|
|
|
r = show_properties(bus, path, &new_line);
|
2013-06-20 03:45:08 +02:00
|
|
|
else
|
2013-12-17 19:42:03 +01:00
|
|
|
r = print_user_status_info(bus, path, &new_line);
|
|
|
|
|
|
|
|
if (r < 0)
|
2013-11-07 08:58:23 +01:00
|
|
|
return r;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int show_seat(int argc, char *argv[], void *userdata) {
|
2013-12-17 19:42:01 +01:00
|
|
|
bool properties, new_line = false;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-08 21:39:10 +02:00
|
|
|
|
|
|
|
assert(bus);
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(argv);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
properties = !strstr(argv[0], "status");
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2018-11-11 12:56:29 +01:00
|
|
|
(void) pager_open(arg_pager_flags);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2015-01-09 01:43:53 +01:00
|
|
|
if (argc <= 1) {
|
2019-04-28 18:02:03 +02:00
|
|
|
/* If no argument is specified inspect the manager itself */
|
2015-01-09 01:43:53 +01:00
|
|
|
if (properties)
|
|
|
|
return show_properties(bus, "/org/freedesktop/login1", &new_line);
|
|
|
|
|
2019-04-28 18:02:03 +02:00
|
|
|
return print_seat_status_info(bus, "/org/freedesktop/login1/seat/auto", &new_line);
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
|
2011-07-08 21:39:10 +02:00
|
|
|
const char *path = NULL;
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"GetSeat",
|
|
|
|
&error, &reply,
|
2015-01-08 23:11:35 +01:00
|
|
|
"s", argv[i]);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to get seat: %s", bus_error_message(&error, r));
|
2013-06-20 03:45:08 +02:00
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
r = sd_bus_message_read(reply, "o", &path);
|
|
|
|
if (r < 0)
|
2013-11-07 21:26:31 +01:00
|
|
|
return bus_log_parse_error(r);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2013-12-17 19:42:01 +01:00
|
|
|
if (properties)
|
|
|
|
r = show_properties(bus, path, &new_line);
|
2013-11-07 08:58:23 +01:00
|
|
|
else
|
2013-12-17 19:42:03 +01:00
|
|
|
r = print_seat_status_info(bus, path, &new_line);
|
|
|
|
|
|
|
|
if (r < 0)
|
2013-11-07 08:58:23 +01:00
|
|
|
return r;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int activate(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-01-08 15:33:46 +01:00
|
|
|
|
2015-01-09 21:30:39 +01:00
|
|
|
if (argc < 2) {
|
2020-01-21 13:43:04 +01:00
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1/session/auto",
|
|
|
|
"org.freedesktop.login1.Session",
|
|
|
|
streq(argv[0], "lock-session") ? "Lock" :
|
|
|
|
streq(argv[0], "unlock-session") ? "Unlock" :
|
|
|
|
streq(argv[0], "terminate-session") ? "Terminate" :
|
|
|
|
"Activate",
|
|
|
|
&error, NULL, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
|
2015-01-14 23:16:28 +01:00
|
|
|
|
2020-01-21 13:43:04 +01:00
|
|
|
return 0;
|
2015-01-09 21:30:39 +01:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2011-09-23 01:44:36 +02:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = sd_bus_call_method(
|
2012-08-08 14:38:05 +02:00
|
|
|
bus,
|
2011-07-09 00:04:27 +02:00
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
2015-01-08 23:11:35 +01:00
|
|
|
streq(argv[0], "lock-session") ? "LockSession" :
|
|
|
|
streq(argv[0], "unlock-session") ? "UnlockSession" :
|
|
|
|
streq(argv[0], "terminate-session") ? "TerminateSession" :
|
2012-08-08 14:38:05 +02:00
|
|
|
"ActivateSession",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
2015-01-08 23:11:35 +01:00
|
|
|
"s", argv[i]);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
2019-04-28 18:02:03 +02:00
|
|
|
return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
|
2011-07-09 00:04:27 +02:00
|
|
|
}
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int kill_session(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-13 19:58:35 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-13 19:58:35 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-01-08 15:33:46 +01:00
|
|
|
|
2011-07-13 19:58:35 +02:00
|
|
|
if (!arg_kill_who)
|
|
|
|
arg_kill_who = "all";
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2013-03-19 01:31:21 +01:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = sd_bus_call_method(
|
2013-03-19 01:31:21 +01:00
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"KillSession",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
2015-01-08 23:11:35 +01:00
|
|
|
"ssi", argv[i], arg_kill_who, arg_signal);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Could not kill session: %s", bus_error_message(&error, -r));
|
2011-07-13 19:58:35 +02:00
|
|
|
}
|
|
|
|
|
2013-03-19 01:31:21 +01:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int enable_linger(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
2015-01-14 23:16:28 +01:00
|
|
|
char* short_argv[3];
|
2013-11-07 08:58:23 +01:00
|
|
|
bool b;
|
2015-01-08 23:11:35 +01:00
|
|
|
int r, i;
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2012-04-11 18:50:16 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
b = streq(argv[0], "enable-linger");
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-01-09 21:30:39 +01:00
|
|
|
if (argc < 2) {
|
2017-09-18 19:04:59 +02:00
|
|
|
/* No argument? Let's use an empty user name,
|
|
|
|
* then logind will use our user. */
|
2017-06-01 04:23:30 +02:00
|
|
|
|
2015-01-14 23:16:28 +01:00
|
|
|
short_argv[0] = argv[0];
|
2017-09-18 19:04:59 +02:00
|
|
|
short_argv[1] = (char*) "";
|
2015-01-14 23:16:28 +01:00
|
|
|
short_argv[2] = NULL;
|
|
|
|
argv = short_argv;
|
2015-01-09 21:30:39 +01:00
|
|
|
argc = 2;
|
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2011-07-23 00:47:17 +02:00
|
|
|
uid_t uid;
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-01-09 21:30:39 +01:00
|
|
|
if (isempty(argv[i]))
|
|
|
|
uid = UID_INVALID;
|
|
|
|
else {
|
2018-08-02 18:36:47 +02:00
|
|
|
r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
|
2015-01-09 21:30:39 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
|
|
|
|
}
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = sd_bus_call_method(
|
2013-03-19 01:31:21 +01:00
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"SetUserLinger",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
|
|
|
"ubb", (uint32_t) uid, b, true);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Could not enable linger: %s", bus_error_message(&error, -r));
|
2011-07-09 02:58:05 +02:00
|
|
|
}
|
|
|
|
|
2013-03-19 01:31:21 +01:00
|
|
|
return 0;
|
2011-07-09 02:58:05 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int terminate_user(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-01-08 15:33:46 +01:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2011-07-23 00:47:17 +02:00
|
|
|
uid_t uid;
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2018-08-02 18:36:47 +02:00
|
|
|
r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
|
2014-11-28 18:50:43 +01:00
|
|
|
if (r < 0)
|
2015-01-08 23:11:35 +01:00
|
|
|
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = sd_bus_call_method(
|
2013-03-19 01:31:21 +01:00
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"TerminateUser",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
|
|
|
"u", (uint32_t) uid);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Could not terminate user: %s", bus_error_message(&error, -r));
|
2011-07-09 02:58:05 +02:00
|
|
|
}
|
|
|
|
|
2013-03-19 01:31:21 +01:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int kill_user(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-13 19:58:35 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-13 19:58:35 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-01-08 15:33:46 +01:00
|
|
|
|
2011-07-13 19:58:35 +02:00
|
|
|
if (!arg_kill_who)
|
|
|
|
arg_kill_who = "all";
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2011-07-23 00:47:17 +02:00
|
|
|
uid_t uid;
|
2011-07-13 19:58:35 +02:00
|
|
|
|
2018-08-02 18:36:47 +02:00
|
|
|
r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0);
|
2014-11-28 18:50:43 +01:00
|
|
|
if (r < 0)
|
2015-01-08 23:11:35 +01:00
|
|
|
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
|
2011-07-13 19:58:35 +02:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = sd_bus_call_method(
|
2013-03-19 01:31:21 +01:00
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"KillUser",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
|
|
|
"ui", (uint32_t) uid, arg_signal);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Could not kill user: %s", bus_error_message(&error, -r));
|
2011-07-13 19:58:35 +02:00
|
|
|
}
|
|
|
|
|
2013-03-19 01:31:21 +01:00
|
|
|
return 0;
|
2011-07-13 19:58:35 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int attach(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2012-04-11 18:50:16 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 2; i < argc; i++) {
|
2013-03-19 01:31:21 +01:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = sd_bus_call_method(
|
2013-03-19 01:31:21 +01:00
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"AttachDevice",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
2015-01-08 23:11:35 +01:00
|
|
|
"ssb", argv[1], argv[i], true);
|
2013-11-07 08:58:23 +01:00
|
|
|
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Could not attach device: %s", bus_error_message(&error, -r));
|
2011-07-09 02:58:05 +02:00
|
|
|
}
|
|
|
|
|
2013-03-19 01:31:21 +01:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int flush_devices(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2012-04-11 18:50:16 +02:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = sd_bus_call_method(
|
2012-08-08 14:38:05 +02:00
|
|
|
bus,
|
2011-07-09 02:58:05 +02:00
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
2012-08-08 14:38:05 +02:00
|
|
|
"FlushDevices",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
|
|
|
"b", true);
|
|
|
|
if (r < 0)
|
2018-08-07 03:14:30 +02:00
|
|
|
return log_error_errno(r, "Could not flush devices: %s", bus_error_message(&error, -r));
|
2013-11-07 08:58:23 +01:00
|
|
|
|
2018-08-07 03:14:30 +02:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int lock_sessions(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
2013-01-24 05:29:37 +01:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2012-07-29 17:08:47 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-01-08 15:33:46 +01:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
r = sd_bus_call_method(
|
2012-08-08 14:38:05 +02:00
|
|
|
bus,
|
2012-07-29 17:08:47 +02:00
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
2015-01-08 23:11:35 +01:00
|
|
|
streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
|
|
|
NULL);
|
|
|
|
if (r < 0)
|
2018-08-07 03:14:30 +02:00
|
|
|
return log_error_errno(r, "Could not lock sessions: %s", bus_error_message(&error, -r));
|
2013-11-07 08:58:23 +01:00
|
|
|
|
2018-08-07 03:14:30 +02:00
|
|
|
return 0;
|
2012-07-29 17:08:47 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int terminate_seat(int argc, char *argv[], void *userdata) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-08 23:11:35 +01:00
|
|
|
sd_bus *bus = userdata;
|
|
|
|
int r, i;
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(argv);
|
2011-07-09 02:58:05 +02:00
|
|
|
|
2017-10-30 09:57:53 +01:00
|
|
|
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
2015-01-08 15:33:46 +01:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2013-03-19 01:31:21 +01:00
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
r = sd_bus_call_method(
|
2013-03-19 01:31:21 +01:00
|
|
|
bus,
|
|
|
|
"org.freedesktop.login1",
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
"TerminateSeat",
|
2013-11-07 08:58:23 +01:00
|
|
|
&error, NULL,
|
2015-01-08 23:11:35 +01:00
|
|
|
"s", argv[i]);
|
2018-08-07 03:14:30 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Could not terminate seat: %s", bus_error_message(&error, -r));
|
2011-07-09 02:58:05 +02:00
|
|
|
}
|
|
|
|
|
2013-03-19 01:31:21 +01:00
|
|
|
return 0;
|
2011-07-08 21:39:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int help(int argc, char *argv[], void *userdata) {
|
2018-08-09 10:32:31 +02:00
|
|
|
_cleanup_free_ char *link = NULL;
|
|
|
|
int r;
|
|
|
|
|
2018-11-11 12:56:29 +01:00
|
|
|
(void) pager_open(arg_pager_flags);
|
2018-08-09 10:32:31 +02:00
|
|
|
|
|
|
|
r = terminal_urlify_man("loginctl", "1", &link);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
2015-01-08 15:33:46 +01:00
|
|
|
|
2019-11-15 18:38:44 +01:00
|
|
|
printf("%s [OPTIONS...] COMMAND ...\n\n"
|
|
|
|
"%sSend control commands to or query the login manager.%s\n"
|
2019-10-08 17:58:44 +02:00
|
|
|
"\nSession Commands:\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" list-sessions List sessions\n"
|
2015-01-09 01:43:53 +01:00
|
|
|
" session-status [ID...] Show session status\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" show-session [ID...] Show properties of sessions or the manager\n"
|
2015-01-09 21:30:39 +01:00
|
|
|
" activate [ID] Activate a session\n"
|
|
|
|
" lock-session [ID...] Screen lock one or more sessions\n"
|
|
|
|
" unlock-session [ID...] Screen unlock one or more sessions\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" lock-sessions Screen lock all current sessions\n"
|
|
|
|
" unlock-sessions Screen unlock all current sessions\n"
|
|
|
|
" terminate-session ID... Terminate one or more sessions\n"
|
2019-11-15 18:38:44 +01:00
|
|
|
" kill-session ID... Send signal to processes of a session\n"
|
|
|
|
"\nUser Commands:\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" list-users List users\n"
|
2015-01-09 01:43:53 +01:00
|
|
|
" user-status [USER...] Show user status\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" show-user [USER...] Show properties of users or the manager\n"
|
2015-01-09 21:30:39 +01:00
|
|
|
" enable-linger [USER...] Enable linger state of one or more users\n"
|
|
|
|
" disable-linger [USER...] Disable linger state of one or more users\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" terminate-user USER... Terminate all sessions of one or more users\n"
|
2019-11-15 18:38:44 +01:00
|
|
|
" kill-user USER... Send signal to processes of a user\n"
|
|
|
|
"\nSeat Commands:\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" list-seats List seats\n"
|
2015-01-09 01:43:53 +01:00
|
|
|
" seat-status [NAME...] Show seat status\n"
|
|
|
|
" show-seat [NAME...] Show properties of seats or the manager\n"
|
2013-12-08 14:16:59 +01:00
|
|
|
" attach NAME DEVICE... Attach one or more devices to a seat\n"
|
|
|
|
" flush-devices Flush all device associations\n"
|
2014-08-02 17:12:21 +02:00
|
|
|
" terminate-seat NAME... Terminate all sessions on one or more seats\n"
|
2019-11-15 18:38:44 +01:00
|
|
|
"\nOptions:\n"
|
2019-10-08 17:58:44 +02:00
|
|
|
" -h --help Show this help\n"
|
|
|
|
" --version Show package version\n"
|
|
|
|
" --no-pager Do not pipe output into a pager\n"
|
|
|
|
" --no-legend Do not show the headers and footers\n"
|
|
|
|
" --no-ask-password Don't prompt for password\n"
|
|
|
|
" -H --host=[USER@]HOST Operate on remote host\n"
|
|
|
|
" -M --machine=CONTAINER Operate on local container\n"
|
|
|
|
" -p --property=NAME Show only properties by this name\n"
|
|
|
|
" -a --all Show all properties, including empty ones\n"
|
|
|
|
" --value When showing properties, only print the value\n"
|
|
|
|
" -l --full Do not ellipsize output\n"
|
|
|
|
" --kill-who=WHO Who to send signal to\n"
|
|
|
|
" -s --signal=SIGNAL Which signal to send\n"
|
|
|
|
" -n --lines=INTEGER Number of journal entries to show\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, json-seq, cat,\n"
|
|
|
|
" with-unit)\n"
|
2018-08-09 10:32:31 +02:00
|
|
|
"\nSee the %s for details.\n"
|
|
|
|
, program_invocation_short_name
|
2019-11-15 18:38:44 +01:00
|
|
|
, ansi_highlight()
|
2019-10-08 18:19:59 +02:00
|
|
|
, ansi_normal()
|
2018-08-09 10:32:31 +02:00
|
|
|
, link
|
|
|
|
);
|
2015-01-08 23:11:35 +01:00
|
|
|
|
|
|
|
return 0;
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_argv(int argc, char *argv[]) {
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ARG_VERSION = 0x100,
|
2016-03-17 17:48:02 +01:00
|
|
|
ARG_VALUE,
|
2011-07-08 21:39:10 +02:00
|
|
|
ARG_NO_PAGER,
|
2013-12-21 20:20:29 +01:00
|
|
|
ARG_NO_LEGEND,
|
2012-04-11 18:50:16 +02:00
|
|
|
ARG_KILL_WHO,
|
2013-01-14 18:16:50 +01:00
|
|
|
ARG_NO_ASK_PASSWORD,
|
2011-07-07 03:29:56 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct option options[] = {
|
2012-10-17 02:50:09 +02:00
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "version", no_argument, NULL, ARG_VERSION },
|
|
|
|
{ "property", required_argument, NULL, 'p' },
|
|
|
|
{ "all", no_argument, NULL, 'a' },
|
2016-03-17 17:48:02 +01:00
|
|
|
{ "value", no_argument, NULL, ARG_VALUE },
|
2013-06-20 00:08:14 +02:00
|
|
|
{ "full", no_argument, NULL, 'l' },
|
2012-10-17 02:50:09 +02:00
|
|
|
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
2013-12-21 20:20:29 +01:00
|
|
|
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
2012-10-17 02:50:09 +02:00
|
|
|
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
|
|
|
|
{ "signal", required_argument, NULL, 's' },
|
|
|
|
{ "host", required_argument, NULL, 'H' },
|
2013-11-07 08:58:23 +01:00
|
|
|
{ "machine", required_argument, NULL, 'M' },
|
2012-10-17 02:50:09 +02:00
|
|
|
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
|
2015-01-08 14:38:52 +01:00
|
|
|
{ "lines", required_argument, NULL, 'n' },
|
|
|
|
{ "output", required_argument, NULL, 'o' },
|
2013-11-06 18:28:39 +01:00
|
|
|
{}
|
2011-07-07 03:29:56 +02:00
|
|
|
};
|
|
|
|
|
2013-12-17 19:42:00 +01:00
|
|
|
int c, r;
|
2011-07-07 03:29:56 +02:00
|
|
|
|
|
|
|
assert(argc >= 0);
|
|
|
|
assert(argv);
|
|
|
|
|
2015-01-08 14:38:52 +01:00
|
|
|
while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
|
2011-07-07 03:29:56 +02:00
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
|
|
case 'h':
|
2018-08-09 10:32:31 +02:00
|
|
|
return help(0, NULL, NULL);
|
2011-07-07 03:29:56 +02:00
|
|
|
|
|
|
|
case ARG_VERSION:
|
2015-09-23 03:01:06 +02:00
|
|
|
return version();
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2011-07-08 21:39:10 +02:00
|
|
|
case 'p': {
|
2013-12-17 19:42:00 +01:00
|
|
|
r = strv_extend(&arg_property, optarg);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
2011-07-08 21:39:10 +02:00
|
|
|
|
|
|
|
/* If the user asked for a particular
|
|
|
|
* property, show it to him, even if it is
|
|
|
|
* empty. */
|
|
|
|
arg_all = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'a':
|
|
|
|
arg_all = true;
|
|
|
|
break;
|
|
|
|
|
2016-03-17 17:48:02 +01:00
|
|
|
case ARG_VALUE:
|
|
|
|
arg_value = true;
|
|
|
|
break;
|
|
|
|
|
2013-06-20 00:08:14 +02:00
|
|
|
case 'l':
|
|
|
|
arg_full = true;
|
|
|
|
break;
|
|
|
|
|
2015-01-08 14:38:52 +01:00
|
|
|
case 'n':
|
2018-11-20 23:40:44 +01:00
|
|
|
if (safe_atou(optarg, &arg_lines) < 0)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Failed to parse lines '%s'", optarg);
|
2015-01-08 14:38:52 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'o':
|
2018-05-22 12:10:56 +02:00
|
|
|
if (streq(optarg, "help")) {
|
|
|
|
DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-01-08 14:38:52 +01:00
|
|
|
arg_output = output_mode_from_string(optarg);
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_output < 0)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Unknown output '%s'.", optarg);
|
2018-12-03 20:46:33 +01:00
|
|
|
|
|
|
|
if (OUTPUT_MODE_IS_JSON(arg_output))
|
|
|
|
arg_legend = false;
|
|
|
|
|
2015-01-08 14:38:52 +01:00
|
|
|
break;
|
|
|
|
|
2011-07-07 03:29:56 +02:00
|
|
|
case ARG_NO_PAGER:
|
2018-11-11 12:56:29 +01:00
|
|
|
arg_pager_flags |= PAGER_DISABLE;
|
2011-07-07 03:29:56 +02:00
|
|
|
break;
|
|
|
|
|
2013-12-21 20:20:29 +01:00
|
|
|
case ARG_NO_LEGEND:
|
|
|
|
arg_legend = false;
|
|
|
|
break;
|
|
|
|
|
2012-04-11 18:50:16 +02:00
|
|
|
case ARG_NO_ASK_PASSWORD:
|
|
|
|
arg_ask_password = false;
|
2012-09-21 12:33:32 +02:00
|
|
|
break;
|
2012-04-11 18:50:16 +02:00
|
|
|
|
2011-07-08 21:39:10 +02:00
|
|
|
case ARG_KILL_WHO:
|
|
|
|
arg_kill_who = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's':
|
2018-05-22 12:10:56 +02:00
|
|
|
if (streq(optarg, "help")) {
|
|
|
|
DUMP_STRING_TABLE(signal, int, _NSIG);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-03 09:38:57 +02:00
|
|
|
arg_signal = signal_from_string(optarg);
|
2018-11-20 23:40:44 +01:00
|
|
|
if (arg_signal < 0)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Failed to parse signal string %s.", optarg);
|
2011-07-08 21:39:10 +02:00
|
|
|
break;
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
case 'H':
|
|
|
|
arg_transport = BUS_TRANSPORT_REMOTE;
|
|
|
|
arg_host = optarg;
|
2011-07-07 03:29:56 +02:00
|
|
|
break;
|
|
|
|
|
2013-11-07 08:58:23 +01:00
|
|
|
case 'M':
|
2014-12-23 23:38:13 +01:00
|
|
|
arg_transport = BUS_TRANSPORT_MACHINE;
|
2013-11-07 08:58:23 +01:00
|
|
|
arg_host = optarg;
|
2011-07-07 03:29:56 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '?':
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
default:
|
2013-11-06 18:28:39 +01:00
|
|
|
assert_not_reached("Unhandled option");
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
|
|
|
|
|
|
|
|
static const Verb verbs[] = {
|
|
|
|
{ "help", VERB_ANY, VERB_ANY, 0, help },
|
|
|
|
{ "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
|
2015-01-09 01:43:53 +01:00
|
|
|
{ "session-status", VERB_ANY, VERB_ANY, 0, show_session },
|
2015-01-08 23:11:35 +01:00
|
|
|
{ "show-session", VERB_ANY, VERB_ANY, 0, show_session },
|
2015-01-09 21:30:39 +01:00
|
|
|
{ "activate", VERB_ANY, 2, 0, activate },
|
|
|
|
{ "lock-session", VERB_ANY, VERB_ANY, 0, activate },
|
|
|
|
{ "unlock-session", VERB_ANY, VERB_ANY, 0, activate },
|
2015-01-08 23:11:35 +01:00
|
|
|
{ "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
|
|
|
|
{ "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
|
|
|
|
{ "terminate-session", 2, VERB_ANY, 0, activate },
|
|
|
|
{ "kill-session", 2, VERB_ANY, 0, kill_session },
|
|
|
|
{ "list-users", VERB_ANY, 1, 0, list_users },
|
2015-01-09 01:43:53 +01:00
|
|
|
{ "user-status", VERB_ANY, VERB_ANY, 0, show_user },
|
2015-01-08 23:11:35 +01:00
|
|
|
{ "show-user", VERB_ANY, VERB_ANY, 0, show_user },
|
2015-01-09 21:30:39 +01:00
|
|
|
{ "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
|
|
|
|
{ "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger },
|
2015-01-08 23:11:35 +01:00
|
|
|
{ "terminate-user", 2, VERB_ANY, 0, terminate_user },
|
|
|
|
{ "kill-user", 2, VERB_ANY, 0, kill_user },
|
|
|
|
{ "list-seats", VERB_ANY, 1, 0, list_seats },
|
2015-01-09 01:43:53 +01:00
|
|
|
{ "seat-status", VERB_ANY, VERB_ANY, 0, show_seat },
|
|
|
|
{ "show-seat", VERB_ANY, VERB_ANY, 0, show_seat },
|
2015-01-08 23:11:35 +01:00
|
|
|
{ "attach", 3, VERB_ANY, 0, attach },
|
|
|
|
{ "flush-devices", VERB_ANY, 1, 0, flush_devices },
|
|
|
|
{ "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
|
|
|
|
{}
|
2011-07-07 03:29:56 +02:00
|
|
|
};
|
|
|
|
|
2015-01-08 23:11:35 +01:00
|
|
|
return dispatch_verb(argc, argv, verbs, bus);
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
|
|
|
|
2018-11-20 10:15:33 +01:00
|
|
|
static int run(int argc, char *argv[]) {
|
|
|
|
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
2013-11-07 08:58:23 +01:00
|
|
|
int r;
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2012-11-12 20:16:07 +01:00
|
|
|
setlocale(LC_ALL, "");
|
2019-04-26 12:28:25 +02:00
|
|
|
log_show_color(true);
|
2011-07-07 03:29:56 +02:00
|
|
|
log_parse_environment();
|
|
|
|
log_open();
|
2018-10-01 17:44:46 +02:00
|
|
|
|
|
|
|
/* The journal merging logic potentially needs a lot of fds. */
|
|
|
|
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
|
|
|
|
|
2017-11-10 21:04:08 +01:00
|
|
|
sigbus_install();
|
2011-07-07 03:29:56 +02:00
|
|
|
|
|
|
|
r = parse_argv(argc, argv);
|
2013-11-07 08:58:23 +01:00
|
|
|
if (r <= 0)
|
2018-11-20 10:15:33 +01:00
|
|
|
return r;
|
2013-11-07 08:58:23 +01:00
|
|
|
|
2015-09-24 13:30:10 +02:00
|
|
|
r = bus_connect_transport(arg_transport, arg_host, false, &bus);
|
2018-11-20 10:15:33 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to create bus connection: %m");
|
2011-07-07 03:29:56 +02:00
|
|
|
|
2018-11-20 10:15:33 +01:00
|
|
|
(void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
|
2011-07-08 21:39:10 +02:00
|
|
|
|
2018-11-20 10:15:33 +01:00
|
|
|
return loginctl_main(argc, argv, bus);
|
2011-07-07 03:29:56 +02:00
|
|
|
}
|
2018-11-20 10:15:33 +01:00
|
|
|
|
|
|
|
DEFINE_MAIN_FUNCTION(run);
|