ash: cleanup part 7
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 23 Feb 2007 01:05:26 +0000 (01:05 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 23 Feb 2007 01:05:26 +0000 (01:05 -0000)
shell/ash.c

index 69b8ab0b9467818dcdd26530266c0d51e50a0cfa..e061211a0701e7d0ef95a68f2eb5dc9ec670964e 100644 (file)
@@ -932,7 +932,6 @@ static int startlinno;                 /* line # where last token started */
 static char *commandname;              /* currently executing command */
 static struct strlist *cmdenviron;     /* environment for builtin command */
 static int exitstatus;                 /* exit status of last command */
-static int back_exitstatus;            /* exit status of backquoted command */
 
 
 /* ============ Message printing */
@@ -2398,19 +2397,6 @@ static int casematch(union node *, char *);
 static void expari(int);
 #endif
 
-/*      eval.h       */
-
-
-
-struct backcmd {                /* result of evalbackcmd */
-       int fd;                 /* file descriptor to read from */
-       char *buf;              /* buffer */
-       int nleft;              /* number of chars in buffer */
-       struct job *jp;         /* job structure for command */
-};
-
-
-static void freefunc(struct funcnode *);
 /*      parser.h     */
 
 /* control characters in argument strings */
@@ -3160,104 +3146,6 @@ struct builtincmd {
        /* unsigned flags; */
 };
 
-
-#define COMMANDCMD (builtincmd + 5 + \
-       2 * ENABLE_ASH_BUILTIN_TEST + \
-       ENABLE_ASH_ALIAS + \
-       ENABLE_ASH_JOB_CONTROL)
-#define EXECCMD (builtincmd + 7 + \
-       2 * ENABLE_ASH_BUILTIN_TEST + \
-       ENABLE_ASH_ALIAS + \
-       ENABLE_ASH_JOB_CONTROL + \
-       ENABLE_ASH_CMDCMD + \
-       ENABLE_ASH_BUILTIN_ECHO)
-
-#define BUILTIN_NOSPEC  "0"
-#define BUILTIN_SPECIAL "1"
-#define BUILTIN_REGULAR "2"
-#define BUILTIN_SPEC_REG "3"
-#define BUILTIN_ASSIGN  "4"
-#define BUILTIN_SPEC_ASSG  "5"
-#define BUILTIN_REG_ASSG   "6"
-#define BUILTIN_SPEC_REG_ASSG   "7"
-
-#define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
-#define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
-#define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
-
-/* make sure to keep these in proper order since it is searched via bsearch() */
-static const struct builtincmd builtincmd[] = {
-       { BUILTIN_SPEC_REG      ".", dotcmd },
-       { BUILTIN_SPEC_REG      ":", truecmd },
-#if ENABLE_ASH_BUILTIN_TEST
-       { BUILTIN_REGULAR       "[", testcmd },
-       { BUILTIN_REGULAR       "[[", testcmd },
-#endif
-#if ENABLE_ASH_ALIAS
-       { BUILTIN_REG_ASSG      "alias", aliascmd },
-#endif
-#if JOBS
-       { BUILTIN_REGULAR       "bg", fg_bgcmd },
-#endif
-       { BUILTIN_SPEC_REG      "break", breakcmd },
-       { BUILTIN_REGULAR       "cd", cdcmd },
-       { BUILTIN_NOSPEC        "chdir", cdcmd },
-#if ENABLE_ASH_CMDCMD
-       { BUILTIN_REGULAR       "command", commandcmd },
-#endif
-       { BUILTIN_SPEC_REG      "continue", breakcmd },
-#if ENABLE_ASH_BUILTIN_ECHO
-       { BUILTIN_REGULAR       "echo", echocmd },
-#endif
-       { BUILTIN_SPEC_REG      "eval", evalcmd },
-       { BUILTIN_SPEC_REG      "exec", execcmd },
-       { BUILTIN_SPEC_REG      "exit", exitcmd },
-       { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
-       { BUILTIN_REGULAR       "false", falsecmd },
-#if JOBS
-       { BUILTIN_REGULAR       "fg", fg_bgcmd },
-#endif
-#if ENABLE_ASH_GETOPTS
-       { BUILTIN_REGULAR       "getopts", getoptscmd },
-#endif
-       { BUILTIN_NOSPEC        "hash", hashcmd },
-#if !ENABLE_FEATURE_SH_EXTRA_QUIET
-       { BUILTIN_NOSPEC        "help", helpcmd },
-#endif
-#if JOBS
-       { BUILTIN_REGULAR       "jobs", jobscmd },
-       { BUILTIN_REGULAR       "kill", killcmd },
-#endif
-#if ENABLE_ASH_MATH_SUPPORT
-       { BUILTIN_NOSPEC        "let", letcmd },
-#endif
-       { BUILTIN_ASSIGN        "local", localcmd },
-       { BUILTIN_NOSPEC        "pwd", pwdcmd },
-       { BUILTIN_REGULAR       "read", readcmd },
-       { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
-       { BUILTIN_SPEC_REG      "return", returncmd },
-       { BUILTIN_SPEC_REG      "set", setcmd },
-       { BUILTIN_SPEC_REG      "shift", shiftcmd },
-       { BUILTIN_SPEC_REG      "source", dotcmd },
-#if ENABLE_ASH_BUILTIN_TEST
-       { BUILTIN_REGULAR       "test", testcmd },
-#endif
-       { BUILTIN_SPEC_REG      "times", timescmd },
-       { BUILTIN_SPEC_REG      "trap", trapcmd },
-       { BUILTIN_REGULAR       "true", truecmd },
-       { BUILTIN_NOSPEC        "type", typecmd },
-       { BUILTIN_NOSPEC        "ulimit", ulimitcmd },
-       { BUILTIN_REGULAR       "umask", umaskcmd },
-#if ENABLE_ASH_ALIAS
-       { BUILTIN_REGULAR       "unalias", unaliascmd },
-#endif
-       { BUILTIN_SPEC_REG      "unset", unsetcmd },
-       { BUILTIN_REGULAR       "wait", waitcmd },
-};
-
-#define NUMBUILTINS (sizeof(builtincmd) / sizeof(builtincmd[0]))
-
-
 struct cmdentry {
        int cmdtype;
        union param {
@@ -3267,7 +3155,6 @@ struct cmdentry {
        } u;
 };
 
-
 /* action to find_command() */
 #define DO_ERR          0x01    /* prints errors */
 #define DO_ABS          0x02    /* checks absolute paths */
@@ -3674,12 +3561,6 @@ static void evalcommand(union node *, int);
 static int evalbltin(const struct builtincmd *, int, char **);
 static int evalfun(struct funcnode *, int, char **, int);
 static void prehash(union node *);
-static int bltincmd(int, char **);
-
-static const struct builtincmd bltin = {
-       "\0\0", bltincmd
-};
-
 
 /*
  * Evaluate a parse tree.  The value is left in the global variable
@@ -4039,57 +3920,6 @@ evalpipe(union node *n, int flags)
 }
 
 
-/*
- * Execute a command inside back quotes.  If it's a builtin command, we
- * want to save its output in a block obtained from malloc.  Otherwise
- * we fork off a subprocess and get the output of the command via a pipe.
- * Should be called with interrupts off.
- */
-static void
-evalbackcmd(union node *n, struct backcmd *result)
-{
-       int saveherefd;
-
-       result->fd = -1;
-       result->buf = NULL;
-       result->nleft = 0;
-       result->jp = NULL;
-       if (n == NULL) {
-               goto out;
-       }
-
-       saveherefd = herefd;
-       herefd = -1;
-
-       {
-               int pip[2];
-               struct job *jp;
-
-               if (pipe(pip) < 0)
-                       ash_msg_and_raise_error("Pipe call failed");
-               jp = makejob(n, 1);
-               if (forkshell(jp, n, FORK_NOJOB) == 0) {
-                       FORCE_INT_ON;
-                       close(pip[0]);
-                       if (pip[1] != 1) {
-                               close(1);
-                               copyfd(pip[1], 1);
-                               close(pip[1]);
-                       }
-                       eflag = 0;
-                       evaltreenr(n, EV_EXIT);
-                       /* NOTREACHED */
-               }
-               close(pip[1]);
-               result->fd = pip[0];
-               result->jp = jp;
-       }
-       herefd = saveherefd;
- out:
-       TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
-               result->fd, result->buf, result->nleft, result->jp));
-}
-
 #if ENABLE_ASH_CMDCMD
 static char **
 parse_command_args(char **argv, const char **path)
@@ -4125,20 +3955,127 @@ parse_command_args(char **argv, const char **path)
 }
 #endif
 
-static int isassignment(const char *p)
+#define BUILTIN_NOSPEC  "0"
+#define BUILTIN_SPECIAL "1"
+#define BUILTIN_REGULAR "2"
+#define BUILTIN_SPEC_REG "3"
+#define BUILTIN_ASSIGN  "4"
+#define BUILTIN_SPEC_ASSG  "5"
+#define BUILTIN_REG_ASSG   "6"
+#define BUILTIN_SPEC_REG_ASSG   "7"
+
+#define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
+#define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
+#define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
+
+/* make sure to keep these in proper order since it is searched via bsearch() */
+static const struct builtincmd builtintab[] = {
+       { BUILTIN_SPEC_REG      ".", dotcmd },
+       { BUILTIN_SPEC_REG      ":", truecmd },
+#if ENABLE_ASH_BUILTIN_TEST
+       { BUILTIN_REGULAR       "[", testcmd },
+       { BUILTIN_REGULAR       "[[", testcmd },
+#endif
+#if ENABLE_ASH_ALIAS
+       { BUILTIN_REG_ASSG      "alias", aliascmd },
+#endif
+#if JOBS
+       { BUILTIN_REGULAR       "bg", fg_bgcmd },
+#endif
+       { BUILTIN_SPEC_REG      "break", breakcmd },
+       { BUILTIN_REGULAR       "cd", cdcmd },
+       { BUILTIN_NOSPEC        "chdir", cdcmd },
+#if ENABLE_ASH_CMDCMD
+       { BUILTIN_REGULAR       "command", commandcmd },
+#endif
+       { BUILTIN_SPEC_REG      "continue", breakcmd },
+#if ENABLE_ASH_BUILTIN_ECHO
+       { BUILTIN_REGULAR       "echo", echocmd },
+#endif
+       { BUILTIN_SPEC_REG      "eval", evalcmd },
+       { BUILTIN_SPEC_REG      "exec", execcmd },
+       { BUILTIN_SPEC_REG      "exit", exitcmd },
+       { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
+       { BUILTIN_REGULAR       "false", falsecmd },
+#if JOBS
+       { BUILTIN_REGULAR       "fg", fg_bgcmd },
+#endif
+#if ENABLE_ASH_GETOPTS
+       { BUILTIN_REGULAR       "getopts", getoptscmd },
+#endif
+       { BUILTIN_NOSPEC        "hash", hashcmd },
+#if !ENABLE_FEATURE_SH_EXTRA_QUIET
+       { BUILTIN_NOSPEC        "help", helpcmd },
+#endif
+#if JOBS
+       { BUILTIN_REGULAR       "jobs", jobscmd },
+       { BUILTIN_REGULAR       "kill", killcmd },
+#endif
+#if ENABLE_ASH_MATH_SUPPORT
+       { BUILTIN_NOSPEC        "let", letcmd },
+#endif
+       { BUILTIN_ASSIGN        "local", localcmd },
+       { BUILTIN_NOSPEC        "pwd", pwdcmd },
+       { BUILTIN_REGULAR       "read", readcmd },
+       { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
+       { BUILTIN_SPEC_REG      "return", returncmd },
+       { BUILTIN_SPEC_REG      "set", setcmd },
+       { BUILTIN_SPEC_REG      "shift", shiftcmd },
+       { BUILTIN_SPEC_REG      "source", dotcmd },
+#if ENABLE_ASH_BUILTIN_TEST
+       { BUILTIN_REGULAR       "test", testcmd },
+#endif
+       { BUILTIN_SPEC_REG      "times", timescmd },
+       { BUILTIN_SPEC_REG      "trap", trapcmd },
+       { BUILTIN_REGULAR       "true", truecmd },
+       { BUILTIN_NOSPEC        "type", typecmd },
+       { BUILTIN_NOSPEC        "ulimit", ulimitcmd },
+       { BUILTIN_REGULAR       "umask", umaskcmd },
+#if ENABLE_ASH_ALIAS
+       { BUILTIN_REGULAR       "unalias", unaliascmd },
+#endif
+       { BUILTIN_SPEC_REG      "unset", unsetcmd },
+       { BUILTIN_REGULAR       "wait", waitcmd },
+};
+
+#define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0]))
+
+#define COMMANDCMD (builtintab + 5 + \
+       2 * ENABLE_ASH_BUILTIN_TEST + \
+       ENABLE_ASH_ALIAS + \
+       ENABLE_ASH_JOB_CONTROL)
+#define EXECCMD (builtintab + 7 + \
+       2 * ENABLE_ASH_BUILTIN_TEST + \
+       ENABLE_ASH_ALIAS + \
+       ENABLE_ASH_JOB_CONTROL + \
+       ENABLE_ASH_CMDCMD + \
+       ENABLE_ASH_BUILTIN_ECHO)
+
+/*
+ * Execute a simple command.
+ */
+static int back_exitstatus; /* exit status of backquoted command */
+static int
+isassignment(const char *p)
 {
        const char *q = endofname(p);
        if (p == q)
                return 0;
        return *q == '=';
 }
-
-/*
- * Execute a simple command.
- */
+static int
+bltincmd(int argc, char **argv)
+{
+       /* Preserve exitstatus of a previous possible redirection
+        * as POSIX mandates */
+       return back_exitstatus;
+}
 static void
 evalcommand(union node *cmd, int flags)
 {
+       static const struct builtincmd bltin = {
+               "\0\0", bltincmd
+       };
        struct stackmark smark;
        union node *argp;
        struct arglist arglist;
@@ -4269,7 +4206,6 @@ evalcommand(union node *cmd, int flags)
                                cmd_is_exec++;
 #if ENABLE_ASH_CMDCMD
                        if (cmdentry.u.cmd == COMMANDCMD) {
-
                                path = oldpath;
                                nargv = parse_command_args(argv, &path);
                                if (!nargv)
@@ -4429,6 +4365,16 @@ poplocalvars(void)
        }
 }
 
+/*
+ * Free a parse tree.
+ */
+static void
+freefunc(struct funcnode *f)
+{
+       if (f && --f->count < 0)
+               free(f);
+}
+
 static int
 evalfun(struct funcnode *func, int argc, char **argv, int flags)
 {
@@ -4497,26 +4443,11 @@ prehash(union node *n)
 }
 
 
-
 /*
  * Builtin commands.  Builtin commands whose functions are closely
  * tied to evaluation are implemented here.
  */
 
