From 568c26861b47a3f1b7138bf4cbfb37bf0d43896d Mon Sep 17 00:00:00 2001
From: Gerhard Rieger <gerhard@dest-unreach.org>
Date: Sun, 26 Nov 2023 14:08:33 +0100
Subject: [PATCH] Procan: print saved set-user-ID

---
 CHANGES      |  3 +++
 config.h.in  |  6 ++++++
 configure.ac |  2 ++
 procan.c     | 20 ++++++++++++++++++++
 4 files changed, 31 insertions(+)

diff --git a/CHANGES b/CHANGES
index 22574fe..a68fa3b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -98,6 +98,9 @@ Features:
 	POSIXMQ is now an alias for POSIXMQ-BIDIRECTIONAL. It can also be used
 	in unidirectional context.
 
+	Procan uses getresuid() and getresgid() when available, to determine
+	the saved set-user-ID.
+
 Building:
 	Disabling certain features during configure could break build process.
 
diff --git a/config.h.in b/config.h.in
index 410576b..39061f1 100644
--- a/config.h.in
+++ b/config.h.in
@@ -162,6 +162,12 @@
 /* Define if you have the clock_gettime function */
 #undef HAVE_CLOCK_GETTIME
 
+/* Define if you have the getresuid function */
+#undef HAVE_GETRESUID
+
+/* Define if you have the getresgid function */
+#undef HAVE_GETRESGID
+
 /* Define if you have the strtoll function */
 #undef HAVE_STRTOLL
 
diff --git a/configure.ac b/configure.ac
index bdc2fd0..da5d4e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1722,6 +1722,8 @@ AC_CHECK_PROTOTYPE_LIB(gettimeofday)
 
 AC_CHECK_FUNC(clock_gettime, AC_DEFINE(HAVE_CLOCK_GETTIME), AC_CHECK_LIB(rt, clock_gettime, [LIBS="-lrt $LIBS"; AC_DEFINE(HAVE_CLOCK_GETTIME)]))
 
+AC_CHECK_FUNCS(getresuid getresgid)
+
 dnl Search for flock()
 # with Linux it's in libc, with AIX in libbsd
 AC_CHECK_FUNC(flock, AC_DEFINE(HAVE_FLOCK),
diff --git a/procan.c b/procan.c
index 22dd5e4..f51751c 100644
--- a/procan.c
+++ b/procan.c
@@ -187,10 +187,30 @@ int procan(FILE *outfile) {
    fprintf(outfile, "process group id if fg process / stderr = "F_pid"\n", Tcgetpgrp(2));
 
    /* process owner, groups */
+#if HAVE_GETRESUID
+   {
+      uid_t ruid, euid, suid;
+      getresuid(&ruid, &euid, &suid);
+      fprintf(outfile, "user id  = "F_uid"\n", ruid);
+      fprintf(outfile, "effective user id  = "F_uid"\n", euid);
+      fprintf(outfile, "saved set-user id  = "F_uid"\n", suid);
+   }
+#else /* !HAVE_GETRESUID */
    fprintf(outfile, "user id  = "F_uid"\n", Getuid());
    fprintf(outfile, "effective user id  = "F_uid"\n", Geteuid());
+#endif /* !HAVE_GETRESUID */
+#if HAVE_GETRESGID
+   {
+      gid_t rgid, egid, sgid;
+      getresgid(&rgid, &egid, &sgid);
+      fprintf(outfile, "group id = "F_gid"\n", rgid);
+      fprintf(outfile, "effective group id = "F_gid"\n", egid);
+      fprintf(outfile, "saved set-group id = "F_gid"\n", sgid);
+   }
+#else /* !HAVE_GETRESGID */
    fprintf(outfile, "group id = "F_gid"\n", Getgid());
    fprintf(outfile, "effective group id = "F_gid"\n", Getegid());
+#endif /* !HAVE_GETRESGID */
 
    /* Simple process features */
    fprintf(outfile, "\n");