summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-08-23 13:14:48 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-08-23 13:14:48 +0000
commit50812fff219a3d0b9eccb9ff9647d6d66a7934c7 (patch)
tree8bc85cb977beca060f7eefc8bf395b3e8dfdfca0 /shell
parentde9e803149a6e3e2d8c7db03620dd94b48a55843 (diff)
downloadbusybox-w32-50812fff219a3d0b9eccb9ff9647d6d66a7934c7.tar.gz
busybox-w32-50812fff219a3d0b9eccb9ff9647d6d66a7934c7.tar.bz2
busybox-w32-50812fff219a3d0b9eccb9ff9647d6d66a7934c7.zip
Apply vodz last_path_51-2
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c566
1 files changed, 171 insertions, 395 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 15ec04380..216f1c4e9 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -267,7 +267,6 @@ static void stunalloc(pointer);
267static void ungrabstackstr(char *, char *); 267static void ungrabstackstr(char *, char *);
268static char *growstackstr(void); 268static char *growstackstr(void);
269static char *makestrspace(size_t newlen); 269static char *makestrspace(size_t newlen);
270static char *sstrdup(const char *);
271 270
272/* 271/*
273 * Parse trees for commands are allocated in lifo order, so we use a stack 272 * Parse trees for commands are allocated in lifo order, so we use a stack
@@ -311,7 +310,6 @@ static int stacknleft = MINSIZE;
311#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) 310#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
312 311
313 312
314
315#ifdef DEBUG 313#ifdef DEBUG
316#define TRACE(param) trace param 314#define TRACE(param) trace param
317typedef union node unode; 315typedef union node unode;
@@ -676,37 +674,22 @@ static void out2c(int c)
676#define ARISYNTAX 3 /* in arithmetic */ 674#define ARISYNTAX 3 /* in arithmetic */
677 675
678static const char S_I_T[][4] = { 676static const char S_I_T[][4] = {
679 /* 0 */ {CSPCL, CIGN, CIGN, CIGN}, 677 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
680 /* PEOA */ 678 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
681 /* 1 */ {CSPCL, CWORD, CWORD, CWORD}, 679 {CNL, CNL, CNL, CNL}, /* 2, \n */
682 /* ' ' */ 680 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
683 /* 2 */ {CNL, CNL, CNL, CNL}, 681 {CDQUOTE, CENDQUOTE, CWORD, CDQUOTE}, /* 4, '"' */
684 /* \n */ 682 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
685 /* 3 */ {CWORD, CCTL, CCTL, CWORD}, 683 {CSQUOTE, CWORD, CENDQUOTE, CSQUOTE}, /* 6, "'" */
686 /* !*-/:=?[]~ */ 684 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
687 /* 4 */ {CDQUOTE, CENDQUOTE, CWORD, CDQUOTE}, 685 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
688 /* '"' */ 686 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
689 /* 5 */ {CVAR, CVAR, CWORD, CVAR}, 687 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
690 /* $ */ 688 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
691 /* 6 */ {CSQUOTE, CWORD, CENDQUOTE, CSQUOTE},
692 /* "'" */
693 /* 7 */ {CSPCL, CWORD, CWORD, CLP},
694 /* ( */
695 /* 8 */ {CSPCL, CWORD, CWORD, CRP},
696 /* ) */
697 /* 9 */ {CBACK, CBACK, CCTL, CBACK},
698 /* \ */
699 /* 10 */ {CBQUOTE, CBQUOTE, CWORD, CBQUOTE},
700 /* ` */
701 /* 11 */ {CENDVAR, CENDVAR, CWORD, CENDVAR},
702 /* } */
703#ifndef USE_SIT_FUNCTION 689#ifndef USE_SIT_FUNCTION
704 /* 12 */ {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, 690 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
705 /* PEOF */ 691 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
706 /* 13 */ {CWORD, CWORD, CWORD, CWORD}, 692 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
707 /* 0-9A-Za-z */
708 /* 14 */ {CCTL, CCTL, CCTL, CCTL}
709 /* CTLESC ... */
710#endif 693#endif
711}; 694};
712 695
@@ -766,16 +749,16 @@ static const char syntax_index_table[258] = {
766 /* 0 -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE, 749 /* 0 -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
767 /* 1 -129 PEOA */ CSPCL_CIGN_CIGN_CIGN, 750 /* 1 -129 PEOA */ CSPCL_CIGN_CIGN_CIGN,
768 /* 2 -128 0xff */ CWORD_CWORD_CWORD_CWORD, 751 /* 2 -128 0xff */ CWORD_CWORD_CWORD_CWORD,
769 /* 3 -127 */ CCTL_CCTL_CCTL_CCTL, 752 /* 3 -127 */ CCTL_CCTL_CCTL_CCTL,
770 /* CTLQUOTEMARK */ 753 /* CTLQUOTEMARK */
771 /* 4 -126 */ CCTL_CCTL_CCTL_CCTL, 754 /* 4 -126 */ CCTL_CCTL_CCTL_CCTL,
772 /* 5 -125 */ CCTL_CCTL_CCTL_CCTL, 755 /* 5 -125 */ CCTL_CCTL_CCTL_CCTL,
773 /* 6 -124 */ CCTL_CCTL_CCTL_CCTL, 756 /* 6 -124 */ CCTL_CCTL_CCTL_CCTL,
774 /* 7 -123 */ CCTL_CCTL_CCTL_CCTL, 757 /* 7 -123 */ CCTL_CCTL_CCTL_CCTL,
775 /* 8 -122 */ CCTL_CCTL_CCTL_CCTL, 758 /* 8 -122 */ CCTL_CCTL_CCTL_CCTL,
776 /* 9 -121 */ CCTL_CCTL_CCTL_CCTL, 759 /* 9 -121 */ CCTL_CCTL_CCTL_CCTL,
777 /* 10 -120 */ CCTL_CCTL_CCTL_CCTL, 760 /* 10 -120 */ CCTL_CCTL_CCTL_CCTL,
778 /* CTLESC */ 761 /* CTLESC */
779 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD, 762 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
780 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD, 763 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
781 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD, 764 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
@@ -1107,15 +1090,9 @@ static void onsig(int);
1107static void dotrap(void); 1090static void dotrap(void);
1108static int decode_signal(const char *, int); 1091static int decode_signal(const char *, int);
1109 1092
1110static void shprocvar(void);
1111static void deletefuncs(void);
1112static void setparam(char **); 1093static void setparam(char **);
1113static void freeparam(volatile struct shparam *); 1094static void freeparam(volatile struct shparam *);
1114 1095
1115static void find_command(const char *, struct cmdentry *, int, const char *);
1116
1117static inline void hashcd(void);
1118
1119/* reasons for skipping commands (see comment on breakcmd routine) */ 1096/* reasons for skipping commands (see comment on breakcmd routine) */
1120#define SKIPBREAK 1 1097#define SKIPBREAK 1
1121#define SKIPCONT 2 1098#define SKIPCONT 2
@@ -1583,7 +1560,7 @@ static void setpwd(const char *, int);
1583struct builtincmd { 1560struct builtincmd {
1584 const char *name; 1561 const char *name;
1585 int (*const builtinfunc) (int, char **); 1562 int (*const builtinfunc) (int, char **);
1586 /* unsigned flags; */ 1563 //unsigned flags;
1587}; 1564};
1588 1565
1589 1566
@@ -1660,7 +1637,7 @@ static struct builtincmd *EXECCMD;
1660static struct builtincmd *EVALCMD; 1637static struct builtincmd *EVALCMD;
1661 1638
1662/* states */ 1639/* states */
1663#define CONFIG_ASH_JOB_CONTROLTOPPED 1 /* all procs are stopped */ 1640#define JOBSTOPPED 1 /* all procs are stopped */
1664#define JOBDONE 2 /* all procs are completed */ 1641#define JOBDONE 2 /* all procs are completed */
1665 1642
1666/* 1643/*
@@ -1708,7 +1685,6 @@ static int initialpgrp; /* pgrp of shell on invocation */
1708static int curjob; /* current job */ 1685static int curjob; /* current job */
1709static int jobctl; 1686static int jobctl;
1710#endif 1687#endif
1711static int intreceived;
1712 1688
1713static struct job *makejob(const union node *, int); 1689static struct job *makejob(const union node *, int);
1714static int forkshell(struct job *, const union node *, int); 1690static int forkshell(struct job *, const union node *, int);
@@ -1769,6 +1745,28 @@ static int cdcmd(int argc, char **argv)
1769 1745
1770 1746
1771/* 1747/*
1748 * Update curdir (the name of the current directory) in response to a
1749 * cd command. We also call hashcd to let the routines in exec.c know
1750 * that the current directory has changed.
1751 */
1752
1753static void hashcd(void);
1754
1755static inline void updatepwd(const char *dir)
1756{
1757 hashcd(); /* update command hash table */
1758
1759 /*
1760 * If our argument is NULL, we don't know the current directory
1761 */
1762 if (dir == NULL || curdir == nullstr) {
1763 setpwd(0, 1);
1764 } else {
1765 setpwd(dir, 1);
1766 }
1767}
1768
1769/*
1772 * Actually do the chdir. In an interactive shell, print the 1770 * Actually do the chdir. In an interactive shell, print the
1773 * directory name if "print" is nonzero. 1771 * directory name if "print" is nonzero.
1774 */ 1772 */
@@ -1781,18 +1779,7 @@ static int docd(char *dest, int print)
1781 INTON; 1779 INTON;
1782 return -1; 1780 return -1;
1783 } 1781 }
1784 hashcd(); 1782 updatepwd(dest);
1785 /*
1786 * Update curdir (the name of the current directory) in response to a
1787 * cd command. We also call hashcd to let the routines in exec.c know
1788 * that the current directory has changed.
1789 */
1790 /* If dest is NULL, we don't know the current directory */
1791 if (dest == NULL || curdir == nullstr)
1792 setpwd(0, 1);
1793 else
1794 setpwd(dest, 1);
1795
1796 INTON; 1783 INTON;
1797 if (print && iflag) 1784 if (print && iflag)
1798 puts(curdir); 1785 puts(curdir);
@@ -1863,6 +1850,7 @@ struct jmploc {
1863#define EXERROR 1 /* a generic error */ 1850#define EXERROR 1 /* a generic error */
1864#define EXSHELLPROC 2 /* execute a shell procedure */ 1851#define EXSHELLPROC 2 /* execute a shell procedure */
1865#define EXEXEC 3 /* command execution failed */ 1852#define EXEXEC 3 /* command execution failed */
1853#define EXREDIR 4 /* redirection error */
1866 1854
1867static struct jmploc *handler; 1855static struct jmploc *handler;
1868static int exception; 1856static int exception;
@@ -1911,12 +1899,11 @@ static void onint(void)
1911 intpending = 0; 1899 intpending = 0;
1912 sigemptyset(&mysigset); 1900 sigemptyset(&mysigset);
1913 sigprocmask(SIG_SETMASK, &mysigset, NULL); 1901 sigprocmask(SIG_SETMASK, &mysigset, NULL);
1914 if (rootshell && iflag) 1902 if (!(rootshell && iflag)) {
1915 exraise(EXINT);
1916 else {
1917 signal(SIGINT, SIG_DFL); 1903 signal(SIGINT, SIG_DFL);
1918 raise(SIGINT); 1904 raise(SIGINT);
1919 } 1905 }
1906 exraise(EXINT);
1920 /* NOTREACHED */ 1907 /* NOTREACHED */
1921} 1908}
1922 1909
@@ -2101,6 +2088,7 @@ static int oexitstatus; /* saved exit status */
2101 2088
2102static void evalsubshell(const union node *, int); 2089static void evalsubshell(const union node *, int);
2103static void expredir(union node *); 2090static void expredir(union node *);
2091static void prehash(union node *);
2104static void eprintlist(struct strlist *); 2092static void eprintlist(struct strlist *);
2105 2093
2106static union node *parsecmd(int); 2094static union node *parsecmd(int);
@@ -2218,6 +2206,7 @@ static inline void evalloop(const union node *n, int flags)
2218 2206
2219 loopnest++; 2207 loopnest++;
2220 status = 0; 2208 status = 0;
2209 flags &= EV_TESTED;
2221 for (;;) { 2210 for (;;) {
2222 evaltree(n->nbinary.ch1, EV_TESTED); 2211 evaltree(n->nbinary.ch1, EV_TESTED);
2223 if (evalskip) { 2212 if (evalskip) {
@@ -2236,7 +2225,7 @@ static inline void evalloop(const union node *n, int flags)
2236 if (exitstatus == 0) 2225 if (exitstatus == 0)
2237 break; 2226 break;
2238 } 2227 }
2239 evaltree(n->nbinary.ch2, flags & EV_TESTED); 2228 evaltree(n->nbinary.ch2, flags);
2240 status = exitstatus; 2229 status = exitstatus;
2241 if (evalskip) 2230 if (evalskip)
2242 goto skipping; 2231 goto skipping;
@@ -2264,9 +2253,10 @@ static void evalfor(const union node *n, int flags)
2264 2253
2265 exitstatus = 0; 2254 exitstatus = 0;
2266 loopnest++; 2255 loopnest++;
2256 flags &= EV_TESTED;
2267 for (sp = arglist.list; sp; sp = sp->next) { 2257 for (sp = arglist.list; sp; sp = sp->next) {
2268 setvar(n->nfor.var, sp->text, 0); 2258 setvar(n->nfor.var, sp->text, 0);
2269 evaltree(n->nfor.body, flags & EV_TESTED); 2259 evaltree(n->nfor.body, flags);
2270 if (evalskip) { 2260 if (evalskip) {
2271 if (evalskip == SKIPCONT && --skipcount <= 0) { 2261 if (evalskip == SKIPCONT && --skipcount <= 0) {
2272 evalskip = 0; 2262 evalskip = 0;
@@ -2314,7 +2304,7 @@ static inline void evalcase(const union node *n, int flags)
2314 * of all the rest.) 2304 * of all the rest.)
2315 */ 2305 */
2316 2306
2317static inline void evalpipe(union node *n) 2307static inline void evalpipe(union node *n, int flags)
2318{ 2308{
2319 struct job *jp; 2309 struct job *jp;
2320 struct nodelist *lp; 2310 struct nodelist *lp;
@@ -2326,24 +2316,12 @@ static inline void evalpipe(union node *n)
2326 pipelen = 0; 2316 pipelen = 0;
2327 for (lp = n->npipe.cmdlist; lp; lp = lp->next) 2317 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
2328 pipelen++; 2318 pipelen++;
2319 flags |= EV_EXIT;
2329 INTOFF; 2320 INTOFF;
2330 jp = makejob(n, pipelen); 2321 jp = makejob(n, pipelen);
2331 prevfd = -1; 2322 prevfd = -1;
2332 for (lp = n->npipe.cmdlist; lp; lp = lp->next) { 2323 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
2333 /* 2324 prehash(lp->n);
2334 * Search for a command. This is called before we fork so that the
2335 * location of the command will be available in the parent as well as
2336 * the child. The check for "goodname" is an overly conservative
2337 * check that the name will not be subject to expansion.
2338 */
2339
2340 struct cmdentry entry;
2341 union node *lpn = lp->n;
2342
2343 if (lpn->type == NCMD && lpn->ncmd.args
2344 && goodname(lpn->ncmd.args->narg.text))
2345 find_command(lpn->ncmd.args->narg.text, &entry, 0, pathval());
2346
2347 pip[1] = -1; 2325 pip[1] = -1;
2348 if (lp->next) { 2326 if (lp->next) {
2349 if (pipe(pip) < 0) { 2327 if (pipe(pip) < 0) {
@@ -2353,40 +2331,33 @@ static inline void evalpipe(union node *n)
2353 } 2331 }
2354 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { 2332 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2355 INTON; 2333 INTON;
2334 if (pip[1] >= 0) {
2335 close(pip[0]);
2336 }
2356 if (prevfd > 0) { 2337 if (prevfd > 0) {
2357 close(0); 2338 dup2(prevfd, 0);
2358 dup_as_newfd(prevfd, 0);
2359 close(prevfd); 2339 close(prevfd);
2360 if (pip[0] == 0) {
2361 pip[0] = -1;
2362 }
2363 } 2340 }
2364 if (pip[1] >= 0) { 2341 if (pip[1] > 1) {
2365 if (pip[0] >= 0) { 2342 dup2(pip[1], 1);
2366 close(pip[0]); 2343 close(pip[1]);
2367 }
2368 if (pip[1] != 1) {
2369 close(1);
2370 dup_as_newfd(pip[1], 1);
2371 close(pip[1]);
2372 }
2373 } 2344 }
2374 evaltree(lp->n, EV_EXIT); 2345 evaltree(lp->n, flags);
2375 } 2346 }
2376 if (prevfd >= 0) 2347 if (prevfd >= 0)
2377 close(prevfd); 2348 close(prevfd);
2378 prevfd = pip[0]; 2349 prevfd = pip[0];
2379 close(pip[1]); 2350 close(pip[1]);
2380 } 2351 }
2381 INTON;
2382 if (n->npipe.backgnd == 0) { 2352 if (n->npipe.backgnd == 0) {
2383 INTOFF;
2384 exitstatus = waitforjob(jp); 2353 exitstatus = waitforjob(jp);
2385 TRACE(("evalpipe: job done exit status %d\n", exitstatus)); 2354 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
2386 INTON;
2387 } 2355 }
2356 INTON;
2388} 2357}
2389 2358
2359static void find_command(const char *, struct cmdentry *, int, const char *);
2360
2390static int isassignment(const char *word) 2361static int isassignment(const char *word)
2391{ 2362{
2392 if (!is_name(*word)) { 2363 if (!is_name(*word)) {
@@ -2418,7 +2389,7 @@ static void evalcommand(union node *cmd, int flags)
2418 volatile int e; 2389 volatile int e;
2419 char *lastarg; 2390 char *lastarg;
2420 const char *path; 2391 const char *path;
2421 const struct builtincmd *firstbltin; 2392 int spclbltin;
2422 struct jmploc *volatile savehandler; 2393 struct jmploc *volatile savehandler;
2423 struct jmploc jmploc; 2394 struct jmploc jmploc;
2424 2395
@@ -2428,6 +2399,7 @@ static void evalcommand(union node *cmd, int flags)
2428 (void) &argc; 2399 (void) &argc;
2429 (void) &lastarg; 2400 (void) &lastarg;
2430 (void) &flags; 2401 (void) &flags;
2402 (void) &spclbltin;
2431#endif 2403#endif
2432 2404
2433 /* First expand the arguments. */ 2405 /* First expand the arguments. */
@@ -2442,23 +2414,9 @@ static void evalcommand(union node *cmd, int flags)
2442 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { 2414 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2443 expandarg(argp, &varlist, EXP_VARTILDE); 2415 expandarg(argp, &varlist, EXP_VARTILDE);
2444 } 2416 }
2445 for (argp = cmd->ncmd.args; argp && !arglist.list; argp = argp->narg.next) { 2417 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
2446 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 2418 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2447 } 2419 }
2448 if (argp) {
2449 struct builtincmd *bcmd;
2450 int pseudovarflag;
2451
2452 bcmd = find_builtin(arglist.list->text);
2453 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2454 for (; argp; argp = argp->narg.next) {
2455 if (pseudovarflag && isassignment(argp->narg.text)) {
2456 expandarg(argp, &arglist, EXP_VARTILDE);
2457 continue;
2458 }
2459 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2460 }
2461 }
2462 *arglist.lastp = NULL; 2420 *arglist.lastp = NULL;
2463 *varlist.lastp = NULL; 2421 *varlist.lastp = NULL;
2464 expredir(cmd->ncmd.redirect); 2422 expredir(cmd->ncmd.redirect);
@@ -2488,7 +2446,8 @@ static void evalcommand(union node *cmd, int flags)
2488 /* Now locate the command. */ 2446 /* Now locate the command. */
2489 if (argc == 0) { 2447 if (argc == 0) {
2490 cmdentry.cmdtype = CMDBUILTIN; 2448 cmdentry.cmdtype = CMDBUILTIN;
2491 firstbltin = cmdentry.u.cmd = BLTINCMD; 2449 cmdentry.u.cmd = BLTINCMD;
2450 spclbltin = 1;
2492 } else { 2451 } else {
2493 const char *oldpath; 2452 const char *oldpath;
2494 int findflag = DO_ERR; 2453 int findflag = DO_ERR;
@@ -2505,7 +2464,7 @@ static void evalcommand(union node *cmd, int flags)
2505 } 2464 }
2506 oldpath = path; 2465 oldpath = path;
2507 oldfindflag = findflag; 2466 oldfindflag = findflag;
2508 firstbltin = 0; 2467 spclbltin = -1;
2509 for (;;) { 2468 for (;;) {
2510 find_command(argv[0], &cmdentry, findflag, path); 2469 find_command(argv[0], &cmdentry, findflag, path);
2511 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ 2470 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
@@ -2516,8 +2475,8 @@ static void evalcommand(union node *cmd, int flags)
2516 if (cmdentry.cmdtype != CMDBUILTIN) { 2475 if (cmdentry.cmdtype != CMDBUILTIN) {
2517 break; 2476 break;
2518 } 2477 }
2519 if (!firstbltin) { 2478 if (spclbltin < 0) {
2520 firstbltin = cmdentry.u.cmd; 2479 spclbltin = !!(IS_BUILTIN_SPECIAL(cmdentry.u.cmd)) * 2;
2521 } 2480 }
2522 if (cmdentry.u.cmd == BLTINCMD) { 2481 if (cmdentry.u.cmd == BLTINCMD) {
2523 for (;;) { 2482 for (;;) {
@@ -2567,13 +2526,17 @@ static void evalcommand(union node *cmd, int flags)
2567 2526
2568 /* Fork off a child process if necessary. */ 2527 /* Fork off a child process if necessary. */
2569 if (cmd->ncmd.backgnd 2528 if (cmd->ncmd.backgnd
2570 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) 2529 || (cmdentry.cmdtype == CMDNORMAL && (!(flags & EV_EXIT) || trap[0]))
2571 ) { 2530 ) {
2531 INTOFF;
2572 jp = makejob(cmd, 1); 2532 jp = makejob(cmd, 1);
2573 mode = cmd->ncmd.backgnd; 2533 mode = cmd->ncmd.backgnd;
2574 if (forkshell(jp, cmd, mode) != 0) 2534 if (forkshell(jp, cmd, mode) != 0)
2575 goto parent; /* at end of routine */ 2535 goto parent; /* at end of routine */
2536 FORCEINTON;
2576 flags |= EV_EXIT; 2537 flags |= EV_EXIT;
2538 } else {
2539 flags &= ~EV_EXIT;
2577 } 2540 }
2578 2541
2579 /* This is the child process if a fork occurred. */ 2542 /* This is the child process if a fork occurred. */
@@ -2584,7 +2547,6 @@ static void evalcommand(union node *cmd, int flags)
2584 trargs(argv); 2547 trargs(argv);
2585#endif 2548#endif
2586 exitstatus = oexitstatus; 2549 exitstatus = oexitstatus;
2587 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2588 saveparam = shellparam; 2550 saveparam = shellparam;
2589 shellparam.malloc = 0; 2551 shellparam.malloc = 0;
2590 shellparam.nparam = argc - 1; 2552 shellparam.nparam = argc - 1;
@@ -2594,15 +2556,14 @@ static void evalcommand(union node *cmd, int flags)
2594 localvars = NULL; 2556 localvars = NULL;
2595 INTON; 2557 INTON;
2596 if (setjmp(jmploc.loc)) { 2558 if (setjmp(jmploc.loc)) {
2597 if (exception == EXSHELLPROC) { 2559 if (exception == EXREDIR) {
2598 freeparam((volatile struct shparam *) 2560 exitstatus = 2;
2599 &saveparam); 2561 goto funcdone;
2600 } else {
2601 saveparam.optind = shellparam.optind;
2602 saveparam.optoff = shellparam.optoff;
2603 freeparam(&shellparam);
2604 shellparam = saveparam;
2605 } 2562 }
2563 saveparam.optind = shellparam.optind;
2564 saveparam.optoff = shellparam.optoff;
2565 freeparam(&shellparam);
2566 shellparam = saveparam;
2606 poplocalvars(); 2567 poplocalvars();
2607 localvars = savelocalvars; 2568 localvars = savelocalvars;
2608 handler = savehandler; 2569 handler = savehandler;
@@ -2610,11 +2571,12 @@ static void evalcommand(union node *cmd, int flags)
2610 } 2571 }
2611 savehandler = handler; 2572 savehandler = handler;
2612 handler = &jmploc; 2573 handler = &jmploc;
2613 for (sp = varlist.list; sp; sp = sp->next) 2574 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2614 mklocal(sp->text); 2575 listsetvar(varlist.list);
2615 funcnest++; 2576 funcnest++;
2616 evaltree(cmdentry.u.func, flags & EV_TESTED); 2577 evaltree(cmdentry.u.func, flags & EV_TESTED);
2617 funcnest--; 2578 funcnest--;
2579 funcdone:
2618 INTOFF; 2580 INTOFF;
2619 poplocalvars(); 2581 poplocalvars();
2620 localvars = savelocalvars; 2582 localvars = savelocalvars;
@@ -2629,17 +2591,16 @@ static void evalcommand(union node *cmd, int flags)
2629 evalskip = 0; 2591 evalskip = 0;
2630 skipcount = 0; 2592 skipcount = 0;
2631 } 2593 }
2632 if (flags & EV_EXIT)
2633 exitshell(exitstatus);
2634 } else if (cmdentry.cmdtype == CMDBUILTIN) { 2594 } else if (cmdentry.cmdtype == CMDBUILTIN) {
2595 int redir;
2596
2635#ifdef DEBUG 2597#ifdef DEBUG
2636 trputs("builtin command: "); 2598 trputs("builtin command: ");
2637 trargs(argv); 2599 trargs(argv);
2638#endif 2600#endif
2639 mode = (cmdentry.u.cmd == EXECCMD) ? 0 : REDIR_PUSH; 2601 redir = (cmdentry.u.cmd == EXECCMD) ? 0 : REDIR_PUSH;
2640 redirect(cmd->ncmd.redirect, mode);
2641 savecmdname = commandname; 2602 savecmdname = commandname;
2642 if (IS_BUILTIN_SPECIAL(firstbltin)) { 2603 if (spclbltin) {
2643 listsetvar(varlist.list); 2604 listsetvar(varlist.list);
2644 } else { 2605 } else {
2645 cmdenviron = varlist.list; 2606 cmdenviron = varlist.list;
@@ -2652,6 +2613,7 @@ static void evalcommand(union node *cmd, int flags)
2652 } 2613 }
2653 savehandler = handler; 2614 savehandler = handler;
2654 handler = &jmploc; 2615 handler = &jmploc;
2616 redirect(cmd->ncmd.redirect, redir);
2655 commandname = argv[0]; 2617 commandname = argv[0];
2656 argptr = argv + 1; 2618 argptr = argv + 1;
2657 optptr = NULL; /* initialize nextopt */ 2619 optptr = NULL; /* initialize nextopt */
@@ -2659,18 +2621,13 @@ static void evalcommand(union node *cmd, int flags)
2659 flushall(); 2621 flushall();
2660 cmddone: 2622 cmddone:
2661 cmdenviron = NULL; 2623 cmdenviron = NULL;
2662 if (e != EXSHELLPROC) { 2624 commandname = savecmdname;
2663 commandname = savecmdname;
2664 if (flags & EV_EXIT)
2665 exitshell(exitstatus);
2666 }
2667 handler = savehandler; 2625 handler = savehandler;
2668 if (e != -1) { 2626 if (e != -1) {
2669 if ((e != EXERROR && e != EXEXEC) 2627 if (e == EXINT || spclbltin & 2) {
2670 || cmdentry.u.cmd == BLTINCMD 2628 if (e == EXREDIR)
2671 || cmdentry.u.cmd == DOTCMD 2629 exraise(e);
2672 || cmdentry.u.cmd == EVALCMD || cmdentry.u.cmd == EXECCMD) 2630 }
2673 exraise(e);
2674 FORCEINTON; 2631 FORCEINTON;
2675 } 2632 }
2676 if (cmdentry.u.cmd != EXECCMD) 2633 if (cmdentry.u.cmd != EXECCMD)
@@ -2687,14 +2644,15 @@ static void evalcommand(union node *cmd, int flags)
2687 envp = environment(); 2644 envp = environment();
2688 shellexec(argv, envp, path, cmdentry.u.index); 2645 shellexec(argv, envp, path, cmdentry.u.index);
2689 } 2646 }
2647 if (flags & EV_EXIT)
2648 exitshell(exitstatus);
2690 goto out; 2649 goto out;
2691 2650
2692 parent: /* parent process gets here (if we forked) */ 2651 parent: /* parent process gets here (if we forked) */
2693 if (mode == 0) { /* argument to fork */ 2652 if (mode == 0) { /* argument to fork */
2694 INTOFF;
2695 exitstatus = waitforjob(jp); 2653 exitstatus = waitforjob(jp);
2696 INTON;
2697 } 2654 }
2655 INTON;
2698 2656
2699 out: 2657 out:
2700 if (lastarg) 2658 if (lastarg)
@@ -2790,7 +2748,7 @@ static void evaltree(union node *n, int flags)
2790 break; 2748 break;
2791 2749
2792 case NPIPE: 2750 case NPIPE:
2793 evalpipe(n); 2751 evalpipe(n, flags);
2794 checkexit = 1; 2752 checkexit = 1;
2795 break; 2753 break;
2796 case NCMD: 2754 case NCMD:
@@ -2818,22 +2776,27 @@ static void evaltree(union node *n, int flags)
2818 2776
2819static void evalsubshell(const union node *n, int flags) 2777static void evalsubshell(const union node *n, int flags)
2820{ 2778{
2821 struct job *jp; 2779 struct job *jp = 0;
2822 int backgnd = (n->type == NBACKGND); 2780 int backgnd = (n->type == NBACKGND);
2823 2781
2824 expredir(n->nredir.redirect); 2782 expredir(n->nredir.redirect);
2783 if (!backgnd && flags & EV_EXIT && !trap[0])
2784 goto nofork;
2785 INTOFF;
2825 jp = makejob(n, 1); 2786 jp = makejob(n, 1);
2826 if (forkshell(jp, n, backgnd) == 0) { 2787 if (forkshell(jp, n, backgnd) == 0) {
2788 INTON;
2789 flags |= EV_EXIT;
2827 if (backgnd) 2790 if (backgnd)
2828 flags &= ~EV_TESTED; 2791 flags &= ~EV_TESTED;
2792 nofork:
2829 redirect(n->nredir.redirect, 0); 2793 redirect(n->nredir.redirect, 0);
2830 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ 2794 evaltree(n->nredir.n, flags); /* never returns */
2831 } 2795 }
2832 if (!backgnd) { 2796 if (!backgnd) {
2833 INTOFF;
2834 exitstatus = waitforjob(jp); 2797 exitstatus = waitforjob(jp);
2835 INTON;
2836 } 2798 }
2799 INTON;
2837} 2800}
2838 2801
2839/* 2802/*
@@ -2923,6 +2886,22 @@ static void evalbackcmd(union node *n, struct backcmd *result)
2923 * Execute a simple command. 2886 * Execute a simple command.
2924 */ 2887 */
2925 2888
2889/*
2890 * Search for a command. This is called before we fork so that the
2891 * location of the command will be available in the parent as well as
2892 * the child. The check for "goodname" is an overly conservative
2893 * check that the name will not be subject to expansion.
2894 */
2895
2896static void prehash(union node *n)
2897{
2898 struct cmdentry entry;
2899
2900 if (n->type == NCMD && n->ncmd.args)
2901 if (goodname(n->ncmd.args->narg.text))
2902 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
2903}
2904
2926 2905
2927/* 2906/*
2928 * Builtin commands. Builtin commands whose functions are closely 2907 * Builtin commands. Builtin commands whose functions are closely
@@ -3132,65 +3111,6 @@ static void clear_traps(void)
3132} 3111}
3133 3112
3134 3113
3135static void initshellproc(void)
3136{
3137
3138#ifdef CONFIG_ASH_ALIAS
3139 /* from alias.c: */
3140 {
3141 rmaliases();
3142 }
3143#endif
3144 /* from eval.c: */
3145 {
3146 exitstatus = 0;
3147 }
3148
3149 /* from exec.c: */
3150 {
3151 deletefuncs();
3152 }
3153
3154 /* from jobs.c: */
3155 {
3156 backgndpid = -1;
3157#ifdef CONFIG_ASH_JOB_CONTROL
3158 jobctl = 0;
3159#endif
3160 }
3161
3162 /* from options.c: */
3163 {
3164 int i;
3165
3166 for (i = 0; i < NOPTS; i++)
3167 optent_val(i) = 0;
3168 optschanged();
3169
3170 }
3171
3172 /* from redir.c: */
3173 {
3174 clearredir();
3175 }
3176
3177 /* from trap.c: */
3178 {
3179 char *sm;
3180
3181 clear_traps();
3182 for (sm = sigmode; sm < sigmode + NSIG - 1; sm++) {
3183 if (*sm == S_IGN)
3184 *sm = S_HARD_IGN;
3185 }
3186 }
3187
3188 /* from var.c: */
3189 {
3190 shprocvar();
3191 }
3192}
3193
3194static int preadbuffer(void); 3114static int preadbuffer(void);
3195static void pushfile(void); 3115static void pushfile(void);
3196 3116
@@ -3326,7 +3246,7 @@ static void setinputfile(const char *fname, int push)
3326 3246
3327static void tryexec(char *cmd, char **argv, char **envp) 3247static void tryexec(char *cmd, char **argv, char **envp)
3328{ 3248{
3329 int e; 3249 int repeated = 0;
3330 3250
3331#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL 3251#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3332 char *name = cmd; 3252 char *name = cmd;
@@ -3344,17 +3264,21 @@ static void tryexec(char *cmd, char **argv, char **envp)
3344 optind = 1; 3264 optind = 1;
3345 run_applet_by_name(name, argc_l, argv); 3265 run_applet_by_name(name, argc_l, argv);
3346#endif 3266#endif
3267 repeat:
3347 execve(cmd, argv, envp); 3268 execve(cmd, argv, envp);
3348 e = errno; 3269 if (repeated++) {
3349 if (e == ENOEXEC) { 3270 free(argv);
3350 INTOFF; 3271 } else if (errno == ENOEXEC) {
3351 initshellproc(); 3272 char **ap;
3352 setinputfile(cmd, 0); 3273 char **new;
3353 commandname = arg0 = xstrdup(argv[0]); 3274
3354 setparam(argv + 1); 3275 for (ap = argv; *ap; ap++);
3355 exraise(EXSHELLPROC); 3276 ap = new = xmalloc((ap - argv + 2) * sizeof(char *));
3277 *ap++ = cmd = "/bin/sh";
3278 while ((*ap++ = *argv++));
3279 argv = new;
3280 goto repeat;
3356 } 3281 }
3357 errno = e;
3358} 3282}
3359 3283
3360static char *commandtext(const union node *); 3284static char *commandtext(const union node *);
@@ -3430,7 +3354,6 @@ static const char *const *findkwd(const char *s)
3430 3354
3431/*** Command hashing code ***/ 3355/*** Command hashing code ***/
3432 3356
3433
3434static int hashcmd(int argc, char **argv) 3357static int hashcmd(int argc, char **argv)
3435{ 3358{
3436 struct tblentry **pp; 3359 struct tblentry **pp;
@@ -3766,17 +3689,12 @@ find_command(const char *name, struct cmdentry *entry, int act,
3766 * Search the table of builtin commands. 3689 * Search the table of builtin commands.
3767 */ 3690 */
3768 3691
3769static int bstrcmp(const void *name, const void *b)
3770{
3771 return strcmp((const char *) name, (*(const char *const *) b) + 1);
3772}
3773
3774static struct builtincmd *find_builtin(const char *name) 3692static struct builtincmd *find_builtin(const char *name)
3775{ 3693{
3776 struct builtincmd *bp; 3694 struct builtincmd *bp;
3777 3695
3778 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd), 3696 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
3779 bstrcmp); 3697 pstrcmp);
3780 return bp; 3698 return bp;
3781} 3699}
3782 3700
@@ -3786,7 +3704,7 @@ static struct builtincmd *find_builtin(const char *name)
3786 * are executed they will be rehashed. 3704 * are executed they will be rehashed.
3787 */ 3705 */
3788 3706
3789static inline void hashcd(void) 3707static void hashcd(void)
3790{ 3708{
3791 struct tblentry **pp; 3709 struct tblentry **pp;
3792 struct tblentry *cmdp; 3710 struct tblentry *cmdp;
@@ -3853,34 +3771,6 @@ static void clearcmdentry(int firstchange)
3853 3771
3854 3772
3855/* 3773/*
3856 * Delete all functions.
3857 */
3858
3859static void deletefuncs(void)
3860{
3861 struct tblentry **tblp;
3862 struct tblentry **pp;
3863 struct tblentry *cmdp;
3864
3865 INTOFF;
3866 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
3867 pp = tblp;
3868 while ((cmdp = *pp) != NULL) {
3869 if (cmdp->cmdtype == CMDFUNCTION) {
3870 *pp = cmdp->next;
3871 free(cmdp->param.func);
3872 free(cmdp);
3873 } else {
3874 pp = &cmdp->next;
3875 }
3876 }
3877 }
3878 INTON;
3879}
3880
3881
3882
3883/*
3884 * Locate a command in the command hash table. If "add" is nonzero, 3774 * Locate a command in the command hash table. If "add" is nonzero,
3885 * add the command to the table if it is not already present. The 3775 * add the command to the table if it is not already present. The
3886 * variable "lastcmdentry" is set to point to the address of the link 3776 * variable "lastcmdentry" is set to point to the address of the link
@@ -3926,7 +3816,7 @@ static struct tblentry *cmdlookup(const char *name, int add)
3926 * Delete the command entry returned on the last lookup. 3816 * Delete the command entry returned on the last lookup.
3927 */ 3817 */
3928 3818
3929static void delete_cmd_entry() 3819static void delete_cmd_entry(void)
3930{ 3820{
3931 struct tblentry *cmdp; 3821 struct tblentry *cmdp;
3932 3822
@@ -4117,7 +4007,7 @@ static void expbackq(union node *, int, int);
4117static int subevalvar(char *, char *, int, int, int, int, int); 4007static int subevalvar(char *, char *, int, int, int, int, int);
4118static int varisset(char *, int); 4008static int varisset(char *, int);
4119static void strtodest(const char *, int, int); 4009static void strtodest(const char *, int, int);
4120static inline void varvalue(char *, int, int); 4010static void varvalue(char *, int, int);
4121static void recordregion(int, int, int); 4011static void recordregion(int, int, int);
4122static void removerecordregions(int); 4012static void removerecordregions(int);
4123static void ifsbreakup(char *, struct arglist *); 4013static void ifsbreakup(char *, struct arglist *);
@@ -4127,7 +4017,7 @@ static void expandmeta(struct strlist *, int);
4127#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) 4017#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4128#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB) 4018#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4129#if !defined(GLOB_BROKEN) 4019#if !defined(GLOB_BROKEN)
4130static inline void addglob(const glob_t *); 4020static void addglob(const glob_t *);
4131#endif 4021#endif
4132#endif 4022#endif
4133#if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) 4023#if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
@@ -4431,7 +4321,6 @@ static void argstr(char *p, int flag)
4431 STPUTC(c, expdest); 4321 STPUTC(c, expdest);
4432 } 4322 }
4433 } 4323 }
4434 return;
4435} 4324}
4436 4325
4437static char *exptilde(char *p, int flag) 4326static char *exptilde(char *p, int flag)
@@ -4573,7 +4462,6 @@ static void expari(int flag)
4573 error("syntax error: \"%s\"\n", p + 2); 4462 error("syntax error: \"%s\"\n", p + 2);
4574 } 4463 }
4575 snprintf(p, 12, "%d", result); 4464 snprintf(p, 12, "%d", result);
4576
4577 while (*p++); 4465 while (*p++);
4578 4466
4579 if (quoted == 0) 4467 if (quoted == 0)
@@ -4857,7 +4745,7 @@ static void strtodest(const char *p, int syntax, int quotes)
4857 * Add the value of a specialized variable to the stack string. 4745 * Add the value of a specialized variable to the stack string.
4858 */ 4746 */
4859 4747
4860static inline void varvalue(char *name, int quoted, int flags) 4748static void varvalue(char *name, int quoted, int flags)
4861{ 4749{
4862 int num; 4750 int num;
4863 char *p; 4751 char *p;
@@ -5059,9 +4947,10 @@ static void ifsfree(void)
5059static void addfname(const char *name) 4947static void addfname(const char *name)
5060{ 4948{
5061 struct strlist *sp; 4949 struct strlist *sp;
4950 size_t len = strlen(name) + 1;
5062 4951
5063 sp = (struct strlist *) stalloc(sizeof *sp); 4952 sp = (struct strlist *) stalloc(sizeof *sp);
5064 sp->text = sstrdup(name); 4953 sp->text = memcpy(stalloc(len), name, len);
5065 *exparg.lastp = sp; 4954 *exparg.lastp = sp;
5066 exparg.lastp = &sp->next; 4955 exparg.lastp = &sp->next;
5067} 4956}
@@ -5113,7 +5002,7 @@ static void expandmeta(struct strlist *str, int flag)
5113 * Add the result of glob(3) to the list. 5002 * Add the result of glob(3) to the list.
5114 */ 5003 */
5115 5004
5116static inline void addglob(const glob_t * pglob) 5005static void addglob(const glob_t * pglob)
5117{ 5006{
5118 char **p = pglob->gl_pathv; 5007 char **p = pglob->gl_pathv;
5119 5008
@@ -5704,8 +5593,7 @@ static void reset(void)
5704 5593
5705 /* from input.c: */ 5594 /* from input.c: */
5706 { 5595 {
5707 if (exception != EXSHELLPROC) 5596 parselleft = parsenleft = 0; /* clear input buffer */
5708 parselleft = parsenleft = 0; /* clear input buffer */
5709 popallfiles(); 5597 popallfiles();
5710 } 5598 }
5711 5599
@@ -6014,7 +5902,6 @@ static void restartjob(struct job *);
6014static void freejob(struct job *); 5902static void freejob(struct job *);
6015static struct job *getjob(const char *); 5903static struct job *getjob(const char *);
6016static int dowait(int, struct job *); 5904static int dowait(int, struct job *);
6017static void waitonint(int);
6018 5905
6019 5906
6020/* 5907/*
@@ -6045,20 +5932,12 @@ static void dupredirect(const union node *, int, int fd1dup);
6045 5932
6046static void setjobctl(int enable) 5933static void setjobctl(int enable)
6047{ 5934{
6048#ifdef OLD_TTY_DRIVER
6049 int ldisc;
6050#endif
6051
6052 if (enable == jobctl || rootshell == 0) 5935 if (enable == jobctl || rootshell == 0)
6053 return; 5936 return;
6054 if (enable) { 5937 if (enable) {
6055 do { /* while we are in the background */ 5938 do { /* while we are in the background */
6056#ifdef OLD_TTY_DRIVER
6057 if (ioctl(2, TIOCGPGRP, (char *) &initialpgrp) < 0) {
6058#else
6059 initialpgrp = tcgetpgrp(2); 5939 initialpgrp = tcgetpgrp(2);
6060 if (initialpgrp < 0) { 5940 if (initialpgrp < 0) {
6061#endif
6062 out2str("sh: can't access tty; job control turned off\n"); 5941 out2str("sh: can't access tty; job control turned off\n");
6063 mflag = 0; 5942 mflag = 0;
6064 return; 5943 return;
@@ -6070,30 +5949,14 @@ static void setjobctl(int enable)
6070 continue; 5949 continue;
6071 } 5950 }
6072 } while (0); 5951 } while (0);
6073#ifdef OLD_TTY_DRIVER
6074 if (ioctl(2, TIOCGETD, (char *) &ldisc) < 0 || ldisc != NTTYDISC) {
6075 out2str
6076 ("sh: need new tty driver to run job control; job control turned off\n");
6077 mflag = 0;
6078 return;
6079 }
6080#endif
6081 setsignal(SIGTSTP); 5952 setsignal(SIGTSTP);
6082 setsignal(SIGTTOU); 5953 setsignal(SIGTTOU);
6083 setsignal(SIGTTIN); 5954 setsignal(SIGTTIN);
6084 setpgid(0, rootpid); 5955 setpgid(0, rootpid);
6085#ifdef OLD_TTY_DRIVER
6086 ioctl(2, TIOCSPGRP, (char *) &rootpid);
6087#else
6088 tcsetpgrp(2, rootpid); 5956 tcsetpgrp(2, rootpid);
6089#endif
6090 } else { /* turning job control off */ 5957 } else { /* turning job control off */
6091 setpgid(0, initialpgrp); 5958 setpgid(0, initialpgrp);
6092#ifdef OLD_TTY_DRIVER
6093 ioctl(2, TIOCSPGRP, (char *) &initialpgrp);
6094#else
6095 tcsetpgrp(2, initialpgrp); 5959 tcsetpgrp(2, initialpgrp);
6096#endif
6097 setsignal(SIGTSTP); 5960 setsignal(SIGTSTP);
6098 setsignal(SIGTTOU); 5961 setsignal(SIGTTOU);
6099 setsignal(SIGTTIN); 5962 setsignal(SIGTTIN);
@@ -6196,11 +6059,7 @@ static int fgcmd(int argc, char **argv)
6196 if (jp->jobctl == 0) 6059 if (jp->jobctl == 0)
6197 error("job not created under job control"); 6060 error("job not created under job control");
6198 pgrp = jp->ps[0].pid; 6061 pgrp = jp->ps[0].pid;
6199#ifdef OLD_TTY_DRIVER
6200 ioctl(2, TIOCSPGRP, (char *) &pgrp); 6062 ioctl(2, TIOCSPGRP, (char *) &pgrp);
6201#else
6202 tcsetpgrp(2, pgrp);
6203#endif
6204 restartjob(jp); 6063 restartjob(jp);
6205 status = waitforjob(jp); 6064 status = waitforjob(jp);
6206 return status; 6065 return status;
@@ -6566,13 +6425,8 @@ static int forkshell(struct job *jp, const union node *n, int mode)
6566 setpgid(0, pgrp); 6425 setpgid(0, pgrp);
6567 if (mode == FORK_FG) { 6426 if (mode == FORK_FG) {
6568 /*** this causes superfluous TIOCSPGRPS ***/ 6427 /*** this causes superfluous TIOCSPGRPS ***/
6569#ifdef OLD_TTY_DRIVER
6570 if (ioctl(2, TIOCSPGRP, (char *) &pgrp) < 0)
6571 error("TIOCSPGRP failed, errno=%d", errno);
6572#else
6573 if (tcsetpgrp(2, pgrp) < 0) 6428 if (tcsetpgrp(2, pgrp) < 0)
6574 error("tcsetpgrp failed, errno=%d", errno); 6429 error("tcsetpgrp failed, errno=%d", errno);
6575#endif
6576 } 6430 }
6577 setsignal(SIGTSTP); 6431 setsignal(SIGTSTP);
6578 setsignal(SIGTTOU); 6432 setsignal(SIGTTOU);
@@ -6651,43 +6505,18 @@ static int waitforjob(struct job *jp)
6651#endif 6505#endif
6652 int status; 6506 int status;
6653 int st; 6507 int st;
6654 struct sigaction act, oact;
6655 6508
6656 INTOFF; 6509 INTOFF;
6657 intreceived = 0;
6658#ifdef CONFIG_ASH_JOB_CONTROL
6659 if (!jobctl) {
6660#else
6661 if (!iflag) {
6662#endif
6663 sigaction(SIGINT, 0, &act);
6664 act.sa_handler = waitonint;
6665 sigaction(SIGINT, &act, &oact);
6666 }
6667 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); 6510 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
6668 while (jp->state == 0) { 6511 while (jp->state == 0) {
6669 dowait(1, jp); 6512 dowait(1, jp);
6670 } 6513 }
6671#ifdef CONFIG_ASH_JOB_CONTROL 6514#ifdef CONFIG_ASH_JOB_CONTROL
6672 if (!jobctl) {
6673#else
6674 if (!iflag) {
6675#endif
6676 sigaction(SIGINT, &oact, 0);
6677 if (intreceived)
6678 kill(getpid(), SIGINT);
6679 }
6680#ifdef CONFIG_ASH_JOB_CONTROL
6681 if (jp->jobctl) { 6515 if (jp->jobctl) {
6682#ifdef OLD_TTY_DRIVER
6683 if (ioctl(2, TIOCSPGRP, (char *) &mypgrp) < 0)
6684 error("TIOCSPGRP failed, errno=%d\n", errno);
6685#else
6686 if (tcsetpgrp(2, mypgrp) < 0) 6516 if (tcsetpgrp(2, mypgrp) < 0)
6687 error("tcsetpgrp failed, errno=%d\n", errno); 6517 error("tcsetpgrp failed, errno=%d\n", errno);
6688#endif
6689 } 6518 }
6690 if (jp->state == CONFIG_ASH_JOB_CONTROLTOPPED) 6519 if (jp->state == JOBSTOPPED)
6691 curjob = jp - jobtab + 1; 6520 curjob = jp - jobtab + 1;
6692#endif 6521#endif
6693 status = jp->ps[jp->nprocs - 1].status; 6522 status = jp->ps[jp->nprocs - 1].status;
@@ -6804,7 +6633,7 @@ static int dowait(int block, struct job *job)
6804 done = 0; 6633 done = 0;
6805 } 6634 }
6806 if (stopped) { /* stopped or done */ 6635 if (stopped) { /* stopped or done */
6807 int state = done ? JOBDONE : CONFIG_ASH_JOB_CONTROLTOPPED; 6636 int state = done ? JOBDONE : JOBSTOPPED;
6808 6637
6809 if (jp->state != state) { 6638 if (jp->state != state) {
6810 TRACE(("Job %d: changing state from %d to %d\n", 6639 TRACE(("Job %d: changing state from %d to %d\n",
@@ -6873,7 +6702,7 @@ static int stoppedjobs(void)
6873 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { 6702 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
6874 if (jp->used == 0) 6703 if (jp->used == 0)
6875 continue; 6704 continue;
6876 if (jp->state == CONFIG_ASH_JOB_CONTROLTOPPED) { 6705 if (jp->state == JOBSTOPPED) {
6877 out2str("You have stopped jobs.\n"); 6706 out2str("You have stopped jobs.\n");
6878 job_warning = 2; 6707 job_warning = 2;
6879 return (1); 6708 return (1);
@@ -7301,11 +7130,6 @@ static char *commandtext(const union node *n)
7301} 7130}
7302 7131
7303 7132
7304static void waitonint(int sig)
7305{
7306 intreceived = 1;
7307}
7308
7309#ifdef CONFIG_ASH_MAIL 7133#ifdef CONFIG_ASH_MAIL
7310 7134
7311/* 7135/*
@@ -7493,7 +7317,7 @@ int ash_main(int argc, char **argv)
7493 SIGPIPE 7317 SIGPIPE
7494 }; 7318 };
7495 7319
7496#define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */ 7320#define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])))
7497 int i; 7321 int i;
7498 7322
7499 for (i = 0; i < SIGSSIZE; i++) 7323 for (i = 0; i < SIGSSIZE; i++)
@@ -8343,25 +8167,13 @@ static char *single_quote(const char *s)
8343} 8167}
8344 8168
8345/* 8169/*
8346 * Like strdup but works with the ash stack.
8347 */
8348
8349static char *sstrdup(const char *p)
8350{
8351 size_t len = strlen(p) + 1;
8352
8353 return memcpy(stalloc(len), p, len);
8354}
8355
8356
8357/*
8358 * Routine for dealing with parsed shell commands. 8170 * Routine for dealing with parsed shell commands.
8359 */ 8171 */
8360 8172
8361 8173
8362static void sizenodelist(const struct nodelist *); 8174static void sizenodelist(const struct nodelist *);
8363static struct nodelist *copynodelist(const struct nodelist *); 8175static struct nodelist *copynodelist(const struct nodelist *);
8364static char *nodexstrdup(const char *); 8176static char *nodesavestr(const char *);
8365 8177
8366#define CALCSIZE_TABLE 8178#define CALCSIZE_TABLE
8367#define COPYNODE_TABLE 8179#define COPYNODE_TABLE
@@ -8502,7 +8314,7 @@ static union node *copynode(const union node *n)
8502 if (!(*p & NODE_MBRMASK)) { /* standard node */ 8314 if (!(*p & NODE_MBRMASK)) { /* standard node */
8503 *((union node **) nn) = copynode(*((const union node **) no)); 8315 *((union node **) nn) = copynode(*((const union node **) no));
8504 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */ 8316 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8505 *((const char **) nn) = nodexstrdup(*((const char **) no)); 8317 *((const char **) nn) = nodesavestr(*((const char **) no));
8506 } else if (*p & NODE_NODELIST) { /* nodelist */ 8318 } else if (*p & NODE_NODELIST) { /* nodelist */
8507 *((struct nodelist **) nn) 8319 *((struct nodelist **) nn)
8508 = copynodelist(*((const struct nodelist **) no)); 8320 = copynodelist(*((const struct nodelist **) no));
@@ -8552,7 +8364,7 @@ static union node *copynode(const union node *n)
8552 new->nif.test = copynode(n->nif.test); 8364 new->nif.test = copynode(n->nif.test);
8553 break; 8365 break;
8554 case NFOR: 8366 case NFOR:
8555 new->nfor.var = nodexstrdup(n->nfor.var); 8367 new->nfor.var = nodesavestr(n->nfor.var);
8556 new->nfor.body = copynode(n->nfor.body); 8368 new->nfor.body = copynode(n->nfor.body);
8557 new->nfor.args = copynode(n->nfor.args); 8369 new->nfor.args = copynode(n->nfor.args);
8558 break; 8370 break;
@@ -8568,7 +8380,7 @@ static union node *copynode(const union node *n)
8568 case NDEFUN: 8380 case NDEFUN:
8569 case NARG: 8381 case NARG:
8570 new->narg.backquote = copynodelist(n->narg.backquote); 8382 new->narg.backquote = copynodelist(n->narg.backquote);
8571 new->narg.text = nodexstrdup(n->narg.text); 8383 new->narg.text = nodesavestr(n->narg.text);
8572 new->narg.next = copynode(n->narg.next); 8384 new->narg.next = copynode(n->narg.next);
8573 break; 8385 break;
8574 case NTO: 8386 case NTO:
@@ -8731,7 +8543,7 @@ static struct nodelist *copynodelist(const struct nodelist *lp)
8731} 8543}
8732 8544
8733 8545
8734static char *nodexstrdup(const char *s) 8546static char *nodesavestr(const char *s)
8735{ 8547{
8736 const char *p = s; 8548 const char *p = s;
8737 char *q = funcstring; 8549 char *q = funcstring;
@@ -8866,7 +8678,7 @@ static void options(int cmdline)
8866 minus_o(*argptr, val); 8678 minus_o(*argptr, val);
8867 if (*argptr) 8679 if (*argptr)
8868 argptr++; 8680 argptr++;
8869 } else if (cmdline && (c == '-')) { /* long options */ 8681 } else if (cmdline && (c == '-')) { // long options
8870 if (strcmp(p, "login") == 0) 8682 if (strcmp(p, "login") == 0)
8871 isloginsh = 1; 8683 isloginsh = 1;
8872 break; 8684 break;
@@ -11013,12 +10825,14 @@ static void redirect(union node *redir, int flags)
11013{ 10825{
11014 union node *n; 10826 union node *n;
11015 struct redirtab *sv = NULL; 10827 struct redirtab *sv = NULL;
11016 int i = EMPTY; 10828 int i;
11017 int fd; 10829 int fd;
11018 int newfd; 10830 int newfd;
11019 int try; 10831 int try;
11020 int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */ 10832 int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11021 10833
10834 TRACE(("redirect(%s) called\n",
10835 flags & REDIR_PUSH ? "REDIR_PUSH" : "NO_REDIR_PUSH"));
11022 if (flags & REDIR_PUSH) { 10836 if (flags & REDIR_PUSH) {
11023 sv = xmalloc(sizeof(struct redirtab)); 10837 sv = xmalloc(sizeof(struct redirtab));
11024 for (i = 0; i < 10; i++) 10838 for (i = 0; i < 10; i++)
@@ -11167,6 +10981,7 @@ static int dup_as_newfd(int from, int to)
11167/* 10981/*
11168 * Debugging stuff. 10982 * Debugging stuff.
11169 */ 10983 */
10984
11170static void shtree(union node *, int, char *, FILE *); 10985static void shtree(union node *, int, char *, FILE *);
11171static void shcmd(union node *, FILE *); 10986static void shcmd(union node *, FILE *);
11172static void sharg(union node *, FILE *); 10987static void sharg(union node *, FILE *);
@@ -11174,13 +10989,13 @@ static void indent(int, char *, FILE *);
11174static void trstring(char *); 10989static void trstring(char *);
11175 10990
11176 10991
11177static void showtree(n) 10992#if 0
11178 unode *n; 10993static void showtree(node * n)
11179{ 10994{
11180 trputs("showtree called\n"); 10995 trputs("showtree called\n");
11181 shtree(n, 1, NULL, stdout); 10996 shtree(n, 1, NULL, stdout);
11182} 10997}
11183 10998#endif
11184 10999
11185static void shtree(union node *n, int ind, char *pfx, FILE * fp) 11000static void shtree(union node *n, int ind, char *pfx, FILE * fp)
11186{ 11001{
@@ -11231,7 +11046,6 @@ static void shtree(union node *n, int ind, char *pfx, FILE * fp)
11231} 11046}
11232 11047
11233 11048
11234
11235static void shcmd(union node *cmd, FILE * fp) 11049static void shcmd(union node *cmd, FILE * fp)
11236{ 11050{
11237 union node *np; 11051 union node *np;
@@ -11306,6 +11120,7 @@ static void shcmd(union node *cmd, FILE * fp)
11306 } 11120 }
11307} 11121}
11308 11122
11123
11309static void sharg(union node *arg, FILE * fp) 11124static void sharg(union node *arg, FILE * fp)
11310{ 11125{
11311 char *p; 11126 char *p;
@@ -11401,7 +11216,6 @@ static void indent(int amount, char *pfx, FILE * fp)
11401 } 11216 }
11402} 11217}
11403 11218
11404
11405FILE *tracefile; 11219FILE *tracefile;
11406 11220
11407#if DEBUG == 2 11221#if DEBUG == 2
@@ -11610,10 +11424,6 @@ static int trapcmd(int argc, char **argv)
11610} 11424}
11611 11425
11612 11426
11613
11614
11615
11616
11617/* 11427/*
11618 * Set the signal handler for the specified signal. The routine figures 11428 * Set the signal handler for the specified signal. The routine figures
11619 * out what it should be set to. 11429 * out what it should be set to.
@@ -11819,7 +11629,7 @@ static void initvar()
11819 * PS1 depends on uid 11629 * PS1 depends on uid
11820 */ 11630 */
11821 if ((vps1.flags & VEXPORT) == 0) { 11631 if ((vps1.flags & VEXPORT) == 0) {
11822 vpp = hashvar("PS1=$"); 11632 vpp = hashvar("PS1=$ ");
11823 vps1.next = *vpp; 11633 vps1.next = *vpp;
11824 *vpp = &vps1; 11634 *vpp = &vps1;
11825 vps1.text = xstrdup(geteuid()? "PS1=$ " : "PS1=# "); 11635 vps1.text = xstrdup(geteuid()? "PS1=$ " : "PS1=# ");
@@ -12013,39 +11823,6 @@ static char **environment()
12013 11823
12014 11824
12015/* 11825/*
12016 * Called when a shell procedure is invoked to clear out nonexported
12017 * variables. It is also necessary to reallocate variables of with
12018 * VSTACK set since these are currently allocated on the stack.
12019 */
12020
12021static void shprocvar(void)
12022{
12023 struct var **vpp;
12024 struct var *vp, **prev;
12025
12026 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
12027 for (prev = vpp; (vp = *prev) != NULL;) {
12028 if ((vp->flags & VEXPORT) == 0) {
12029 *prev = vp->next;
12030 if ((vp->flags & VTEXTFIXED) == 0)
12031 free(vp->text);
12032 if ((vp->flags & VSTRFIXED) == 0)
12033 free(vp);
12034 } else {
12035 if (vp->flags & VSTACK) {
12036 vp->text = xstrdup(vp->text);
12037 vp->flags &= ~VSTACK;
12038 }
12039 prev = &vp->next;
12040 }
12041 }
12042 }
12043 initvar();
12044}
12045
12046
12047
12048/*
12049 * Command to list all variables which are set. Currently this command 11826 * Command to list all variables which are set. Currently this command
12050 * is invoked from the set command when the set command is called without 11827 * is invoked from the set command when the set command is called without
12051 * any variables. 11828 * any variables.
@@ -12335,7 +12112,6 @@ static struct var **findvar(struct var **vpp, const char *name)
12335/* 12112/*
12336 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 12113 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12337 * This file contains code for the times builtin. 12114 * This file contains code for the times builtin.
12338 * $Id: ash.c,v 1.57 2002/08/22 18:30:15 bug1 Exp $
12339 */ 12115 */
12340static int timescmd(int argc, char **argv) 12116static int timescmd(int argc, char **argv)
12341{ 12117{