This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 92c3b6446d6cb8c99002cc3d376e040f9cb93fde
Author: Abhishek Mishra <[email protected]>
AuthorDate: Thu Jul 16 18:55:50 2026 +0000

    nsh: show real, effective, and saved IDs in id command
    
    Use getresuid() and getresgid() for Linux-style id output with name
    resolution and a groups= list based on the effective GID.
    
    Signed-off-by: Abhishek Mishra <[email protected]>
---
 nshlib/nsh_identity.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 207 insertions(+), 6 deletions(-)

diff --git a/nshlib/nsh_identity.c b/nshlib/nsh_identity.c
index 7bcb9a4a0..6d9e6160f 100644
--- a/nshlib/nsh_identity.c
+++ b/nshlib/nsh_identity.c
@@ -27,6 +27,7 @@
 #include <nuttx/config.h>
 
 #include <errno.h>
+#include <grp.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdbool.h>
@@ -381,28 +382,228 @@ int cmd_su(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+#ifndef CONFIG_NSH_DISABLE_ID
+
+/****************************************************************************
+ * Name: nsh_id_format_uid
+ *
+ * Description:
+ *   Format a UID token in Linux id(1) style, e.g. "uid=0(root)".
+ *
+ ****************************************************************************/
+
+static void nsh_id_format_uid(FAR char *buf, size_t buflen,
+                              FAR const char *tag, uid_t uid)
+{
+#ifdef CONFIG_LIBC_PASSWD_FILE
+  FAR struct passwd *pwd = getpwuid(uid);
+
+  if (pwd != NULL && pwd->pw_name != NULL)
+    {
+      snprintf(buf, buflen, "%s=%d(%s)", tag, uid, pwd->pw_name);
+      return;
+    }
+#endif
+
+  if (uid == 0)
+    {
+      snprintf(buf, buflen, "%s=%d(root)", tag, uid);
+    }
+  else
+    {
+      snprintf(buf, buflen, "%s=%d", tag, uid);
+    }
+}
+
+/****************************************************************************
+ * Name: nsh_id_format_gid
+ *
+ * Description:
+ *   Format a GID token in Linux id(1) style, e.g. "gid=0(root)".
+ *
+ ****************************************************************************/
+
+static void nsh_id_format_gid(FAR char *buf, size_t buflen,
+                              FAR const char *tag, gid_t gid)
+{
+#ifdef CONFIG_LIBC_GROUP_FILE
+  FAR struct group *grp = getgrgid(gid);
+
+  if (grp != NULL && grp->gr_name != NULL)
+    {
+      snprintf(buf, buflen, "%s=%d(%s)", tag, gid, grp->gr_name);
+      return;
+    }
+#endif
+
+  if (gid == 0)
+    {
+      snprintf(buf, buflen, "%s=%d(root)", tag, gid);
+    }
+  else
+    {
+      snprintf(buf, buflen, "%s=%d", tag, gid);
+    }
+}
+
+static void nsh_id_append(FAR char *line, size_t linelen,
+                          FAR const char *token)
+{
+  size_t len = strlen(line);
+
+  if (len > 0)
+    {
+      strlcat(line, " ", linelen);
+    }
+
+  strlcat(line, token, linelen);
+}
+
+#ifdef CONFIG_LIBC_PASSWD_FILE
+/****************************************************************************
+ * Name: nsh_id_format_group_value
+ *
+ * Description:
+ *   Format a bare group value for a groups= list, e.g. "0(root)".
+ *
+ ****************************************************************************/
+
+static void nsh_id_format_group_value(FAR char *buf, size_t buflen,
+                                      gid_t gid)
+{
+#ifdef CONFIG_LIBC_GROUP_FILE
+  FAR struct group *grp = getgrgid(gid);
+
+  if (grp != NULL && grp->gr_name != NULL)
+    {
+      snprintf(buf, buflen, "%d(%s)", gid, grp->gr_name);
+      return;
+    }
+#endif
+
+  if (gid == 0)
+    {
+      snprintf(buf, buflen, "0(root)");
+    }
+  else
+    {
+      snprintf(buf, buflen, "%d", gid);
+    }
+}
+
+/****************************************************************************
+ * Name: nsh_id_append_groups
+ *
+ * Description:
+ *   Append a Linux-style groups= list to the id output line.
+ *
+ ****************************************************************************/
+
+static void nsh_id_append_groups(FAR char *line, size_t linelen)
+{
+  gid_t grouplist[8];
+  char token[48];
+  int ngroups;
+  int i;
+
+  ngroups = getgroups(sizeof(grouplist) / sizeof(grouplist[0]), grouplist);
+  if (ngroups <= 0)
+    {
+      return;
+    }
+
+  strlcat(line, " groups=", linelen);
+
+  for (i = 0; i < ngroups; i++)
+    {
+      if (i > 0)
+        {
+          strlcat(line, ",", linelen);
+        }
+
+      nsh_id_format_group_value(token, sizeof(token), grouplist[i]);
+      strlcat(line, token, linelen);
+    }
+}
+#endif /* CONFIG_LIBC_PASSWD_FILE */
+
 /****************************************************************************
  * Name: cmd_id
  *
  * Description:
- *   Print real and effective UID/GID for the current session.
+ *   Print real, effective, and saved-set UID/GID for the current session in
+ *   Linux id(1) style with optional user and group names.
  *
  ****************************************************************************/
 
-#ifndef CONFIG_NSH_DISABLE_ID
 int cmd_id(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
 {
+  uid_t ruid;
+  uid_t euid;
+  uid_t suid;
+  gid_t rgid;
+  gid_t egid;
+  gid_t sgid;
+  char line[256];
+  char token[48];
+
   if (argc != 1)
     {
       nsh_error(vtbl, g_fmtarginvalid, argv[0]);
       return ERROR;
     }
 
-  nsh_output(vtbl, "uid=%d euid=%d gid=%d egid=%d\n",
-             getuid(), geteuid(), getgid(), getegid());
+  if (getresuid(&ruid, &euid, &suid) != 0)
+    {
+      nsh_error(vtbl, "id: getresuid() failed: %d\n", errno);
+      return ERROR;
+    }
+
+  if (getresgid(&rgid, &egid, &sgid) != 0)
+    {
+      nsh_error(vtbl, "id: getresgid() failed: %d\n", errno);
+      return ERROR;
+    }
+
+  line[0] = '\0';
+
+  nsh_id_format_uid(token, sizeof(token), "uid", ruid);
+  nsh_id_append(line, sizeof(line), token);
+
+  if (euid != ruid)
+    {
+      nsh_id_format_uid(token, sizeof(token), "euid", euid);
+      nsh_id_append(line, sizeof(line), token);
+    }
+
+  if (suid != ruid && suid != euid)
+    {
+      nsh_id_format_uid(token, sizeof(token), "suid", suid);
+      nsh_id_append(line, sizeof(line), token);
+    }
+
+  nsh_id_format_gid(token, sizeof(token), "gid", rgid);
+  nsh_id_append(line, sizeof(line), token);
+
+  if (egid != rgid)
+    {
+      nsh_id_format_gid(token, sizeof(token), "egid", egid);
+      nsh_id_append(line, sizeof(line), token);
+    }
+
+  if (sgid != rgid && sgid != egid)
+    {
+      nsh_id_format_gid(token, sizeof(token), "sgid", sgid);
+      nsh_id_append(line, sizeof(line), token);
+    }
+
+#ifdef CONFIG_LIBC_PASSWD_FILE
+  nsh_id_append_groups(line, sizeof(line));
+#endif
+  nsh_output(vtbl, "%s\n", line);
   return OK;
 }
-#endif
+#endif /* CONFIG_NSH_DISABLE_ID */
 
 /****************************************************************************
  * Name: cmd_whoami
@@ -442,7 +643,7 @@ int cmd_whoami(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
     }
   else
     {
-      nsh_output(vtbl, "%d\n", (int)euid);
+      nsh_output(vtbl, "%d\n", euid);
     }
 
   return OK;

Reply via email to