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

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

commit 0faa02f29f28c8b0c60a79726399fc477808864b
Author: Abhishek Mishra <[email protected]>
AuthorDate: Wed Aug 12 09:22:43 2026 +0000

    nshlib: apply #/$ prompt markers after login
    
    When NSH_PROMPT_STRING_ROOT/USER are empty, keep NSH_PROMPT_STRING at
    boot (for example, "nsh> ") so CI/NTFC boot detection still works.
    After login, su, or telnet login, replace the last '>' with '#' (euid 0)
    or '$' (non-zero euid) and ensure a trailing space.  Refresh readline
    after console/telnet login when line editing is enabled.
    
    Signed-off-by: Abhishek Mishra <[email protected]>
---
 nshlib/Kconfig           |  14 +++---
 nshlib/nsh.h             |   1 +
 nshlib/nsh_identity.c    |   2 +-
 nshlib/nsh_login.c       |   2 +-
 nshlib/nsh_prompt.c      | 128 ++++++++++++++++++++++++++++++++++++++++++++---
 nshlib/nsh_session.c     |   7 +++
 nshlib/nsh_telnetlogin.c |   2 +-
 7 files changed, 141 insertions(+), 15 deletions(-)

diff --git a/nshlib/Kconfig b/nshlib/Kconfig
index fbbb08d3b..e0259a2ac 100644
--- a/nshlib/Kconfig
+++ b/nshlib/Kconfig
@@ -74,18 +74,20 @@ config NSH_PROMPT_STRING_ROOT
        default ""
        depends on SCHED_USER_IDENTITY
        ---help---
-               If non-empty, NSH uses this prompt when the effective UID is 
zero.
-               If empty, the prompt from NSH_PROMPT_STRING (or ENV/HOSTNAME) 
is used.
-               Set explicitly for multi-user shells (for example, "nsh# ").
+               Optional full prompt override when the effective UID is zero.
+               If empty, NSH keeps NSH_PROMPT_STRING until login; after login 
the
+               last '>' in the base prompt becomes '#' (for example, "nsh> "
+               becomes "nsh# "), or '#' is appended when the prompt has no '>'.
 
 config NSH_PROMPT_STRING_USER
        string "Prompt string for non-root effective UID"
        default ""
        depends on SCHED_USER_IDENTITY
        ---help---
-               If non-empty, NSH uses this prompt when the effective UID is 
non-zero.
-               If empty, the prompt from NSH_PROMPT_STRING (or ENV/HOSTNAME) 
is used.
-               Set explicitly for multi-user shells (for example, "nsh$ ").
+               Optional full prompt override when the effective UID is 
non-zero.
+               If empty, NSH keeps NSH_PROMPT_STRING until login; after login 
the
+               last '>' in the base prompt becomes '$' (for example, "nsh> "
+               becomes "nsh$ "), or '$' is appended when the prompt has no '>'.
 
 config NSH_PROMPT_MAX
        int "Maximum Size of Prompt String"
diff --git a/nshlib/nsh.h b/nshlib/nsh.h
index a7ceb7c95..295f11b94 100644
--- a/nshlib/nsh.h
+++ b/nshlib/nsh.h
@@ -822,6 +822,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, FAR char 
*cmdline);
 
 FAR const char *nsh_prompt(void);
 void nsh_update_prompt(void);
+void nsh_update_prompt_after_login(void);
 
 /****************************************************************************
  * Name: nsh_login
diff --git a/nshlib/nsh_identity.c b/nshlib/nsh_identity.c
index 6d9e6160f..5027975c5 100644
--- a/nshlib/nsh_identity.c
+++ b/nshlib/nsh_identity.c
@@ -377,7 +377,7 @@ int cmd_su(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char 
**argv)
       return ERROR;
     }
 
-  nsh_update_prompt();
+  nsh_update_prompt_after_login();
   return OK;
 }
 #endif
diff --git a/nshlib/nsh_login.c b/nshlib/nsh_login.c
index 228a66397..860c58964 100644
--- a/nshlib/nsh_login.c
+++ b/nshlib/nsh_login.c
@@ -256,7 +256,7 @@ int nsh_login(FAR struct console_stdio_s *pstate)
                   return -1;
                 }
 
-              nsh_update_prompt();
+              nsh_update_prompt_after_login();
 #endif
               return OK;
             }
diff --git a/nshlib/nsh_prompt.c b/nshlib/nsh_prompt.c
index 04f110a83..48566eea0 100644
--- a/nshlib/nsh_prompt.c
+++ b/nshlib/nsh_prompt.c
@@ -31,6 +31,7 @@
 #include <assert.h>
 
 #ifdef CONFIG_SCHED_USER_IDENTITY
+#  include <stdbool.h>
 #  include <unistd.h>
 #endif
 
@@ -49,6 +50,70 @@
 
 static char g_nshprompt[CONFIG_NSH_PROMPT_MAX] = CONFIG_NSH_PROMPT_STRING;
 
+#ifdef CONFIG_SCHED_USER_IDENTITY
+static bool g_nsh_privilege_prompt;
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_USER_IDENTITY
+
+/****************************************************************************
+ * Name: nsh_apply_privilege_marker
+ *
+ * Description:
+ *   Replace the last '>' in the prompt with the privilege marker ('#' or
+ *   '$').  When no '>' is present, append the marker instead.
+ *
+ ****************************************************************************/
+
+static void nsh_apply_privilege_marker(FAR char *prompt, char marker)
+{
+  size_t len;
+  FAR char *p;
+
+  len = strlen(prompt);
+  for (p = prompt + len; p > prompt; p--)
+    {
+      if (*(p - 1) == '>')
+        {
+          *(p - 1) = marker;
+          return;
+        }
+    }
+
+  if (len + 1 < CONFIG_NSH_PROMPT_MAX)
+    {
+      prompt[len]     = marker;
+      prompt[len + 1] = '\0';
+    }
+}
+
+/****************************************************************************
+ * Name: nsh_ensure_trailing_space
+ *
+ * Description:
+ *   Ensure the prompt ends with a separating space before command input.
+ *
+ ****************************************************************************/
+
+static void nsh_ensure_trailing_space(FAR char *prompt)
+{
+  size_t len;
+
+  len = strlen(prompt);
+  if (len > 0 && prompt[len - 1] != ' ' &&
+      len + 1 < CONFIG_NSH_PROMPT_MAX)
+    {
+      prompt[len]     = ' ';
+      prompt[len + 1] = '\0';
+    }
+}
+
+#endif /* CONFIG_SCHED_USER_IDENTITY */
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -63,9 +128,12 @@ static char g_nshprompt[CONFIG_NSH_PROMPT_MAX] = 
CONFIG_NSH_PROMPT_STRING;
  *   - non-empty NSH_PROMPT_STRING
  *   - non-empty HOSTNAME and suffix
  *
