loginctl.c revision 9444b1f20e311f073864d81e913bd4f32fe95cfd
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2010 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmekstatic char **arg_property = NULL;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmekstatic bool arg_all = false;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmekstatic bool arg_full = false;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmekstatic bool arg_no_pager = false;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmekstatic const char *arg_kill_who = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic bool arg_ask_password = true;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic void pager_open_if_enabled(void) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Cache result before we open the pager */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic void polkit_agent_open_if_enabled(void) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Open the polkit agent as a child process if necessary */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int list_sessions(DBusConnection *bus, char **args, unsigned n) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering unsigned k = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "org.freedesktop.login1",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "org.freedesktop.login1.Manager",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "ListSessions",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!dbus_message_iter_init(reply, &iter) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &user, true) < 0 ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &seat, true) < 0 ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int list_users(DBusConnection *bus, char **args, unsigned n) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering unsigned k = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "org.freedesktop.login1",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "org.freedesktop.login1.Manager",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!dbus_message_iter_init(reply, &iter) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &user, true) < 0 ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek printf("%10u %-16s\n", (unsigned) uid, user);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int list_seats(DBusConnection *bus, char **args, unsigned n) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek DBusMessageIter iter, sub, sub2;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering unsigned k = 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "org.freedesktop.login1",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "org.freedesktop.login1.Manager",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!dbus_message_iter_init(reply, &iter) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &seat, true) < 0 ||
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int list_machines(DBusConnection *bus, char **args, unsigned n) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering unsigned k = 0;
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek "org.freedesktop.login1",
ac50788b0f5aeee09e7d45db28ae8ab7f39cd52eZbigniew Jędrzejewski-Szmek "org.freedesktop.login1.Manager",
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!dbus_message_iter_init(reply, &iter) ||
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering const char *name, *class, *service, *object;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &class, true) < 0 ||
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &service, true) < 0 ||
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering printf("%-32s %-9s %-16s\n", name, class, service);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic void print_session_status_info(SessionStatusInfo *i) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering printf("%s (%u)\n", i->name, (unsigned) i->uid);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering printf("\t Leader: %u", (unsigned) i->leader);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering printf("\t Remote: %s@%s\n", i->remote_user, i->remote_host);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek printf("\t Remote: %s\n", i->remote_host);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek printf("\t Remote: user %s\n", i->remote_user);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else if (i->type) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else if (i->class)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt printf("\t CGroup: %s\n", i->default_control_group);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering show_cgroup_and_extra_by_spec(i->default_control_group,
178cc7700c23ac088cd7190d7854282075028d91Lennart Poetteringstatic void print_user_status_info(UserStatusInfo *i) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
if (i->name)
if (s1)
else if (s2)
if (i->slice)
if (i->default_control_group) {
int output_flags =
c = columns();
c, false, output_flags);
assert(i);
c = columns();
assert(i);
if (s1)
else if (s2)
if (i->leader > 0) {
if (i->service) {
if (i->class)
} else if (i->class)
if (i->slice)
if (i->root_directory)
if (i->default_control_group) {
int output_flags =
c = columns();
assert(i);
case DBUS_TYPE_STRING: {
if (!isempty(s)) {
i->id = s;
i->name = s;
i->default_control_group = s;
i->tty = s;
i->display = s;
i->remote_host = s;
i->remote_user = s;
i->service = s;
i->type = s;
i->class = s;
i->slice = s;
i->state = s;
case DBUS_TYPE_UINT32: {
uint32_t u;
i->vtnr = (int) u;
case DBUS_TYPE_BOOLEAN: {
dbus_bool_t b;
i->remote = b;
case DBUS_TYPE_UINT64: {
uint64_t u;
case DBUS_TYPE_STRUCT: {
uint32_t u;
if (!isempty(s))
i->seat = s;
assert(i);
case DBUS_TYPE_STRING: {
if (!isempty(s)) {
i->name = s;
i->default_control_group = s;
i->slice = s;
i->state = s;
case DBUS_TYPE_UINT32: {
uint32_t u;
case DBUS_TYPE_UINT64: {
uint64_t u;
case DBUS_TYPE_STRUCT: {
if (!isempty(s))
i->display = s;
case DBUS_TYPE_ARRAY: {
const char *id;
const char *path;
return -ENOMEM;
i->sessions = l;
assert(i);
case DBUS_TYPE_STRING: {
if (!isempty(s)) {
i->id = s;
case DBUS_TYPE_STRUCT: {
if (!isempty(s))
i->active_session = s;
case DBUS_TYPE_ARRAY: {
const char *id;
const char *path;
return -ENOMEM;
i->sessions = l;
assert(i);
case DBUS_TYPE_STRING: {
if (!isempty(s)) {
i->name = s;
i->default_control_group = s;
i->class = s;
i->service = s;
i->slice = s;
i->root_directory = s;
case DBUS_TYPE_UINT32: {
uint32_t u;
case DBUS_TYPE_UINT64: {
uint64_t u;
case DBUS_TYPE_ARRAY: {
case DBUS_TYPE_STRUCT: {
case DBUS_TYPE_ARRAY:
bool found = false;
const char *id;
const char *path;
if (found)
found = true;
else if (found)
if (arg_all)
static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
bus,
path,
&reply,
NULL,
goto finish;
r = -EIO;
goto finish;
if (*new_line)
*new_line = true;
const char *name;
r = -EIO;
goto finish;
r = -EIO;
goto finish;
r = -EIO;
goto finish;
if (show_properties)
goto finish;
if (!show_properties) {
int r, ret = 0;
goto finish;
bus,
"/org/freedesktop/login1",
&reply,
NULL,
uint32_t u;
if (ret < 0) {
goto finish;
bus,
"/org/freedesktop/login1",
&reply,
NULL,
DBUS_TYPE_UINT32, &u,
bus,
"/org/freedesktop/login1",
&reply,
NULL,
bus,
"/org/freedesktop/login1",
&reply,
NULL,
if (ret < 0)
goto finish;
goto finish;
ret = r;
return ret;
int ret = 0;
bus,
"/org/freedesktop/login1",
NULL,
NULL,
if (ret)
goto finish;
return ret;
if (!arg_kill_who)
bus,
"/org/freedesktop/login1",
NULL,
NULL,
if (!arg_kill_who)
bus,
"/org/freedesktop/login1",
NULL,
NULL,
uint32_t u;
bus,
"/org/freedesktop/login1",
NULL,
NULL,
DBUS_TYPE_UINT32, &u,
DBUS_TYPE_BOOLEAN, &b,
uint32_t u;
bus,
"/org/freedesktop/login1",
NULL,
NULL,
DBUS_TYPE_UINT32, &u,
if (!arg_kill_who)
uint32_t u;
bus,
"/org/freedesktop/login1",
NULL,
NULL,
DBUS_TYPE_UINT32, &u,
bus,
"/org/freedesktop/login1",
NULL,
NULL,
return bus_method_call_with_reply (
bus,
"/org/freedesktop/login1",
NULL,
NULL,
return bus_method_call_with_reply (
bus,
"/org/freedesktop/login1",
NULL,
NULL,
bus,
"/org/freedesktop/login1",
NULL,
NULL,
bus,
"/org/freedesktop/login1",
NULL,
NULL,
static int help(void) {
" show-machine [NAME...] Show properties of one or more VMs/containers\n"
" terminate-machine [NAME...] Terminate one or more VMs/containers\n"
help();
case ARG_VERSION:
return -ENOMEM;
arg_property = l;
arg_all = true;
arg_all = true;
arg_full = true;
case ARG_NO_PAGER:
arg_no_pager = true;
case ARG_NO_ASK_PASSWORD:
arg_ask_password = false;
case ARG_KILL_WHO:
if (arg_signal < 0) {
return -EINVAL;
return -EINVAL;
return -EINVAL;
const char* verb;
MORE,
LESS,
} argc_cmp;
const int argc;
} verbs[] = {
int left;
if (left <= 0)
help();
return -EINVAL;
case EQUAL:
return -EINVAL;
case MORE:
return -EINVAL;
case LESS:
return -EINVAL;
if (!bus) {
return -EIO;
log_open();
goto finish;
goto finish;
if (bus) {
pager_close();
return retval;