[PATCH] add exec -a support (preliminary)

Patrick Pief p.pief at zoho.com
Fri Jan 27 22:54:37 UTC 2017


Hey,

> And, don't duplicate another function if what you did is only extending a
> functionality of that function. BusyBox is coded with size in mind.

I know, and I am reminded of it whenever I look at Busybox's source code.
:)

I thought that this way it might be easier to comment out, but looking at
how my changes aren't all that drastic it was really unnessary. The #if block
could be put around the new lines in execcmd().

> Besides, if you code within shellexec() we
> can see a better diff on what you have extended.

Makes sense, so here is my updated patch.

Some explanation:

* "zeroarg" is the new target argv[0] the target program will see.
* "realcmd" is the original argv[0], the command string which determines what
  gets really called, it's also what identifies the shellexec call in the trace.

I am always open for suggestions on better parameter/variable names.

-Patrick


---
 shell/ash.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index d8f4132..7abca3d 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7706,23 +7706,25 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **
  * have to change the find_command routine as well.
  * argv[-1] must exist and be writable! See tryexec() for why.
  */
-static void shellexec(char **, const char *, int) NORETURN;
+static void shellexec(char **, char *, const char *, int) NORETURN;
 static void
-shellexec(char **argv, const char *path, int idx)
+shellexec(char **argv, char *zeroarg, const char *path, int idx)
 {
        char *cmdname;
+       char *realcmd = argv[0];
        int e;
        char **envp;
        int exerrno;
        int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */

+       argv[0] = zeroarg;
        envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
-       if (strchr(argv[0], '/') != NULL
+       if (strchr(realcmd, '/') != NULL
 #if ENABLE_FEATURE_SH_STANDALONE
-        || (applet_no = find_applet_by_name(argv[0])) >= 0
+        || (applet_no = find_applet_by_name(realcmd)) >= 0
 #endif
        ) {
-               tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
+               tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) realcmd, argv, envp);
                if (applet_no >= 0) {
                        /* We tried execing ourself, but it didn't work.
                         * Maybe /proc/self/exe doesn't exist?
@@ -7734,7 +7736,7 @@ shellexec(char **argv, const char *path, int idx)
        } else {
  try_PATH:
                e = ENOENT;
-               while ((cmdname = path_advance(&path, argv[0])) != NULL) {
+               while ((cmdname = path_advance(&path, realcmd)) != NULL) {
                        if (--idx < 0 && pathopt == NULL) {
                                tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
                                if (errno != ENOENT && errno != ENOTDIR)
@@ -7758,7 +7760,7 @@ shellexec(char **argv, const char *path, int idx)
        }
        exitstatus = exerrno;
        TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
-               argv[0], e, suppress_int));
+               realcmd, e, suppress_int));
        ash_msg_and_raise(EXEXIT, "%s: %s", argv[0], errmsg(e, "not found"));
        /* NOTREACHED */
 }
@@ -9333,7 +9335,11 @@ execcmd(int argc UNUSED_PARAM, char **argv)
                /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
                /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */

-               shellexec(argv + 1, pathval(), 0);
+               if (strcmp(argv[1], "-a") == 0 && argv[2]) {
+                       shellexec(argv + 3, argv[2], pathval(), 0);
+               } else {
+                       shellexec(argv + 1, argv[1], pathval(), 0);
+               }
                /* NOTREACHED */
        }
        return 0;
@@ -9735,7 +9741,7 @@ evalcommand(union node *cmd, int flags)
                        /* fall through to exec'ing external program */
                }
                listsetvar(varlist.list, VEXPORT|VSTACK);
-               shellexec(argv, path, cmdentry.u.index);
+               shellexec(argv, argv[0], path, cmdentry.u.index);
                /* NOTREACHED */
        } /* default */
        case CMDBUILTIN:
--
2.11.0





More information about the busybox mailing list