diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-23 01:05:26 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-23 01:05:26 +0000 |
commit | 34164b837f2b363552e9a22c9a2e06cb7677e603 (patch) | |
tree | 1705d1933309b84e9786bd890007492e0106e41b /shell | |
parent | d33682b521be56a5246299ac826d28442850e76a (diff) | |
download | busybox-w32-34164b837f2b363552e9a22c9a2e06cb7677e603.tar.gz busybox-w32-34164b837f2b363552e9a22c9a2e06cb7677e603.tar.bz2 busybox-w32-34164b837f2b363552e9a22c9a2e06cb7677e603.zip |
ash: cleanup part 7
git-svn-id: svn://busybox.net/trunk/busybox@17959 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 408 |
1 files changed, 191 insertions, 217 deletions
diff --git a/shell/ash.c b/shell/ash.c index 69b8ab0b9..e061211a0 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -932,7 +932,6 @@ static int startlinno; /* line # where last token started */ | |||
932 | static char *commandname; /* currently executing command */ | 932 | static char *commandname; /* currently executing command */ |
933 | static struct strlist *cmdenviron; /* environment for builtin command */ | 933 | static struct strlist *cmdenviron; /* environment for builtin command */ |
934 | static int exitstatus; /* exit status of last command */ | 934 | static int exitstatus; /* exit status of last command */ |
935 | static int back_exitstatus; /* exit status of backquoted command */ | ||
936 | 935 | ||
937 | 936 | ||
938 | /* ============ Message printing */ | 937 | /* ============ Message printing */ |
@@ -2398,19 +2397,6 @@ static int casematch(union node *, char *); | |||
2398 | static void expari(int); | 2397 | static void expari(int); |
2399 | #endif | 2398 | #endif |
2400 | 2399 | ||
2401 | /* eval.h */ | ||
2402 | |||
2403 | |||
2404 | |||
2405 | struct backcmd { /* result of evalbackcmd */ | ||
2406 | int fd; /* file descriptor to read from */ | ||
2407 | char *buf; /* buffer */ | ||
2408 | int nleft; /* number of chars in buffer */ | ||
2409 | struct job *jp; /* job structure for command */ | ||
2410 | }; | ||
2411 | |||
2412 | |||
2413 | static void freefunc(struct funcnode *); | ||
2414 | /* parser.h */ | 2400 | /* parser.h */ |
2415 | 2401 | ||
2416 | /* control characters in argument strings */ | 2402 | /* control characters in argument strings */ |
@@ -3160,104 +3146,6 @@ struct builtincmd { | |||
3160 | /* unsigned flags; */ | 3146 | /* unsigned flags; */ |
3161 | }; | 3147 | }; |
3162 | 3148 | ||
3163 | |||
3164 | #define COMMANDCMD (builtincmd + 5 + \ | ||
3165 | 2 * ENABLE_ASH_BUILTIN_TEST + \ | ||
3166 | ENABLE_ASH_ALIAS + \ | ||
3167 | ENABLE_ASH_JOB_CONTROL) | ||
3168 | #define EXECCMD (builtincmd + 7 + \ | ||
3169 | 2 * ENABLE_ASH_BUILTIN_TEST + \ | ||
3170 | ENABLE_ASH_ALIAS + \ | ||
3171 | ENABLE_ASH_JOB_CONTROL + \ | ||
3172 | ENABLE_ASH_CMDCMD + \ | ||
3173 | ENABLE_ASH_BUILTIN_ECHO) | ||
3174 | |||
3175 | #define BUILTIN_NOSPEC "0" | ||
3176 | #define BUILTIN_SPECIAL "1" | ||
3177 | #define BUILTIN_REGULAR "2" | ||
3178 | #define BUILTIN_SPEC_REG "3" | ||
3179 | #define BUILTIN_ASSIGN "4" | ||
3180 | #define BUILTIN_SPEC_ASSG "5" | ||
3181 | #define BUILTIN_REG_ASSG "6" | ||
3182 | #define BUILTIN_SPEC_REG_ASSG "7" | ||
3183 | |||
3184 | #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1) | ||
3185 | #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2) | ||
3186 | #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4) | ||
3187 | |||
3188 | /* make sure to keep these in proper order since it is searched via bsearch() */ | ||
3189 | static const struct builtincmd builtincmd[] = { | ||
3190 | { BUILTIN_SPEC_REG ".", dotcmd }, | ||
3191 | { BUILTIN_SPEC_REG ":", truecmd }, | ||
3192 | #if ENABLE_ASH_BUILTIN_TEST | ||
3193 | { BUILTIN_REGULAR "[", testcmd }, | ||
3194 | { BUILTIN_REGULAR "[[", testcmd }, | ||
3195 | #endif | ||
3196 | #if ENABLE_ASH_ALIAS | ||
3197 | { BUILTIN_REG_ASSG "alias", aliascmd }, | ||
3198 | #endif | ||
3199 | #if JOBS | ||
3200 | { BUILTIN_REGULAR "bg", fg_bgcmd }, | ||
3201 | #endif | ||
3202 | { BUILTIN_SPEC_REG "break", breakcmd }, | ||
3203 | { BUILTIN_REGULAR "cd", cdcmd }, | ||
3204 | { BUILTIN_NOSPEC "chdir", cdcmd }, | ||
3205 | #if ENABLE_ASH_CMDCMD | ||
3206 | { BUILTIN_REGULAR "command", commandcmd }, | ||
3207 | #endif | ||
3208 | { BUILTIN_SPEC_REG "continue", breakcmd }, | ||
3209 | #if ENABLE_ASH_BUILTIN_ECHO | ||
3210 | { BUILTIN_REGULAR "echo", echocmd }, | ||
3211 | #endif | ||
3212 | { BUILTIN_SPEC_REG "eval", evalcmd }, | ||
3213 | { BUILTIN_SPEC_REG "exec", execcmd }, | ||
3214 | { BUILTIN_SPEC_REG "exit", exitcmd }, | ||
3215 | { BUILTIN_SPEC_REG_ASSG "export", exportcmd }, | ||
3216 | { BUILTIN_REGULAR "false", falsecmd }, | ||
3217 | #if JOBS | ||
3218 | { BUILTIN_REGULAR "fg", fg_bgcmd }, | ||
3219 | #endif | ||
3220 | #if ENABLE_ASH_GETOPTS | ||
3221 | { BUILTIN_REGULAR "getopts", getoptscmd }, | ||
3222 | #endif | ||
3223 | { BUILTIN_NOSPEC "hash", hashcmd }, | ||
3224 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET | ||
3225 | { BUILTIN_NOSPEC "help", helpcmd }, | ||
3226 | #endif | ||
3227 | #if JOBS | ||
3228 | { BUILTIN_REGULAR "jobs", jobscmd }, | ||
3229 | { BUILTIN_REGULAR "kill", killcmd }, | ||
3230 | #endif | ||
3231 | #if ENABLE_ASH_MATH_SUPPORT | ||
3232 | { BUILTIN_NOSPEC "let", letcmd }, | ||
3233 | #endif | ||
3234 | { BUILTIN_ASSIGN "local", localcmd }, | ||
3235 | { BUILTIN_NOSPEC "pwd", pwdcmd }, | ||
3236 | { BUILTIN_REGULAR "read", readcmd }, | ||
3237 | { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd }, | ||
3238 | { BUILTIN_SPEC_REG "return", returncmd }, | ||
3239 | { BUILTIN_SPEC_REG "set", setcmd }, | ||
3240 | { BUILTIN_SPEC_REG "shift", shiftcmd }, | ||
3241 | { BUILTIN_SPEC_REG "source", dotcmd }, | ||
3242 | #if ENABLE_ASH_BUILTIN_TEST | ||
3243 | { BUILTIN_REGULAR "test", testcmd }, | ||
3244 | #endif | ||
3245 | { BUILTIN_SPEC_REG "times", timescmd }, | ||
3246 | { BUILTIN_SPEC_REG "trap", trapcmd }, | ||
3247 | { BUILTIN_REGULAR "true", truecmd }, | ||
3248 | { BUILTIN_NOSPEC "type", typecmd }, | ||
3249 | { BUILTIN_NOSPEC "ulimit", ulimitcmd }, | ||
3250 | { BUILTIN_REGULAR "umask", umaskcmd }, | ||
3251 | #if ENABLE_ASH_ALIAS | ||
3252 | { BUILTIN_REGULAR "unalias", unaliascmd }, | ||
3253 | #endif | ||
3254 | { BUILTIN_SPEC_REG "unset", unsetcmd }, | ||
3255 | { BUILTIN_REGULAR "wait", waitcmd }, | ||
3256 | }; | ||
3257 | |||
3258 | #define NUMBUILTINS (sizeof(builtincmd) / sizeof(builtincmd[0])) | ||
3259 | |||
3260 | |||
3261 | struct cmdentry { | 3149 | struct cmdentry { |
3262 | int cmdtype; | 3150 | int cmdtype; |
3263 | union param { | 3151 | union param { |
@@ -3267,7 +3155,6 @@ struct cmdentry { | |||
3267 | } u; | 3155 | } u; |
3268 | }; | 3156 | }; |
3269 | 3157 | ||
3270 | |||
3271 | /* action to find_command() */ | 3158 | /* action to find_command() */ |
3272 | #define DO_ERR 0x01 /* prints errors */ | 3159 | #define DO_ERR 0x01 /* prints errors */ |
3273 | #define DO_ABS 0x02 /* checks absolute paths */ | 3160 | #define DO_ABS 0x02 /* checks absolute paths */ |
@@ -3674,12 +3561,6 @@ static void evalcommand(union node *, int); | |||
3674 | static int evalbltin(const struct builtincmd *, int, char **); | 3561 | static int evalbltin(const struct builtincmd *, int, char **); |
3675 | static int evalfun(struct funcnode *, int, char **, int); | 3562 | static int evalfun(struct funcnode *, int, char **, int); |
3676 | static void prehash(union node *); | 3563 | static void prehash(union node *); |
3677 | static int bltincmd(int, char **); | ||
3678 | |||
3679 | static const struct builtincmd bltin = { | ||
3680 | "\0\0", bltincmd | ||
3681 | }; | ||
3682 | |||
3683 | 3564 | ||
3684 | /* | 3565 | /* |
3685 | * Evaluate a parse tree. The value is left in the global variable | 3566 | * Evaluate a parse tree. The value is left in the global variable |
@@ -4039,57 +3920,6 @@ evalpipe(union node *n, int flags) | |||
4039 | } | 3920 | } |
4040 | 3921 | ||
4041 | 3922 | ||
4042 | /* | ||
4043 | * Execute a command inside back quotes. If it's a builtin command, we | ||
4044 | * want to save its output in a block obtained from malloc. Otherwise | ||
4045 | * we fork off a subprocess and get the output of the command via a pipe. | ||
4046 | * Should be called with interrupts off. | ||
4047 | */ | ||
4048 | static void | ||
4049 | evalbackcmd(union node *n, struct backcmd *result) | ||
4050 | { | ||
4051 | int saveherefd; | ||
4052 | |||
4053 | result->fd = -1; | ||
4054 | result->buf = NULL; | ||
4055 | result->nleft = 0; | ||
4056 | result->jp = NULL; | ||
4057 | if (n == NULL) { | ||
4058 | goto out; | ||
4059 | } | ||
4060 | |||
4061 | saveherefd = herefd; | ||
4062 | herefd = -1; | ||
4063 | |||
4064 | { | ||
4065 | int pip[2]; | ||
4066 | struct job *jp; | ||
4067 | |||
4068 | if (pipe(pip) < 0) | ||
4069 | ash_msg_and_raise_error("Pipe call failed"); | ||
4070 | jp = makejob(n, 1); | ||
4071 | if (forkshell(jp, n, FORK_NOJOB) == 0) { | ||
4072 | FORCE_INT_ON; | ||
4073 | close(pip[0]); | ||
4074 | if (pip[1] != 1) { | ||
4075 | close(1); | ||
4076 | copyfd(pip[1], 1); | ||
4077 | close(pip[1]); | ||
4078 | } | ||
4079 | eflag = 0; | ||
4080 | evaltreenr(n, EV_EXIT); | ||
4081 | /* NOTREACHED */ | ||
4082 | } | ||
4083 | close(pip[1]); | ||
4084 | result->fd = pip[0]; | ||
4085 | result->jp = jp; | ||
4086 | } | ||
4087 | herefd = saveherefd; | ||
4088 | out: | ||
4089 | TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", | ||
4090 | result->fd, result->buf, result->nleft, result->jp)); | ||
4091 | } | ||
4092 | |||
4093 | #if ENABLE_ASH_CMDCMD | 3923 | #if ENABLE_ASH_CMDCMD |
4094 | static char ** | 3924 | static char ** |
4095 | parse_command_args(char **argv, const char **path) | 3925 | parse_command_args(char **argv, const char **path) |
@@ -4125,20 +3955,127 @@ parse_command_args(char **argv, const char **path) | |||
4125 | } | 3955 | } |
4126 | #endif | 3956 | #endif |
4127 | 3957 | ||
4128 | static int isassignment(const char *p) | 3958 | #define BUILTIN_NOSPEC "0" |
3959 | #define BUILTIN_SPECIAL "1" | ||
3960 | #define BUILTIN_REGULAR "2" | ||
3961 | #define BUILTIN_SPEC_REG "3" | ||
3962 | #define BUILTIN_ASSIGN "4" | ||
3963 | #define BUILTIN_SPEC_ASSG "5" | ||
3964 | #define BUILTIN_REG_ASSG "6" | ||
3965 | #define BUILTIN_SPEC_REG_ASSG "7" | ||
3966 | |||
3967 | #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1) | ||
3968 | #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2) | ||
3969 | #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4) | ||
3970 | |||
3971 | /* make sure to keep these in proper order since it is searched via bsearch() */ | ||
3972 | static const struct builtincmd builtintab[] = { | ||
3973 | { BUILTIN_SPEC_REG ".", dotcmd }, | ||
3974 | { BUILTIN_SPEC_REG ":", truecmd }, | ||
3975 | #if ENABLE_ASH_BUILTIN_TEST | ||
3976 | { BUILTIN_REGULAR "[", testcmd }, | ||
3977 | { BUILTIN_REGULAR "[[", testcmd }, | ||
3978 | #endif | ||
3979 | #if ENABLE_ASH_ALIAS | ||
3980 | { BUILTIN_REG_ASSG "alias", aliascmd }, | ||
3981 | #endif | ||
3982 | #if JOBS | ||
3983 | { BUILTIN_REGULAR "bg", fg_bgcmd }, | ||
3984 | #endif | ||
3985 | { BUILTIN_SPEC_REG "break", breakcmd }, | ||
3986 | { BUILTIN_REGULAR "cd", cdcmd }, | ||
3987 | { BUILTIN_NOSPEC "chdir", cdcmd }, | ||
3988 | #if ENABLE_ASH_CMDCMD | ||
3989 | { BUILTIN_REGULAR "command", commandcmd }, | ||
3990 | #endif | ||
3991 | { BUILTIN_SPEC_REG "continue", breakcmd }, | ||
3992 | #if ENABLE_ASH_BUILTIN_ECHO | ||
3993 | { BUILTIN_REGULAR "echo", echocmd }, | ||
3994 | #endif | ||
3995 | { BUILTIN_SPEC_REG "eval", evalcmd }, | ||
3996 | { BUILTIN_SPEC_REG "exec", execcmd }, | ||
3997 | { BUILTIN_SPEC_REG "exit", exitcmd }, | ||
3998 | { BUILTIN_SPEC_REG_ASSG "export", exportcmd }, | ||
3999 | { BUILTIN_REGULAR "false", falsecmd }, | ||
4000 | #if JOBS | ||
4001 | { BUILTIN_REGULAR "fg", fg_bgcmd }, | ||
4002 | #endif | ||
4003 | #if ENABLE_ASH_GETOPTS | ||
4004 | { BUILTIN_REGULAR "getopts", getoptscmd }, | ||
4005 | #endif | ||
4006 | { BUILTIN_NOSPEC "hash", hashcmd }, | ||
4007 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET | ||
4008 | { BUILTIN_NOSPEC "help", helpcmd }, | ||
4009 | #endif | ||
4010 | #if JOBS | ||
4011 | { BUILTIN_REGULAR "jobs", jobscmd }, | ||
4012 | { BUILTIN_REGULAR "kill", killcmd }, | ||
4013 | #endif | ||
4014 | #if ENABLE_ASH_MATH_SUPPORT | ||
4015 | { BUILTIN_NOSPEC "let", letcmd }, | ||
4016 | #endif | ||
4017 | { BUILTIN_ASSIGN "local", localcmd }, | ||
4018 | { BUILTIN_NOSPEC "pwd", pwdcmd }, | ||
4019 | { BUILTIN_REGULAR "read", readcmd }, | ||
4020 | { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd }, | ||
4021 | { BUILTIN_SPEC_REG "return", returncmd }, | ||
4022 | { BUILTIN_SPEC_REG "set", setcmd }, | ||
4023 | { BUILTIN_SPEC_REG "shift", shiftcmd }, | ||
4024 | { BUILTIN_SPEC_REG "source", dotcmd }, | ||
4025 | #if ENABLE_ASH_BUILTIN_TEST | ||
4026 | { BUILTIN_REGULAR "test", testcmd }, | ||
4027 | #endif | ||
4028 | { BUILTIN_SPEC_REG "times", timescmd }, | ||
4029 | { BUILTIN_SPEC_REG "trap", trapcmd }, | ||
4030 | { BUILTIN_REGULAR "true", truecmd }, | ||
4031 | { BUILTIN_NOSPEC "type", typecmd }, | ||
4032 | { BUILTIN_NOSPEC "ulimit", ulimitcmd }, | ||
4033 | { BUILTIN_REGULAR "umask", umaskcmd }, | ||
4034 | #if ENABLE_ASH_ALIAS | ||
4035 | { BUILTIN_REGULAR "unalias", unaliascmd }, | ||
4036 | #endif | ||
4037 | { BUILTIN_SPEC_REG "unset", unsetcmd }, | ||
4038 | { BUILTIN_REGULAR "wait", waitcmd }, | ||
4039 | }; | ||
4040 | |||
4041 | #define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0])) | ||
4042 | |||
4043 | #define COMMANDCMD (builtintab + 5 + \ | ||
4044 | 2 * ENABLE_ASH_BUILTIN_TEST + \ | ||
4045 | ENABLE_ASH_ALIAS + \ | ||
4046 | ENABLE_ASH_JOB_CONTROL) | ||
4047 | #define EXECCMD (builtintab + 7 + \ | ||
4048 | 2 * ENABLE_ASH_BUILTIN_TEST + \ | ||
4049 | ENABLE_ASH_ALIAS + \ | ||
4050 | ENABLE_ASH_JOB_CONTROL + \ | ||
4051 | ENABLE_ASH_CMDCMD + \ | ||
4052 | ENABLE_ASH_BUILTIN_ECHO) | ||
4053 | |||
4054 | /* | ||
4055 | * Execute a simple command. | ||
4056 | */ | ||
4057 | static int back_exitstatus; /* exit status of backquoted command */ | ||
4058 | static int | ||
4059 | isassignment(const char *p) | ||
4129 | { | 4060 | { |
4130 | const char *q = endofname(p); | 4061 | const char *q = endofname(p); |
4131 | if (p == q) | 4062 | if (p == q) |
4132 | return 0; | 4063 | return 0; |
4133 | return *q == '='; | 4064 | return *q == '='; |
4134 | } | 4065 | } |
4135 | 4066 | static int | |
4136 | /* | 4067 | bltincmd(int argc, char **argv) |
4137 | * Execute a simple command. | 4068 | { |
4138 | */ | 4069 | /* Preserve exitstatus of a previous possible redirection |
4070 | * as POSIX mandates */ | ||
4071 | return back_exitstatus; | ||
4072 | } | ||
4139 | static void | 4073 | static void |
4140 | evalcommand(union node *cmd, int flags) | 4074 | evalcommand(union node *cmd, int flags) |
4141 | { | 4075 | { |
4076 | static const struct builtincmd bltin = { | ||
4077 | "\0\0", bltincmd | ||
4078 | }; | ||
4142 | struct stackmark smark; | 4079 | struct stackmark smark; |
4143 | union node *argp; | 4080 | union node *argp; |
4144 | struct arglist arglist; | 4081 | struct arglist arglist; |
@@ -4269,7 +4206,6 @@ evalcommand(union node *cmd, int flags) | |||
4269 | cmd_is_exec++; | 4206 | cmd_is_exec++; |
4270 | #if ENABLE_ASH_CMDCMD | 4207 | #if ENABLE_ASH_CMDCMD |
4271 | if (cmdentry.u.cmd == COMMANDCMD) { | 4208 | if (cmdentry.u.cmd == COMMANDCMD) { |
4272 | |||
4273 | path = oldpath; | 4209 | path = oldpath; |
4274 | nargv = parse_command_args(argv, &path); | 4210 | nargv = parse_command_args(argv, &path); |
4275 | if (!nargv) | 4211 | if (!nargv) |
@@ -4429,6 +4365,16 @@ poplocalvars(void) | |||
4429 | } | 4365 | } |
4430 | } | 4366 | } |
4431 | 4367 | ||
4368 | /* | ||
4369 | * Free a parse tree. | ||
4370 | */ | ||
4371 | static void | ||
4372 | freefunc(struct funcnode *f) | ||
4373 | { | ||
4374 | if (f && --f->count < 0) | ||
4375 | free(f); | ||
4376 | } | ||
4377 | |||
4432 | static int | 4378 | static int |
4433 | evalfun(struct funcnode *func, int argc, char **argv, int flags) | 4379 | evalfun(struct funcnode *func, int argc, char **argv, int flags) |
4434 | { | 4380 | { |
@@ -4497,27 +4443,12 @@ prehash(union node *n) | |||
4497 | } | 4443 | } |
4498 | 4444 | ||
4499 | 4445 | ||
4500 | |||
4501 | /* | 4446 | /* |
4502 | * Builtin commands. Builtin commands whose functions are closely | 4447 | * Builtin commands. Builtin commands whose functions are closely |
4503 | * tied to evaluation are implemented here. | 4448 | * tied to evaluation are implemented here. |
4504 | */ | 4449 | */ |
4505 | 4450 | ||
4506 | /* | 4451 | /* |
4507 | * No command given. | ||
4508 | */ | ||
4509 | static int | ||
4510 | bltincmd(int argc, char **argv) | ||
4511 | { | ||
4512 | /* | ||
4513 | * Preserve exitstatus of a previous possible redirection | ||
4514 | * as POSIX mandates | ||
4515 | */ | ||
4516 | return back_exitstatus; | ||
4517 | } | ||
4518 | |||
4519 | |||
4520 | /* | ||
4521 | * Handle break and continue commands. Break, continue, and return are | 4452 | * Handle break and continue commands. Break, continue, and return are |
4522 | * all handled by setting the evalskip flag. The evaluation routines | 4453 | * all handled by setting the evalskip flag. The evaluation routines |
4523 | * above all check this flag, and if it is set they start skipping | 4454 | * above all check this flag, and if it is set they start skipping |
@@ -4544,7 +4475,6 @@ breakcmd(int argc, char **argv) | |||
4544 | return 0; | 4475 | return 0; |
4545 | } | 4476 | } |
4546 | 4477 | ||
4547 | |||
4548 | /* | 4478 | /* |
4549 | * The return command. | 4479 | * The return command. |
4550 | */ | 4480 | */ |
@@ -4559,21 +4489,18 @@ returncmd(int argc, char **argv) | |||
4559 | return argv[1] ? number(argv[1]) : exitstatus; | 4489 | return argv[1] ? number(argv[1]) : exitstatus; |
4560 | } | 4490 | } |
4561 | 4491 | ||
4562 | |||
4563 | static int | 4492 | static int |
4564 | falsecmd(int argc, char **argv) | 4493 | falsecmd(int argc, char **argv) |
4565 | { | 4494 | { |
4566 | return 1; | 4495 | return 1; |
4567 | } | 4496 | } |
4568 | 4497 | ||
4569 | |||
4570 | static int | 4498 | static int |
4571 | truecmd(int argc, char **argv) | 4499 | truecmd(int argc, char **argv) |
4572 | { | 4500 | { |
4573 | return 0; | 4501 | return 0; |
4574 | } | 4502 | } |
4575 | 4503 | ||
4576 | |||
4577 | static int | 4504 | static int |
4578 | execcmd(int argc, char **argv) | 4505 | execcmd(int argc, char **argv) |
4579 | { | 4506 | { |
@@ -4984,7 +4911,7 @@ find_builtin(const char *name) | |||
4984 | struct builtincmd *bp; | 4911 | struct builtincmd *bp; |
4985 | 4912 | ||
4986 | bp = bsearch( | 4913 | bp = bsearch( |
4987 | name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd), | 4914 | name, builtintab, NUMBUILTINS, sizeof(builtintab[0]), |
4988 | pstrcmp | 4915 | pstrcmp |
4989 | ); | 4916 | ); |
4990 | return bp; | 4917 | return bp; |
@@ -5154,7 +5081,8 @@ delete_cmd_entry(void) | |||
5154 | * Add a new command entry, replacing any existing command entry for | 5081 | * Add a new command entry, replacing any existing command entry for |
5155 | * the same name - except special builtins. | 5082 | * the same name - except special builtins. |
5156 | */ | 5083 | */ |
5157 | static void addcmdentry(char *name, struct cmdentry *entry) | 5084 | static void |
5085 | addcmdentry(char *name, struct cmdentry *entry) | ||
5158 | { | 5086 | { |
5159 | struct tblentry *cmdp; | 5087 | struct tblentry *cmdp; |
5160 | 5088 | ||
@@ -5171,7 +5099,8 @@ static void addcmdentry(char *name, struct cmdentry *entry) | |||
5171 | /* | 5099 | /* |
5172 | * Make a copy of a parse tree. | 5100 | * Make a copy of a parse tree. |
5173 | */ | 5101 | */ |
5174 | static struct funcnode * copyfunc(union node *n) | 5102 | static struct funcnode * |
5103 | copyfunc(union node *n) | ||
5175 | { | 5104 | { |
5176 | struct funcnode *f; | 5105 | struct funcnode *f; |
5177 | size_t blocksize; | 5106 | size_t blocksize; |
@@ -5188,7 +5117,6 @@ static struct funcnode * copyfunc(union node *n) | |||
5188 | return f; | 5117 | return f; |
5189 | } | 5118 | } |
5190 | 5119 | ||
5191 | |||
5192 | /* | 5120 | /* |
5193 | * Define a shell function. | 5121 | * Define a shell function. |
5194 | */ | 5122 | */ |
@@ -5204,7 +5132,6 @@ defun(char *name, union node *func) | |||
5204 | INT_ON; | 5132 | INT_ON; |
5205 | } | 5133 | } |
5206 | 5134 | ||
5207 | |||
5208 | /* | 5135 | /* |
5209 | * Delete a function if it exists. | 5136 | * Delete a function if it exists. |
5210 | */ | 5137 | */ |
@@ -5432,8 +5359,8 @@ static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NO | |||
5432 | * | 5359 | * |
5433 | * Returns an stalloced string. | 5360 | * Returns an stalloced string. |
5434 | */ | 5361 | */ |
5435 | 5362 | static char * | |
5436 | static char * preglob(const char *pattern, int quoted, int flag) | 5363 | preglob(const char *pattern, int quoted, int flag) |
5437 | { | 5364 | { |
5438 | flag |= RMESCAPE_GLOB; | 5365 | flag |= RMESCAPE_GLOB; |
5439 | if (quoted) { | 5366 | if (quoted) { |
@@ -5458,8 +5385,8 @@ esclen(const char *start, const char *p) | |||
5458 | /* | 5385 | /* |
5459 | * Expand shell variables and backquotes inside a here document. | 5386 | * Expand shell variables and backquotes inside a here document. |
5460 | */ | 5387 | */ |
5461 | 5388 | static void | |
5462 | static void expandhere(union node *arg, int fd) | 5389 | expandhere(union node *arg, int fd) |
5463 | { | 5390 | { |
5464 | herefd = fd; | 5391 | herefd = fd; |
5465 | expandarg(arg, (struct arglist *)NULL, 0); | 5392 | expandarg(arg, (struct arglist *)NULL, 0); |
@@ -5756,7 +5683,7 @@ removerecordregions(int endoff) | |||
5756 | * Expand arithmetic expression. Backup to start of expression, | 5683 | * Expand arithmetic expression. Backup to start of expression, |
5757 | * evaluate, place result in (backed up) result, adjust string position. | 5684 | * evaluate, place result in (backed up) result, adjust string position. |
5758 | */ | 5685 | */ |
5759 | void | 5686 | static void |
5760 | expari(int quotes) | 5687 | expari(int quotes) |
5761 | { | 5688 | { |
5762 | char *p, *start; | 5689 | char *p, *start; |
@@ -5815,6 +5742,64 @@ expari(int quotes) | |||
5815 | 5742 | ||
5816 | 5743 | ||
5817 | /* | 5744 | /* |
5745 | * Execute a command inside back quotes. If it's a builtin command, we | ||
5746 | * want to save its output in a block obtained from malloc. Otherwise | ||
5747 | * we fork off a subprocess and get the output of the command via a pipe. | ||
5748 | * Should be called with interrupts off. | ||
5749 | */ | ||
5750 | struct backcmd { /* result of evalbackcmd */ | ||
5751 | int fd; /* file descriptor to read from */ | ||
5752 | char *buf; /* buffer */ | ||
5753 | int nleft; /* number of chars in buffer */ | ||
5754 | struct job *jp; /* job structure for command */ | ||
5755 | }; | ||
5756 | |||
5757 | static void | ||
5758 | evalbackcmd(union node *n, struct backcmd *result) | ||
5759 | { | ||
5760 | int saveherefd; | ||
5761 | |||
5762 | result->fd = -1; | ||
5763 | result->buf = NULL; | ||
5764 | result->nleft = 0; | ||
5765 | result->jp = NULL; | ||
5766 | if (n == NULL) { | ||
5767 | goto out; | ||
5768 | } | ||
5769 | |||
5770 | saveherefd = herefd; | ||
5771 | herefd = -1; | ||
5772 | |||
5773 | { | ||
5774 | int pip[2]; | ||
5775 | struct job *jp; | ||
5776 | |||
5777 | if (pipe(pip) < 0) | ||
5778 | ash_msg_and_raise_error("Pipe call failed"); | ||
5779 | jp = makejob(n, 1); | ||
5780 | if (forkshell(jp, n, FORK_NOJOB) == 0) { | ||
5781 | FORCE_INT_ON; | ||
5782 | close(pip[0]); | ||
5783 | if (pip[1] != 1) { | ||
5784 | close(1); | ||
5785 | copyfd(pip[1], 1); | ||
5786 | close(pip[1]); | ||
5787 | } | ||
5788 | eflag = 0; | ||
5789 | evaltreenr(n, EV_EXIT); | ||
5790 | /* NOTREACHED */ | ||
5791 | } | ||
5792 | close(pip[1]); | ||
5793 | result->fd = pip[0]; | ||
5794 | result->jp = jp; | ||
5795 | } | ||
5796 | herefd = saveherefd; | ||
5797 | out: | ||
5798 | TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", | ||
5799 | result->fd, result->buf, result->nleft, result->jp)); | ||
5800 | } | ||
5801 | |||
5802 | /* | ||
5818 | * Expand stuff in backwards quotes. | 5803 | * Expand stuff in backwards quotes. |
5819 | */ | 5804 | */ |
5820 | static void | 5805 | static void |
@@ -5834,7 +5819,7 @@ expbackq(union node *cmd, int quoted, int quotes) | |||
5834 | dest = expdest; | 5819 | dest = expdest; |
5835 | startloc = dest - (char *)stackblock(); | 5820 | startloc = dest - (char *)stackblock(); |
5836 | grabstackstr(dest); | 5821 | grabstackstr(dest); |
5837 | evalbackcmd(cmd, (struct backcmd *) &in); | 5822 | evalbackcmd(cmd, &in); |
5838 | popstackmark(&smark); | 5823 | popstackmark(&smark); |
5839 | 5824 | ||
5840 | p = in.buf; | 5825 | p = in.buf; |
@@ -8918,17 +8903,6 @@ nodeckstrdup(char *s) | |||
8918 | } | 8903 | } |
8919 | 8904 | ||
8920 | 8905 | ||
8921 | /* | ||
8922 | * Free a parse tree. | ||
8923 | */ | ||
8924 | static void | ||
8925 | freefunc(struct funcnode *f) | ||
8926 | { | ||
8927 | if (f && --f->count < 0) | ||
8928 | free(f); | ||
8929 | } | ||
8930 | |||
8931 | |||
8932 | static void | 8906 | static void |
8933 | optschanged(void) | 8907 | optschanged(void) |
8934 | { | 8908 | { |