aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2026-01-27 11:05:11 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2026-01-27 11:17:38 +0100
commit97a78139719deeb2dae02fda6299f174809320fb (patch)
treeb1be5983f13c42e59314daaf581131fb230898fb
parente4f4bf95ac446e72f2c04770552cb2bc8590cfdd (diff)
downloadbusybox-w32-97a78139719deeb2dae02fda6299f174809320fb.tar.gz
busybox-w32-97a78139719deeb2dae02fda6299f174809320fb.tar.bz2
busybox-w32-97a78139719deeb2dae02fda6299f174809320fb.zip
ash: move applet handling out of tryexec() - making it similar to dash
function old new delta tryexec - 60 +60 shellexec 476 349 -127 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 60/-127) Total: -67 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c123
1 files changed, 61 insertions, 62 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 97ad95a28..7cfd1bc42 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8476,67 +8476,71 @@ static struct tblentry **cmdtable;
8476static int builtinloc = -1; /* index in path of %builtin, or -1 */ 8476static int builtinloc = -1; /* index in path of %builtin, or -1 */
8477 8477
8478 8478
8479static void
8480tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8481{
8482#if ENABLE_FEATURE_SH_STANDALONE 8479#if ENABLE_FEATURE_SH_STANDALONE
8483 if (applet_no >= 0) { 8480static void
8484 if (!vforked && APPLET_IS_NOEXEC(applet_no)) { 8481tryexec_applet(int applet_no, const char *cmd, char **argv, char **envp)
8485 dbg_show_dirtymem("dirtymem in NOEXEC tryexec"); 8482{
8486 clearenv(); 8483 if (!vforked && APPLET_IS_NOEXEC(applet_no)) {
8487 while (*envp) 8484 dbg_show_dirtymem("dirtymem in NOEXEC tryexec");
8488 putenv(*envp++); 8485 clearenv();
8489 popredir(/*drop:*/ 1); 8486 while (*envp)
8487 putenv(*envp++);
8488 popredir(/*drop:*/ 1);
8490//FIXME: exec resets all non-DFL, non-IGN signal handlers to DFL, 8489//FIXME: exec resets all non-DFL, non-IGN signal handlers to DFL,
8491//but we _don't_ exec, such signals will reach ash's handler instead! 8490//but we _don't_ exec, such signals will reach ash's handler instead!
8492//Maybe add code there to set the handler to DFL, and signal itself? 8491//Maybe add code there to set the handler to DFL, and signal itself?
8493// This works for "CMD [| CMD]..." pipes: 8492// This works for "CMD [| CMD]..." pipes:
8494//vforkexec() 8493//vforkexec():
8495// vfork(); 8494// vfork();
8496// forkchild(jp, n, FORK_FG); // this resets TSTP,TTOU,INT,TERM,QUIT to DFL 8495// forkchild(jp, n, FORK_FG); // this resets TSTP,TTOU,INT,TERM,QUIT to DFL
8497// shellexec(argv[0], argv, path, idx) 8496// shellexec(argv[0], argv, path, idx)
8498// tryexec() 8497// tryexec_applet()
8499// we are here 8498// we are here
8500// And for "exec CMD": 8499// And for "exec CMD":
8501//execcmd() 8500//execcmd():
8502// iflag = 0; 8501// iflag = 0;
8503// mflag = 0; 8502// mflag = 0;
8504// optschanged(); // this resets TSTP,TTOU,INT,TERM to DFL 8503// optschanged(); // this resets TSTP,TTOU,INT,TERM to DFL
8505// shlvl++; 8504// shlvl++;
8506// setsignal(SIGQUIT); // this resets QUIT to DFL 8505// setsignal(SIGQUIT); // this resets QUIT to DFL
8507// shellexec() 8506// shellexec() ->
8508// tryexec() 8507// tryexec_applet() ->
8509// we are here 8508// we are here
8510// But ash -c 'LAST_CMD_DOESNT_FORK' does not work! 8509// But ash -c 'LAST_CMD_WONT_FORK' does not work!
8511//evalcommand() 8510//evalcommand():
8512// if (!(flags & EV_EXIT) || may_have_traps) 8511// if (!(flags & EV_EXIT) || may_have_traps)
8513// // we don't use this branch 8512// // we don't use this branch
8514// //else: 8513// //else:
8515// shellexec() 8514// shellexec() ->
8516// tryexec() 8515// tryexec_applet() ->
8517// we are here 8516// we are here
8518//SIGINT works 'by accident' (sets DFL+signals itself) 8517//SIGINT works 'by accident' (sets DFL+signals itself)
8519//SIGQUIT is IGNORED! 8518//SIGQUIT is IGNORED!
8520//Fixed by adding in the evalcommand() before the shown shellexec(): 8519//Fixed by adding in the evalcommand() before that shellexec():
8521// shlvl++; 8520// shlvl++;
8522// setsignal(SIGQUIT); 8521// setsignal(SIGQUIT);
8523// //TODO: setsignal(TSTP,TTOU,INT,TERM) too? 8522// //TODO: setsignal(TSTP,TTOU,INT,TERM) too?
8524// 8523//
8525// With traps set, this: 8524// With traps set, this:
8526// ash -c 'trap "echo HERE!" INT; exec xargs' 8525// ash -c 'trap "echo HERE!" INT; exec xargs'
8527// didn't work: ^C sets a "run trap later" flag and _returns_, 8526// didn't work: ^C sets a "run trap later" flag and _returns_,
8528// which is not expected by the NOFORK'ed xargs! 8527// which is not expected by the NOEXEC'ed xargs applet! (It gets EINTR on read).
8529// clear_traps() helps with this: 8528// clear_traps() helps with this:
8530 clear_traps(); 8529 clear_traps();
8531 run_noexec_applet_and_exit(applet_no, cmd, argv); 8530 run_noexec_applet_and_exit(applet_no, cmd, argv);
8532 } 8531 /* does not return */
8533 /* re-exec ourselves with the new arguments */
8534 execve(bb_busybox_exec_path, argv, envp);
8535 /* If they called chroot or otherwise made the binary no longer
8536 * executable, fall through */
8537 } 8532 }
8533 /* re-exec ourselves with the new arguments */
8534 execve(bb_busybox_exec_path, argv, envp);
8535 /* If they called chroot or otherwise made the binary
8536 * no longer executable, return.
8537 */
8538}
8538#endif 8539#endif
8539 8540
8541static void
8542tryexec(const char *cmd, char **argv, char **envp)
8543{
8540 repeat: 8544 repeat:
8541#ifdef SYSV 8545#ifdef SYSV
8542 do { 8546 do {
@@ -8545,7 +8549,6 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c
8545#else 8549#else
8546 execve(cmd, argv, envp); 8550 execve(cmd, argv, envp);
8547#endif 8551#endif
8548
8549 if (cmd != bb_busybox_exec_path && errno == ENOEXEC) { 8552 if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8550 /* Run "cmd" as a shell script: 8553 /* Run "cmd" as a shell script:
8551 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html 8554 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
@@ -8585,30 +8588,25 @@ static void shellexec(char *prog, char **argv, const char *path, int idx)
8585 int e; 8588 int e;
8586 char **envp; 8589 char **envp;
8587 int exerrno; 8590 int exerrno;
8588 int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8589 8591
8590 envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL); 8592 envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8591 if (strchr(prog, '/') != NULL 8593 if (strchr(prog, '/') != NULL) {
8592#if ENABLE_FEATURE_SH_STANDALONE 8594 tryexec(prog, argv, envp);
8593 || (applet_no = find_applet_by_name(prog)) >= 0
8594#endif
8595 ) {
8596 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8597 if (applet_no >= 0) {
8598 /* We tried execing ourself, but it didn't work.
8599 * Maybe /proc/self/exe doesn't exist?
8600 * Try $PATH search.
8601 */
8602 goto try_PATH;
8603 }
8604 e = errno; 8595 e = errno;
8605 } else { 8596 } else {
8606 try_PATH: 8597#if ENABLE_FEATURE_SH_STANDALONE
8598 int applet_no = find_applet_by_name(prog);
8599 if (applet_no >= 0)
8600 tryexec_applet(applet_no, prog, argv, envp);
8601 /* We tried execing ourself, but it didn't work.
8602 * Maybe /proc/self/exe doesn't exist?
8603 */
8604#endif
8607 e = ENOENT; 8605 e = ENOENT;
8608 while (padvance(&path, argv[0]) >= 0) { 8606 while (padvance(&path, argv[0]) >= 0) {
8609 cmdname = stackblock(); 8607 cmdname = stackblock();
8610 if (--idx < 0 && pathopt == NULL) { 8608 if (--idx < 0 && pathopt == NULL) {
8611 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); 8609 tryexec(cmdname, argv, envp);
8612 if (errno != ENOENT && errno != ENOTDIR) 8610 if (errno != ENOENT && errno != ENOTDIR)
8613 e = errno; 8611 e = errno;
8614 } 8612 }
@@ -10869,6 +10867,7 @@ evalcommand(union node *cmd, int flags)
10869 /* Testcase: ash -c 'ONE_CMD' will use EV_EXIT for ONE_CMD */ 10867 /* Testcase: ash -c 'ONE_CMD' will use EV_EXIT for ONE_CMD */
10870 shlvl++; /* dash does not need it because it doesn't ignore SIGQUIT */ 10868 shlvl++; /* dash does not need it because it doesn't ignore SIGQUIT */
10871 setsignal(SIGQUIT); /* we do (bash compat) */ 10869 setsignal(SIGQUIT); /* we do (bash compat) */
10870 //TODO: setsignal(TSTP,TTOU,INT,TERM) too?
10872 shellexec(argv[0], argv, path, cmdentry.u.index); 10871 shellexec(argv[0], argv, path, cmdentry.u.index);
10873 /* NOTREACHED */ 10872 /* NOTREACHED */
10874 } /* default */ 10873 } /* default */