diff --git a/man/sd_uid_get_state.xml b/man/sd_uid_get_state.xml
index 087a2d539d..e6cf77ff69 100644
--- a/man/sd_uid_get_state.xml
+++ b/man/sd_uid_get_state.xml
@@ -22,6 +22,7 @@
sd_uid_get_sessions
sd_uid_get_seats
sd_uid_get_display
+ sd_uid_get_login_time
Determine login state of a specific Unix user ID
@@ -62,6 +63,12 @@
char **session
+
+
+ int sd_uid_get_login_time
+ uid_t uid
+ uint64_t *usec
+
@@ -126,16 +133,27 @@
of the "primary" session of a user. If the user has graphical
sessions, it will be the oldest graphical session. Otherwise, it
will be the oldest open session.
+
+ sd_uid_get_login_time() may be used to
+ determine the time the user's service manager has been invoked,
+ which is the time when the user's first active session, since which
+ they stayed logged in continuously, began. The usec
+ is in microseconds since the epoch (CLOCK_REALTIME).
+ This call will fail with -ENXIO if the user is not
+ currently logged in.
Return Value
- On success, sd_uid_get_state() returns 0 or a positive integer. If the test
- succeeds, sd_uid_is_on_seat() returns a positive integer; if it fails, 0.
- sd_uid_get_sessions() and sd_uid_get_seats() return the number
- of entries in the returned arrays. sd_uid_get_display() returns a non-negative code
- on success. On failure, these calls return a negative errno-style error code.
+ On success, sd_uid_get_state() and
+ sd_uid_get_login_time() returns 0 or a positive
+ integer. If the test succeeds, sd_uid_is_on_seat()
+ returns a positive integer; if it fails, 0. sd_uid_get_sessions()
+ and sd_uid_get_seats() return the number of entries
+ in the returned arrays. sd_uid_get_display()
+ returns a non-negative code on success. On failure, these calls return
+ a negative errno-style error code.
Errors
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 8b5edabb75..b54417f3d1 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -817,4 +817,5 @@ LIBSYSTEMD_254 {
global:
sd_session_get_username;
sd_session_get_start_time;
+ sd_uid_get_login_time;
} LIBSYSTEMD_253;
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index 12cb4e6792..a81b21062a 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -503,6 +503,36 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
return 0;
}
+_public_ int sd_uid_get_login_time(uid_t uid, uint64_t *usec) {
+ _cleanup_free_ char *p = NULL, *s = NULL, *rt = NULL;
+ usec_t t;
+ int r;
+
+ assert_return(usec, -EINVAL);
+
+ r = file_of_uid(uid, &p);
+ if (r < 0)
+ return r;
+
+ r = parse_env_file(NULL, p, "STATE", &s, "REALTIME", &rt);
+ if (r == -ENOENT)
+ return -ENXIO;
+ if (r < 0)
+ return r;
+ if (isempty(s) || isempty(rt))
+ return -EIO;
+
+ if (!STR_IN_SET(s, "active", "online"))
+ return -ENXIO;
+
+ r = safe_atou64(rt, &t);
+ if (r < 0)
+ return r;
+
+ *usec = t;
+ return 0;
+}
+
static int file_of_seat(const char *seat, char **_p) {
char *p;
int r;
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
index 526af34d37..7246d9f472 100644
--- a/src/systemd/sd-login.h
+++ b/src/systemd/sd-login.h
@@ -130,6 +130,9 @@ int sd_uid_get_state(uid_t uid, char **state);
/* Return primary session of user, if there is any */
int sd_uid_get_display(uid_t uid, char **session);
+/* Determine the login time of user */
+int sd_uid_get_login_time(uid_t uid, uint64_t *usec);
+
/* Return 1 if UID has session on seat. If require_active is true, this will
* look for active sessions only. */
int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat);