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 a0618315735c3a470d2a9f283b85c85d10f990c6 Author: Marco Casaroli <[email protected]> AuthorDate: Sun Oct 18 16:34:35 2026 +0200 nshlib: Keep the exit status of the last command. NSH kept only whether the last command failed. nsh_builtin() and nsh_fileapp() returned 1 for any non-zero exit status, $? expanded to 0 or 1, and "sh -c command" exited with the result of nsh_parse(): 0 or 255 (-1), never the exit status of the command. Keep the exit status in np_status. nsh_builtin() and nsh_fileapp() return the exit status of the application, $? expands to it, and "sh -c" exits with it, as POSIX requires. A command line that cannot be run still gives EXIT_FAILURE. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- nshlib/nsh.h | 3 ++- nshlib/nsh_builtin.c | 18 +++++----------- nshlib/nsh_fileapps.c | 23 ++++++++------------- nshlib/nsh_parse.c | 57 ++++++++++++++++++++++----------------------------- nshlib/nsh_session.c | 12 ++++++++++- 5 files changed, 51 insertions(+), 62 deletions(-) diff --git a/nshlib/nsh.h b/nshlib/nsh.h index 9ac148b94..3ca066867 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -652,10 +652,11 @@ struct nsh_parser_s bool np_redir_out; /* true: Output from the last command was re-directed */ bool np_redir_in; /* true: Input from the last command was re-directed */ bool np_redir_err; /* true: Error from the last command was re-directed */ - bool np_fail; /* true: The last command failed */ + int np_status; /* Exit status of the last command */ pid_t np_lastpid; /* Pid of the last command executed */ #ifdef NSH_HAVE_VARS char np_pids[32]; /* String representation of the last pid */ + char np_rcstr[4]; /* String representation of the exit status */ #endif #ifndef CONFIG_NSH_DISABLESCRIPT diff --git a/nshlib/nsh_builtin.c b/nshlib/nsh_builtin.c index 52085b571..6d1203057 100644 --- a/nshlib/nsh_builtin.c +++ b/nshlib/nsh_builtin.c @@ -64,9 +64,9 @@ * and successfully started. If CONFIG_SCHED_WAITPID is * defined, this return value also indicates that the * application returned successful status (EXIT_SUCCESS) - * 1 If CONFIG_SCHED_WAITPID is defined, then this return value - * indicates that the application task was spawned successfully - * but returned failure exit status. + * >0 If CONFIG_SCHED_WAITPID is defined, the application task + * was spawned successfully and returned this non-zero exit + * status. * ****************************************************************************/ @@ -200,17 +200,9 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, else { - /* We can't return the exact status (nsh has nowhere to put it) - * so just pass back zero/nonzero in a fashion that doesn't - * look like an error. - */ - - ret = (rc == 0) ? OK : 1; + /* Return the exit status of the application */ - /* TODO: Set the environment variable '?' to a string - * corresponding to WEXITSTATUS(rc) so that $? will expand to - * the exit status of the most recently executed task. - */ + ret = WIFEXITED(rc) ? WEXITSTATUS(rc) : 1; } if (vtbl->isctty && tc == 0) diff --git a/nshlib/nsh_fileapps.c b/nshlib/nsh_fileapps.c index 796b167cd..25a9c27c2 100644 --- a/nshlib/nsh_fileapps.c +++ b/nshlib/nsh_fileapps.c @@ -65,9 +65,9 @@ * and successfully started. If CONFIG_SCHED_WAITPID is * defined, this return value also indicates that the * application returned successful status (EXIT_SUCCESS) - * 1 If CONFIG_SCHED_WAITPID is defined, then this return value - * indicates that the application task was spawned successfully - * but returned failure exit status. + * >0 If CONFIG_SCHED_WAITPID is defined, the application task + * was spawned successfully and returned this non-zero exit + * status. * ****************************************************************************/ @@ -341,14 +341,10 @@ int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, else { - /* Ignore the returned child pid */ + /* Keep the exit status of the application */ ret = OK; - - /* TODO: Set the environment variable '?' to a string - * corresponding to WEXITSTATUS(rc) so that $? will expand - * to the exit status of the most recently executed task. - */ + rc = WIFEXITED(rc) ? WEXITSTATUS(rc) : 1; } if (vtbl->isctty && tc == 0) @@ -418,14 +414,11 @@ errout: ret = ERROR; } - else if (rc != 0) + else { - /* We can't return the exact status (nsh has nowhere to put it) - * so just pass back zero/nonzero in a fashion that doesn't look - * like an error. - */ + /* Return the exit status of the application */ - ret = 1; + ret = rc; } return ret; diff --git a/nshlib/nsh_parse.c b/nshlib/nsh_parse.c index 7cba9cc40..51811c667 100644 --- a/nshlib/nsh_parse.c +++ b/nshlib/nsh_parse.c @@ -163,7 +163,7 @@ static void nsh_alist_free(FAR struct nsh_vtbl_s *vtbl, FAR struct nsh_alist_s *alist); #endif -static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result); +static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, int status); static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char *argv[], FAR const struct nsh_param_s *param); @@ -278,8 +278,6 @@ static const size_t g_pipeline1_len = sizeof(g_pipeline1) - 1; #ifdef NSH_HAVE_VARS static const char g_exitstatus[] = "?"; static const char g_lastpid[] = "!"; -static const char g_success[] = "0"; -static const char g_failure[] = "1"; #endif #ifdef NEED_NULLSTRING static const char g_nullstring[] = ""; @@ -445,9 +443,10 @@ static void nsh_alist_free(FAR struct nsh_vtbl_s *vtbl, * Name: nsh_saveresult ****************************************************************************/ -static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result) +static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, int status) { struct nsh_parser_s *np = &vtbl->np; + bool result = status != 0; #ifndef CONFIG_NSH_DISABLESCRIPT #ifndef CONFIG_NSH_DISABLE_LOOPS @@ -462,7 +461,7 @@ static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result) if (np->np_lpstate[np->np_lpndx].lp_state == NSH_LOOP_WHILE) { - np->np_fail = false; + np->np_status = 0; np->np_lpstate[np->np_lpndx].lp_enable = (result == OK); return OK; } @@ -478,7 +477,7 @@ static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result) else if (np->np_lpstate[np->np_lpndx].lp_state == NSH_LOOP_UNTIL) { - np->np_fail = false; + np->np_status = 0; np->np_lpstate[np->np_lpndx].lp_enable = (result != OK); return OK; } @@ -490,7 +489,7 @@ static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result) if (np->np_iestate[np->np_iendx].ie_state == NSH_ITEF_IF) { - np->np_fail = false; + np->np_status = 0; np->np_iestate[np->np_iendx].ie_ifcond = np->np_iestate[np->np_iendx].ie_inverted ^ result; return OK; @@ -499,7 +498,7 @@ static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result) #endif #endif { - np->np_fail = result; + np->np_status = status; return result ? ERROR : OK; } } @@ -544,9 +543,9 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, * and successfully started. If CONFIG_SCHED_WAITPID is * defined, this return value also indicates that the * application returned successful status (EXIT_SUCCESS) - * 1 If CONFIG_SCHED_WAITPID is defined, then this return value - * indicates that the application task was spawned - * successfully but returned failure exit status. + * >0 If CONFIG_SCHED_WAITPID is defined, the application + * task was spawned successfully and returned this non-zero + * exit status. * * Note the priority is not effected by nice-ness. */ @@ -555,14 +554,14 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, ret = nsh_builtin(vtbl, argv[0], argv, param); if (ret >= 0) { - /* nsh_builtin() returned 0 or 1. This means that the built-in - * command was successfully started (although it may not have ran - * successfully). So certainly it is not an NSH command. + /* nsh_builtin() returned 0 or an exit status. This means that the + * built-in command was successfully started (although it may not + * have ran successfully). So certainly it is not an NSH command. */ - /* Save the result: success if 0; failure if 1 */ + /* Save the exit status: success if 0 */ - return nsh_saveresult(vtbl, ret != OK); + return nsh_saveresult(vtbl, ret); } /* No, not a built in command (or, at least, we were unable to start a @@ -581,9 +580,9 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, * and successfully started. If CONFIG_SCHED_WAITPID is * defined, this return value also indicates that the * application returned successful status (EXIT_SUCCESS) - * 1 If CONFIG_SCHED_WAITPID is defined, then this return value - * indicates that the application task was spawned - * successfully but returned failure exit status. + * >0 If CONFIG_SCHED_WAITPID is defined, the application + * task was spawned successfully and returned this non-zero + * exit status. * * Note the priority is not effected by nice-ness. */ @@ -592,14 +591,14 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, ret = nsh_fileapp(vtbl, argv[0], argv, param); if (ret >= 0) { - /* nsh_fileapp() returned 0 or 1. This means that the built-in - * command was successfully started (although it may not have ran - * successfully). So certainly it is not an NSH command. + /* nsh_fileapp() returned 0 or an exit status. This means that the + * built-in command was successfully started (although it may not + * have ran successfully). So certainly it is not an NSH command. */ - /* Save the result: success if 0; failure if 1 */ + /* Save the exit status: success if 0 */ - return nsh_saveresult(vtbl, ret != OK); + return nsh_saveresult(vtbl, ret); } /* No, not a file name command (or, at least, we were unable to start a @@ -1141,14 +1140,8 @@ static FAR char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, if (strcmp(varname, g_exitstatus) == 0) { - if (vtbl->np.np_fail) - { - return (FAR char *)g_failure; - } - else - { - return (FAR char *)g_success; - } + itoa(vtbl->np.np_status, vtbl->np.np_rcstr, 10); + return vtbl->np.np_rcstr; } else if (strcmp(varname, g_lastpid) == 0) { diff --git a/nshlib/nsh_session.c b/nshlib/nsh_session.c index 8d9d7a9f4..46ac1d1cf 100644 --- a/nshlib/nsh_session.c +++ b/nshlib/nsh_session.c @@ -158,7 +158,17 @@ int nsh_session(FAR struct console_stdio_s *pstate, if (argc > 2) { - return nsh_parse(vtbl, argv[2]); + /* Return the exit status of the last command, or a failure + * if the command line could not be run. + */ + + ret = nsh_parse(vtbl, argv[2]); + if (vtbl->np.np_status != 0) + { + return vtbl->np.np_status; + } + + return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } else {
