From 22c902faccb3840350de6534776351131de95daa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 7 Aug 2019 16:22:35 +0200 Subject: [PATCH] logind: port to UserRecord object This changes the user tracking of logind to use the new-style UserRecord object. In a later commit this enables us to do per-user resource management. --- src/login/logind-core.c | 39 ++++++++++--------- src/login/logind-dbus.c | 10 ++--- src/login/logind-seat.c | 8 ++-- src/login/logind-session-dbus.c | 22 +++++------ src/login/logind-session.c | 20 +++++----- src/login/logind-user-dbus.c | 68 +++++++++++++++++++++++++++++---- src/login/logind-user.c | 58 ++++++++++++---------------- src/login/logind-user.h | 10 ++--- src/login/logind.h | 5 ++- 9 files changed, 144 insertions(+), 96 deletions(-) diff --git a/src/login/logind-core.c b/src/login/logind-core.c index e84b38096a..22a42b077c 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -27,6 +27,7 @@ #include "terminal-util.h" #include "udev-util.h" #include "user-util.h" +#include "userdb.h" void manager_reset_config(Manager *m) { assert(m); @@ -137,21 +138,18 @@ int manager_add_session(Manager *m, const char *id, Session **ret_session) { int manager_add_user( Manager *m, - uid_t uid, - gid_t gid, - const char *name, - const char *home, + UserRecord *ur, User **ret_user) { User *u; int r; assert(m); - assert(name); + assert(ur); - u = hashmap_get(m->users, UID_TO_PTR(uid)); + u = hashmap_get(m->users, UID_TO_PTR(ur->uid)); if (!u) { - r = user_new(&u, m, uid, gid, name, home); + r = user_new(&u, m, ur); if (r < 0) return r; } @@ -167,32 +165,35 @@ int manager_add_user_by_name( const char *name, User **ret_user) { - const char *home = NULL; - uid_t uid; - gid_t gid; + _cleanup_(user_record_unrefp) UserRecord *ur = NULL; int r; assert(m); assert(name); - r = get_user_creds(&name, &uid, &gid, &home, NULL, 0); + r = userdb_by_name(name, 0, &ur); if (r < 0) return r; - return manager_add_user(m, uid, gid, name, home, ret_user); + return manager_add_user(m, ur, ret_user); } -int manager_add_user_by_uid(Manager *m, uid_t uid, User **ret_user) { - struct passwd *p; +int manager_add_user_by_uid( + Manager *m, + uid_t uid, + User **ret_user) { + + _cleanup_(user_record_unrefp) UserRecord *ur = NULL; + int r; assert(m); + assert(uid_is_valid(uid)); - errno = 0; - p = getpwuid(uid); - if (!p) - return errno_or_else(ENOENT); + r = userdb_by_uid(uid, 0, &ur); + if (r < 0) + return r; - return manager_add_user(m, uid, p->pw_gid, p->pw_name, p->pw_dir, ret_user); + return manager_add_user(m, ur, ret_user); } int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret) { diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 69b5994878..d3aa6815a6 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -536,8 +536,8 @@ static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_ r = sd_bus_message_append(reply, "(susso)", session->id, - (uint32_t) session->user->uid, - session->user->name, + (uint32_t) session->user->user_record->uid, + session->user->user_record->user_name, session->seat ? session->seat->id : "", p); if (r < 0) @@ -577,8 +577,8 @@ static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_err return -ENOMEM; r = sd_bus_message_append(reply, "(uso)", - (uint32_t) user->uid, - user->name, + (uint32_t) user->user_record->uid, + user->user_record->user_name, p); if (r < 0) return r; @@ -1488,7 +1488,7 @@ static int have_multiple_sessions( * count, and non-login sessions do not count either. */ HASHMAP_FOREACH(session, m->sessions, i) if (session->class == SESSION_USER && - session->user->uid != uid) + session->user->user_record->uid != uid) return true; return false; diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 026bcf4d8e..394f89dd7e 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -119,7 +119,7 @@ int seat_save(Seat *s) { "ACTIVE=%s\n" "ACTIVE_UID="UID_FMT"\n", s->active->id, - s->active->user->uid); + s->active->user->user_record->uid); } if (s->sessions) { @@ -137,7 +137,7 @@ int seat_save(Seat *s) { LIST_FOREACH(sessions_by_seat, i, s->sessions) fprintf(f, UID_FMT"%c", - i->user->uid, + i->user->user_record->uid, i->sessions_by_seat_next ? ' ' : '\n'); } @@ -216,8 +216,8 @@ int seat_apply_acls(Seat *s, Session *old_active) { r = devnode_acl_all(s->id, false, - !!old_active, old_active ? old_active->user->uid : 0, - !!s->active, s->active ? s->active->user->uid : 0); + !!old_active, old_active ? old_active->user->user_record->uid : 0, + !!s->active, s->active ? s->active->user->user_record->uid : 0); if (r < 0) return log_error_errno(r, "Failed to apply ACLs: %m"); diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 32a64fff0c..80f3e432de 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -43,7 +43,7 @@ static int property_get_user( if (!p) return -ENOMEM; - return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->uid, p); + return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->user_record->uid, p); } static int property_get_name( @@ -61,7 +61,7 @@ static int property_get_name( assert(reply); assert(s); - return sd_bus_message_append(reply, "s", s->user->name); + return sd_bus_message_append(reply, "s", s->user->user_record->user_name); } static int property_get_seat( @@ -168,7 +168,7 @@ int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus "org.freedesktop.login1.manage", NULL, false, - s->user->uid, + s->user->user_record->uid, &s->manager->polkit_registry, error); if (r < 0) @@ -210,7 +210,7 @@ int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_erro "org.freedesktop.login1.lock-sessions", NULL, false, - s->user->uid, + s->user->user_record->uid, &s->manager->polkit_registry, error); if (r < 0) @@ -246,7 +246,7 @@ static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_ if (r < 0) return r; - if (uid != 0 && uid != s->user->uid) + if (uid != 0 && uid != s->user->user_record->uid) return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint"); r = session_set_idle_hint(s, b); @@ -279,7 +279,7 @@ static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bu if (r < 0) return r; - if (uid != 0 && uid != s->user->uid) + if (uid != 0 && uid != s->user->user_record->uid) return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint"); session_set_locked_hint(s, b); @@ -318,7 +318,7 @@ int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro "org.freedesktop.login1.manage", NULL, false, - s->user->uid, + s->user->user_record->uid, &s->manager->polkit_registry, error); if (r < 0) @@ -354,7 +354,7 @@ static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_e if (r < 0) return r; - if (uid != 0 && (force || uid != s->user->uid)) + if (uid != 0 && (force || uid != s->user->user_record->uid)) return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control"); r = session_set_controller(s, sd_bus_message_get_sender(message), force, true); @@ -523,7 +523,7 @@ static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus if (r < 0) return r; - if (uid != 0 && uid != s->user->uid) + if (uid != 0 && uid != s->user->user_record->uid) return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may change brightness."); r = sd_device_new_from_subsystem_sysname(&d, subsystem, name); @@ -822,7 +822,7 @@ int session_send_create_reply(Session *s, sd_bus_error *error) { "session_fd=%d seat=%s vtnr=%u", s->id, p, - (uint32_t) s->user->uid, + (uint32_t) s->user->user_record->uid, s->user->runtime_path, fifo_fd, s->seat ? s->seat->id : "", @@ -834,7 +834,7 @@ int session_send_create_reply(Session *s, sd_bus_error *error) { p, s->user->runtime_path, fifo_fd, - (uint32_t) s->user->uid, + (uint32_t) s->user->user_record->uid, s->seat ? s->seat->id : "", (uint32_t) s->vtnr, false); diff --git a/src/login/logind-session.c b/src/login/logind-session.c index a9be416f52..f9e122975e 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -230,8 +230,8 @@ int session_save(Session *s) { "IS_DISPLAY=%i\n" "STATE=%s\n" "REMOTE=%i\n", - s->user->uid, - s->user->name, + s->user->user_record->uid, + s->user->user_record->user_name, session_is_active(s), s->user->display == s, session_state_to_string(session_get_state(s)), @@ -641,7 +641,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er if (!scope) return log_oom(); - description = strjoina("Session ", s->id, " of user ", s->user->name); + description = strjoina("Session ", s->id, " of user ", s->user->user_record->user_name); r = manager_start_scope( s->manager, @@ -657,7 +657,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), - s->user->home, + user_record_home_directory(s->user->user_record), properties, error, &s->scope_job); @@ -698,9 +698,9 @@ int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) { log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR, "SESSION_ID=%s", s->id, - "USER_ID=%s", s->user->name, + "USER_ID=%s", s->user->user_record->user_name, "LEADER="PID_FMT, s->leader, - LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name)); + LOG_MESSAGE("New session %s of user %s.", s->id, s->user->user_record->user_name)); if (!dual_timestamp_is_set(&s->timestamp)) dual_timestamp_get(&s->timestamp); @@ -750,7 +750,7 @@ static int session_stop_scope(Session *s, bool force) { s->scope_job = mfree(s->scope_job); /* Optionally, let's kill everything that's left now. */ - if (force || manager_shall_kill(s->manager, s->user->name)) { + if (force || manager_shall_kill(s->manager, s->user->user_record->user_name)) { r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job); if (r < 0) { @@ -766,7 +766,7 @@ static int session_stop_scope(Session *s, bool force) { * Session stop is quite significant on its own, let's log it. */ log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, "SESSION_ID=%s", s->id, - "USER_ID=%s", s->user->name, + "USER_ID=%s", s->user->user_record->user_name, "LEADER="PID_FMT, s->leader, LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id)); } @@ -824,7 +824,7 @@ int session_finalize(Session *s) { log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR, "SESSION_ID=%s", s->id, - "USER_ID=%s", s->user->name, + "USER_ID=%s", s->user->user_record->user_name, "LEADER="PID_FMT, s->leader, LOG_MESSAGE("Removed session %s.", s->id)); @@ -1189,7 +1189,7 @@ static int session_prepare_vt(Session *s) { if (vt < 0) return vt; - r = fchown(vt, s->user->uid, -1); + r = fchown(vt, s->user->user_record->uid, -1); if (r < 0) { r = log_error_errno(errno, "Cannot change owner of /dev/tty%u: %m", diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index 1dc222f90e..7943a007e1 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -15,6 +15,60 @@ #include "strv.h" #include "user-util.h" +static int property_get_uid( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + User *u = userdata; + + assert(bus); + assert(reply); + assert(u); + + return sd_bus_message_append(reply, "u", (uint32_t) u->user_record->uid); +} + +static int property_get_gid( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + User *u = userdata; + + assert(bus); + assert(reply); + assert(u); + + return sd_bus_message_append(reply, "u", (uint32_t) u->user_record->gid); +} + +static int property_get_name( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + User *u = userdata; + + assert(bus); + assert(reply); + assert(u); + + return sd_bus_message_append(reply, "s", u->user_record->user_name); +} + static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", User, user_get_state, user_state_to_string); static int property_get_display( @@ -152,7 +206,7 @@ int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_er "org.freedesktop.login1.manage", NULL, false, - u->uid, + u->user_record->uid, &u->manager->polkit_registry, error); if (r < 0) @@ -181,7 +235,7 @@ int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * "org.freedesktop.login1.manage", NULL, false, - u->uid, + u->user_record->uid, &u->manager->polkit_registry, error); if (r < 0) @@ -206,9 +260,9 @@ int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * const sd_bus_vtable user_vtable[] = { SD_BUS_VTABLE_START(0), - SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(User, uid), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(User, gid), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Name", "s", NULL, offsetof(User, name), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UID", "u", property_get_uid, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("GID", "u", property_get_gid, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST), @@ -276,7 +330,7 @@ char *user_bus_path(User *u) { assert(u); - if (asprintf(&s, "/org/freedesktop/login1/user/_"UID_FMT, u->uid) < 0) + if (asprintf(&s, "/org/freedesktop/login1/user/_"UID_FMT, u->user_record->uid) < 0) return NULL; return s; @@ -345,7 +399,7 @@ int user_send_signal(User *u, bool new_user) { "/org/freedesktop/login1", "org.freedesktop.login1.Manager", new_user ? "UserNew" : "UserRemoved", - "uo", (uint32_t) u->uid, p); + "uo", (uint32_t) u->user_record->uid, p); } int user_send_changed(User *u, const char *properties, ...) { diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 1550431bea..f078f3f801 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -37,10 +37,7 @@ int user_new(User **ret, Manager *m, - uid_t uid, - gid_t gid, - const char *name, - const char *home) { + UserRecord *ur) { _cleanup_(user_freep) User *u = NULL; char lu[DECIMAL_STR_MAX(uid_t) + 1]; @@ -48,7 +45,13 @@ int user_new(User **ret, assert(ret); assert(m); - assert(name); + assert(ur); + + if (!ur->user_name) + return -EINVAL; + + if (!uid_is_valid(ur->uid)) + return -EINVAL; u = new(User, 1); if (!u) @@ -56,28 +59,17 @@ int user_new(User **ret, *u = (User) { .manager = m, - .uid = uid, - .gid = gid, + .user_record = user_record_ref(ur), .last_session_timestamp = USEC_INFINITY, }; - u->name = strdup(name); - if (!u->name) - return -ENOMEM; - - u->home = strdup(home); - if (!u->home) + if (asprintf(&u->state_file, "/run/systemd/users/" UID_FMT, ur->uid) < 0) return -ENOMEM; - path_simplify(u->home, true); - - if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0) - return -ENOMEM; - - if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0) + if (asprintf(&u->runtime_path, "/run/user/" UID_FMT, ur->uid) < 0) return -ENOMEM; - xsprintf(lu, UID_FMT, uid); + xsprintf(lu, UID_FMT, ur->uid); r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice); if (r < 0) return r; @@ -90,7 +82,7 @@ int user_new(User **ret, if (r < 0) return r; - r = hashmap_put(m->users, UID_TO_PTR(uid), u); + r = hashmap_put(m->users, UID_TO_PTR(ur->uid), u); if (r < 0) return r; @@ -129,9 +121,9 @@ User *user_free(User *u) { if (u->slice) hashmap_remove_value(u->manager->user_units, u->slice, u); - hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u); + hashmap_remove_value(u->manager->users, UID_TO_PTR(u->user_record->uid), u); - (void) sd_event_source_unref(u->timer_event_source); + sd_event_source_unref(u->timer_event_source); u->service_job = mfree(u->service_job); @@ -140,8 +132,8 @@ User *user_free(User *u) { u->slice = mfree(u->slice); u->runtime_path = mfree(u->runtime_path); u->state_file = mfree(u->state_file); - u->name = mfree(u->name); - u->home = mfree(u->home); + + user_record_unref(u->user_record); return mfree(u); } @@ -169,7 +161,7 @@ static int user_save_internal(User *u) { "NAME=%s\n" "STATE=%s\n" /* friendly user-facing state */ "STOPPING=%s\n", /* low-level state */ - u->name, + u->user_record->user_name, user_state_to_string(user_get_state(u)), yes_no(u->stopping)); @@ -376,7 +368,7 @@ int user_start(User *u) { u->stopping = false; if (!u->started) - log_debug("Starting services for new user %s.", u->name); + log_debug("Starting services for new user %s.", u->user_record->user_name); /* Save the user data so far, because pam_systemd will read the XDG_RUNTIME_DIR out of it while starting up * systemd --user. We need to do user_save_internal() because we have not "officially" started yet. */ @@ -460,7 +452,7 @@ int user_finalize(User *u) { * done. This is called as a result of an earlier user_done() when all jobs are completed. */ if (u->started) - log_debug("User %s logged out.", u->name); + log_debug("User %s logged out.", u->user_record->user_name); LIST_FOREACH(sessions_by_user, s, u->sessions) { k = session_finalize(s); @@ -474,8 +466,8 @@ int user_finalize(User *u) { * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up, * and do it only for normal users. */ - if (u->manager->remove_ipc && !uid_is_system(u->uid)) { - k = clean_ipc_by_uid(u->uid); + if (u->manager->remove_ipc && !uid_is_system(u->user_record->uid)) { + k = clean_ipc_by_uid(u->user_record->uid); if (k < 0) r = k; } @@ -531,7 +523,7 @@ int user_check_linger_file(User *u) { _cleanup_free_ char *cc = NULL; char *p = NULL; - cc = cescape(u->name); + cc = cescape(u->user_record->user_name); if (!cc) return -ENOMEM; @@ -712,7 +704,7 @@ void user_elect_display(User *u) { /* This elects a primary session for each user, which we call the "display". We try to keep the assignment * stable, but we "upgrade" to better choices. */ - log_debug("Electing new display for user %s", u->name); + log_debug("Electing new display for user %s", u->user_record->user_name); LIST_FOREACH(sessions_by_user, s, u->sessions) { if (!elect_display_filter(s)) { @@ -775,7 +767,7 @@ void user_update_last_session_timer(User *u) { char s[FORMAT_TIMESPAN_MAX]; log_debug("Last session of user '%s' logged out, terminating user context in %s.", - u->name, + u->user_record->user_name, format_timespan(s, sizeof(s), u->manager->user_stop_delay, USEC_PER_MSEC)); } } diff --git a/src/login/logind-user.h b/src/login/logind-user.h index 4bd65d8373..f8f172cb0f 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -6,6 +6,7 @@ typedef struct User User; #include "conf-parser.h" #include "list.h" #include "logind.h" +#include "user-record.h" typedef enum UserState { USER_OFFLINE, /* Not logged in at all */ @@ -20,10 +21,9 @@ typedef enum UserState { struct User { Manager *manager; - uid_t uid; - gid_t gid; - char *name; - char *home; + + UserRecord *user_record; + char *state_file; char *runtime_path; @@ -50,7 +50,7 @@ struct User { LIST_FIELDS(User, gc_queue); }; -int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name, const char *home); +int user_new(User **out, Manager *m, UserRecord *ur); User *user_free(User *u); DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free); diff --git a/src/login/logind.h b/src/login/logind.h index f0f8928ef2..7e4673d27d 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -12,6 +12,7 @@ #include "list.h" #include "set.h" #include "time-util.h" +#include "user-record.h" typedef struct Manager Manager; @@ -28,7 +29,7 @@ struct Manager { Hashmap *seats; Hashmap *sessions; Hashmap *sessions_by_leader; - Hashmap *users; + Hashmap *users; /* indexed by UID */ Hashmap *inhibitors; Hashmap *buttons; Hashmap *brightness_writers; @@ -130,7 +131,7 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **ret_ int manager_add_button(Manager *m, const char *name, Button **ret_button); int manager_add_seat(Manager *m, const char *id, Seat **ret_seat); int manager_add_session(Manager *m, const char *id, Session **ret_session); -int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, const char *home, User **ret_user); +int manager_add_user(Manager *m, UserRecord *ur, User **ret_user); int manager_add_user_by_name(Manager *m, const char *name, User **ret_user); int manager_add_user_by_uid(Manager *m, uid_t uid, User **ret_user); int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret_inhibitor); -- 2.25.1