- *   When SCHED_USER_IDENTITY is enabled and NSH_PROMPT_STRING_ROOT or
- *   NSH_PROMPT_STRING_USER are non-empty, the prompt for the current
- *   effective UID replaces the value from the sources above.
+ *   When SCHED_USER_IDENTITY is enabled, NSH_PROMPT_STRING_ROOT or
+ *   NSH_PROMPT_STRING_USER replace the prompt when non-empty.
+ *
+ *   After login (see nsh_update_prompt_after_login()), when those overrides
+ *   are empty, the last '>' in the prompt is replaced with '#' (euid 0) or
+ *   '$' (non-zero euid), or the marker is appended when no '>' is present.
  *
  * Note that suffix has higher priority when used to help clearly separate
  * prompts from command line inputs.
@@ -102,20 +170,68 @@ void nsh_update_prompt(void)
 #ifdef CONFIG_SCHED_USER_IDENTITY
   if (geteuid() == 0)
     {
+      bool applied = false;
+
+#ifdef CONFIG_NSH_PROMPT_STRING_ROOT
       if (CONFIG_NSH_PROMPT_STRING_ROOT[0] != '\0')
         {
           strlcpy(g_nshprompt, CONFIG_NSH_PROMPT_STRING_ROOT,
                   CONFIG_NSH_PROMPT_MAX);
+          applied = true;
+        }
+
+#endif
+
+      if (!applied && g_nsh_privilege_prompt)
+        {
+          nsh_apply_privilege_marker(g_nshprompt, '#');
         }
     }
-  else if (CONFIG_NSH_PROMPT_STRING_USER[0] != '\0')
+  else
     {
-      strlcpy(g_nshprompt, CONFIG_NSH_PROMPT_STRING_USER,
-              CONFIG_NSH_PROMPT_MAX);
+      bool applied = false;
+
+#ifdef CONFIG_NSH_PROMPT_STRING_USER
+      if (CONFIG_NSH_PROMPT_STRING_USER[0] != '\0')
+        {
+          strlcpy(g_nshprompt, CONFIG_NSH_PROMPT_STRING_USER,
+                  CONFIG_NSH_PROMPT_MAX);
+          applied = true;
+        }
+
+#endif
+
+      if (!applied && g_nsh_privilege_prompt)
+        {
+          nsh_apply_privilege_marker(g_nshprompt, '$');
+        }
+    }
+
+  if (g_nsh_privilege_prompt)
+    {
+      nsh_ensure_trailing_space(g_nshprompt);
     }
 #endif
 }
 
+/****************************************************************************
+ * Name: nsh_update_prompt_after_login
+ *
+ * Description:
+ *   Enable privilege markers in the prompt and refresh it.  Boot and
+ *   no-login sessions keep NSH_PROMPT_STRING (for example, "nsh> ").
+ *
+ ****************************************************************************/
+
+void nsh_update_prompt_after_login(void)
+{
+#ifdef CONFIG_SCHED_USER_IDENTITY
+  g_nsh_privilege_prompt = true;
+#endif
+
+  nsh_update_prompt();
+}
+
 /****************************************************************************
  * Name: nsh_prompt
  *
diff --git a/nshlib/nsh_session.c b/nshlib/nsh_session.c
index acacb0f54..cf71a7419 100644
--- a/nshlib/nsh_session.c
+++ b/nshlib/nsh_session.c
@@ -103,6 +103,13 @@ int nsh_session(FAR struct console_stdio_s *pstate,
     }
 #endif /* CONFIG_NSH_TELNET_LOGIN */
 
+#ifdef CONFIG_SCHED_USER_IDENTITY
+  if (login != NSH_LOGIN_NONE)
+    {
+      nsh_update_prompt_after_login();
+    }
+#endif
+
   if (login != NSH_LOGIN_NONE)
     {
       /* Present a greeting and possibly a Message of the Day (MOTD) */
diff --git a/nshlib/nsh_telnetlogin.c b/nshlib/nsh_telnetlogin.c
index 8007b2684..7e80ff5e7 100644
--- a/nshlib/nsh_telnetlogin.c
+++ b/nshlib/nsh_telnetlogin.c
@@ -261,7 +261,7 @@ int nsh_telnetlogin(FAR struct console_stdio_s *pstate)
                   return -1;
                 }
 
-              nsh_update_prompt();
+              nsh_update_prompt_after_login();
 #endif
               return OK;
             }

Reply via email to