aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 01:05:26 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 01:05:26 +0000
commit34164b837f2b363552e9a22c9a2e06cb7677e603 (patch)
tree1705d1933309b84e9786bd890007492e0106e41b /shell
parentd33682b521be56a5246299ac826d28442850e76a (diff)
downloadbusybox-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.c408
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 */
932static char *commandname; /* currently executing command */ 932static char *commandname; /* currently executing command */
933static struct strlist *cmdenviron; /* environment for builtin command */ 933static struct strlist *cmdenviron; /* environment for builtin command */
934static int exitstatus; /* exit status of last command */ 934static int exitstatus; /* exit status of last command */
935static 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 *);
2398static void expari(int); 2397static void expari(int);
2399#endif 2398#endif
2400 2399
2401/* eval.h */
2402
2403
2404
2405struct 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
2413static 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() */
3189static 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
3261struct cmdentry { 3149struct 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);
3674static int evalbltin(const struct builtincmd *, int, char **); 3561static int evalbltin(const struct builtincmd *, int, char **);
3675static int evalfun(struct funcnode *, int, char **, int); 3562static int evalfun(struct funcnode *, int, char **, int);
3676static void prehash(union node *); 3563static void prehash(union node *);
3677static int bltincmd(int, char **);
3678
3679static 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 */
4048static void
4049evalbackcmd(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
4094static char ** 3924static char **
4095parse_command_args(char **argv, const char **path) 3925parse_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
4128static 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() */
3972static 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 */
4057static int back_exitstatus; /* exit status of backquoted command */
4058static int
4059isassignment(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 4066static int
4136/* 4067bltincmd(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}
4139static void 4073static void
4140evalcommand(union node *cmd, int flags) 4074evalcommand(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 */
4371static void
4372freefunc(struct funcnode *f)
4373{
4374 if (f && --f->count < 0)
4375 free(f);
4376}
4377
4432static int 4378static int
4433evalfun(struct funcnode *func, int argc, char **argv, int flags) 4379evalfun(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 */
4509static int
4510bltincmd(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
4563static int 4492static int
4564falsecmd(int argc, char **argv) 4493falsecmd(int argc, char **argv)
4565{ 4494{
4566 return 1; 4495 return 1;
4567} 4496}
4568 4497
4569
4570static int 4498static int
4571truecmd(int argc, char **argv) 4499truecmd(int argc, char **argv)
4572{ 4500{
4573 return 0; 4501 return 0;
4574} 4502}
4575 4503
4576
4577static int 4504static int
4578execcmd(int argc, char **argv) 4505execcmd(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 */
5157static void addcmdentry(char *name, struct cmdentry *entry) 5084static void
5085addcmdentry(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 */
5174static struct funcnode * copyfunc(union node *n) 5102static struct funcnode *
5103copyfunc(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 5362static char *
5436static char * preglob(const char *pattern, int quoted, int flag) 5363preglob(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 5388static void
5462static void expandhere(union node *arg, int fd) 5389expandhere(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 */
5759void 5686static void
5760expari(int quotes) 5687expari(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 */
5750struct 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
5757static void
5758evalbackcmd(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 */
5820static void 5805static 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 */
8924static void
8925freefunc(struct funcnode *f)
8926{
8927 if (f && --f->count < 0)
8928 free(f);
8929}
8930
8931
8932static void 8906static void
8933optschanged(void) 8907optschanged(void)
8934{ 8908{