-/*
- * No command given.
- */
-static int
-bltincmd(int argc, char **argv)
-{
-       /*
-        * Preserve exitstatus of a previous possible redirection
-        * as POSIX mandates
-        */
-       return back_exitstatus;
-}
-
-
 /*
  * Handle break and continue commands.  Break, continue, and return are
  * all handled by setting the evalskip flag.  The evaluation routines
@@ -4544,7 +4475,6 @@ breakcmd(int argc, char **argv)
        return 0;
 }
 
-
 /*
  * The return command.
  */
@@ -4559,21 +4489,18 @@ returncmd(int argc, char **argv)
        return argv[1] ? number(argv[1]) : exitstatus;
 }
 
-
 static int
 falsecmd(int argc, char **argv)
 {
        return 1;
 }
 
-
 static int
 truecmd(int argc, char **argv)
 {
        return 0;
 }
 
-
 static int
 execcmd(int argc, char **argv)
 {
@@ -4984,7 +4911,7 @@ find_builtin(const char *name)
        struct builtincmd *bp;
 
        bp = bsearch(
-               name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
+               name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
                pstrcmp
        );
        return bp;
@@ -5154,7 +5081,8 @@ delete_cmd_entry(void)
  * Add a new command entry, replacing any existing command entry for
  * the same name - except special builtins.
  */
-static void addcmdentry(char *name, struct cmdentry *entry)
+static void
+addcmdentry(char *name, struct cmdentry *entry)
 {
        struct tblentry *cmdp;
 
@@ -5171,7 +5099,8 @@ static void addcmdentry(char *name, struct cmdentry *entry)
 /*
  * Make a copy of a parse tree.
  */
-static struct funcnode * copyfunc(union node *n)
+static struct funcnode *
+copyfunc(union node *n)
 {
        struct funcnode *f;
        size_t blocksize;
@@ -5188,7 +5117,6 @@ static struct funcnode * copyfunc(union node *n)
        return f;
 }
 
-
 /*
  * Define a shell function.
  */
@@ -5204,7 +5132,6 @@ defun(char *name, union node *func)
        INT_ON;
 }
 
-
 /*
  * Delete a function if it exists.
  */
@@ -5432,8 +5359,8 @@ static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NO
  *
  * Returns an stalloced string.
  */
-
-static char * preglob(const char *pattern, int quoted, int flag)
+static char *
+preglob(const char *pattern, int quoted, int flag)
 {
        flag |= RMESCAPE_GLOB;
        if (quoted) {
@@ -5458,8 +5385,8 @@ esclen(const char *start, const char *p)
 /*
  * Expand shell variables and backquotes inside a here document.
  */
-
-static void expandhere(union node *arg, int fd)
+static void
+expandhere(union node *arg, int fd)
 {
        herefd = fd;
        expandarg(arg, (struct arglist *)NULL, 0);
@@ -5756,7 +5683,7 @@ removerecordregions(int endoff)
  * Expand arithmetic expression.  Backup to start of expression,
  * evaluate, place result in (backed up) result, adjust string position.
  */
-void
+static void
 expari(int quotes)
 {
        char *p, *start;
@@ -5814,6 +5741,64 @@ expari(int quotes)
 #endif
 
 
+/*
+ * Execute a command inside back quotes.  If it's a builtin command, we
+ * want to save its output in a block obtained from malloc.  Otherwise
+ * we fork off a subprocess and get the output of the command via a pipe.
+ * Should be called with interrupts off.
+ */
+struct backcmd {                /* result of evalbackcmd */
+       int fd;                 /* file descriptor to read from */
+       char *buf;              /* buffer */
+       int nleft;              /* number of chars in buffer */
+       struct job *jp;         /* job structure for command */
+};
+
+static void
+evalbackcmd(union node *n, struct backcmd *result)
+{
+       int saveherefd;
+
+       result->fd = -1;
+       result->buf = NULL;
+       result->nleft = 0;
+       result->jp = NULL;
+       if (n == NULL) {
+               goto out;
+       }
+
+       saveherefd = herefd;
+       herefd = -1;
+
+       {
+               int pip[2];
+               struct job *jp;
+
+               if (pipe(pip) < 0)
+                       ash_msg_and_raise_error("Pipe call failed");
+               jp = makejob(n, 1);
+               if (forkshell(jp, n, FORK_NOJOB) == 0) {
+                       FORCE_INT_ON;
+                       close(pip[0]);
+                       if (pip[1] != 1) {
+                               close(1);
+                               copyfd(pip[1], 1);
+                               close(pip[1]);
+                       }
+                       eflag = 0;
+                       evaltreenr(n, EV_EXIT);
+                       /* NOTREACHED */
+               }
+               close(pip[1]);
+               result->fd = pip[0];
+               result->jp = jp;
+       }
+       herefd = saveherefd;
+ out:
+       TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
+               result->fd, result->buf, result->nleft, result->jp));
+}
+
 /*
  * Expand stuff in backwards quotes.
  */
@@ -5834,7 +5819,7 @@ expbackq(union node *cmd, int quoted, int quotes)
        dest = expdest;
        startloc = dest - (char *)stackblock();
        grabstackstr(dest);
-       evalbackcmd(cmd, (struct backcmd *) &in);
+       evalbackcmd(cmd, &in);
        popstackmark(&smark);
 
        p = in.buf;
@@ -8918,17 +8903,6 @@ nodeckstrdup(char *s)
 }
 
 
-/*
- * Free a parse tree.
- */
-static void
-freefunc(struct funcnode *f)
-{
-       if (f && --f->count < 0)
-               free(f);
-}
-
-
 static void
 optschanged(void)
 {