ash: cleanup part 7

This commit is contained in:
Denis Vlasenko 2007-02-23 01:05:26 +00:00
parent a6704933dd
commit 4fe15f3d9e

View File

@ -932,7 +932,6 @@ static int startlinno; /* line # where last token started */
static char *commandname; /* currently executing command */ static char *commandname; /* currently executing command */
static struct strlist *cmdenviron; /* environment for builtin command */ static struct strlist *cmdenviron; /* environment for builtin command */
static int exitstatus; /* exit status of last command */ static int exitstatus; /* exit status of last command */
static int back_exitstatus; /* exit status of backquoted command */
/* ============ Message printing */ /* ============ Message printing */
@ -2398,19 +2397,6 @@ static int casematch(union node *, char *);
static void expari(int); static void expari(int);
#endif #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 */ /* parser.h */
/* control characters in argument strings */ /* control characters in argument strings */
@ -3160,104 +3146,6 @@ struct builtincmd {
/* unsigned flags; */ /* 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 { struct cmdentry {
int cmdtype; int cmdtype;
union param { union param {
@ -3267,7 +3155,6 @@ struct cmdentry {
} u; } u;
}; };
/* action to find_command() */ /* action to find_command() */
#define DO_ERR 0x01 /* prints errors */ #define DO_ERR 0x01 /* prints errors */
#define DO_ABS 0x02 /* checks absolute paths */ #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 evalbltin(const struct builtincmd *, int, char **);
static int evalfun(struct funcnode *, int, char **, int); static int evalfun(struct funcnode *, int, char **, int);
static void prehash(union node *); 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 * 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 #if ENABLE_ASH_CMDCMD
static char ** static char **
parse_command_args(char **argv, const char **path) parse_command_args(char **argv, const char **path)
@ -4125,20 +3955,127 @@ parse_command_args(char **argv, const char **path)
} }
#endif #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); const char *q = endofname(p);
if (p == q) if (p == q)
return 0; return 0;
return *q == '='; return *q == '=';
} }
static int
/* bltincmd(int argc, char **argv)
* Execute a simple command. {
*/ /* Preserve exitstatus of a previous possible redirection
* as POSIX mandates */
return back_exitstatus;
}
static void static void
evalcommand(union node *cmd, int flags) evalcommand(union node *cmd, int flags)
{ {
static const struct builtincmd bltin = {
"\0\0", bltincmd
};
struct stackmark smark; struct stackmark smark;
union node *argp; union node *argp;
struct arglist arglist; struct arglist arglist;
@ -4269,7 +4206,6 @@ evalcommand(union node *cmd, int flags)
cmd_is_exec++; cmd_is_exec++;
#if ENABLE_ASH_CMDCMD #if ENABLE_ASH_CMDCMD
if (cmdentry.u.cmd == COMMANDCMD) { if (cmdentry.u.cmd == COMMANDCMD) {
path = oldpath; path = oldpath;
nargv = parse_command_args(argv, &path); nargv = parse_command_args(argv, &path);
if (!nargv) 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 static int
evalfun(struct funcnode *func, int argc, char **argv, int flags) 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 * Builtin commands. Builtin commands whose functions are closely
* tied to evaluation are implemented here. * 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 * Handle break and continue commands. Break, continue, and return are
* all handled by setting the evalskip flag. The evaluation routines * all handled by setting the evalskip flag. The evaluation routines
@ -4544,7 +4475,6 @@ breakcmd(int argc, char **argv)
return 0; return 0;
} }
/* /*
* The return command. * The return command.
*/ */
@ -4559,21 +4489,18 @@ returncmd(int argc, char **argv)
return argv[1] ? number(argv[1]) : exitstatus; return argv[1] ? number(argv[1]) : exitstatus;
} }
static int static int
falsecmd(int argc, char **argv) falsecmd(int argc, char **argv)
{ {
return 1; return 1;
} }
static int static int
truecmd(int argc, char **argv) truecmd(int argc, char **argv)
{ {
return 0; return 0;
} }
static int static int
execcmd(int argc, char **argv) execcmd(int argc, char **argv)
{ {
@ -4984,7 +4911,7 @@ find_builtin(const char *name)
struct builtincmd *bp; struct builtincmd *bp;
bp = bsearch( bp = bsearch(
name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd), name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
pstrcmp pstrcmp
); );
return bp; return bp;
@ -5154,7 +5081,8 @@ delete_cmd_entry(void)
* Add a new command entry, replacing any existing command entry for * Add a new command entry, replacing any existing command entry for
* the same name - except special builtins. * 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; struct tblentry *cmdp;
@ -5171,7 +5099,8 @@ static void addcmdentry(char *name, struct cmdentry *entry)
/* /*
* Make a copy of a parse tree. * Make a copy of a parse tree.
*/ */
static struct funcnode * copyfunc(union node *n) static struct funcnode *
copyfunc(union node *n)
{ {
struct funcnode *f; struct funcnode *f;
size_t blocksize; size_t blocksize;
@ -5188,7 +5117,6 @@ static struct funcnode * copyfunc(union node *n)
return f; return f;
} }
/* /*
* Define a shell function. * Define a shell function.
*/ */
@ -5204,7 +5132,6 @@ defun(char *name, union node *func)
INT_ON; INT_ON;
} }
/* /*
* Delete a function if it exists. * 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. * Returns an stalloced string.
*/ */
static char *
static char * preglob(const char *pattern, int quoted, int flag) preglob(const char *pattern, int quoted, int flag)
{ {
flag |= RMESCAPE_GLOB; flag |= RMESCAPE_GLOB;
if (quoted) { if (quoted) {
@ -5458,8 +5385,8 @@ esclen(const char *start, const char *p)
/* /*
* Expand shell variables and backquotes inside a here document. * Expand shell variables and backquotes inside a here document.
*/ */
static void
static void expandhere(union node *arg, int fd) expandhere(union node *arg, int fd)
{ {
herefd = fd; herefd = fd;
expandarg(arg, (struct arglist *)NULL, 0); expandarg(arg, (struct arglist *)NULL, 0);
@ -5756,7 +5683,7 @@ removerecordregions(int endoff)
* Expand arithmetic expression. Backup to start of expression, * Expand arithmetic expression. Backup to start of expression,
* evaluate, place result in (backed up) result, adjust string position. * evaluate, place result in (backed up) result, adjust string position.
*/ */
void static void
expari(int quotes) expari(int quotes)
{ {
char *p, *start; char *p, *start;
@ -5814,6 +5741,64 @@ expari(int quotes)
#endif #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. * Expand stuff in backwards quotes.
*/ */
@ -5834,7 +5819,7 @@ expbackq(union node *cmd, int quoted, int quotes)
dest = expdest; dest = expdest;
startloc = dest - (char *)stackblock(); startloc = dest - (char *)stackblock();
grabstackstr(dest); grabstackstr(dest);
evalbackcmd(cmd, (struct backcmd *) &in); evalbackcmd(cmd, &in);
popstackmark(&smark); popstackmark(&smark);
p = in.buf; 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 static void
optschanged(void) optschanged(void)
{ {