diff options
| author | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2002-08-23 13:14:48 +0000 |
|---|---|---|
| committer | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2002-08-23 13:14:48 +0000 |
| commit | a29c97501e4e60af077f9a74984061c8de4ccccb (patch) | |
| tree | 8bc85cb977beca060f7eefc8bf395b3e8dfdfca0 /shell | |
| parent | 133e009b7809b0a8f86ce9cbfbbc2355e82c0cf4 (diff) | |
| download | busybox-w32-a29c97501e4e60af077f9a74984061c8de4ccccb.tar.gz busybox-w32-a29c97501e4e60af077f9a74984061c8de4ccccb.tar.bz2 busybox-w32-a29c97501e4e60af077f9a74984061c8de4ccccb.zip | |
Apply vodz last_path_51-2
git-svn-id: svn://busybox.net/trunk/busybox@5361 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 566 |
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); | |||
| 267 | static void ungrabstackstr(char *, char *); | 267 | static void ungrabstackstr(char *, char *); |
| 268 | static char *growstackstr(void); | 268 | static char *growstackstr(void); |
| 269 | static char *makestrspace(size_t newlen); | 269 | static char *makestrspace(size_t newlen); |
| 270 | static 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 |
| 317 | typedef union node unode; | 315 | typedef 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 | ||
| 678 | static const char S_I_T[][4] = { | 676 | static 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); | |||
| 1107 | static void dotrap(void); | 1090 | static void dotrap(void); |
| 1108 | static int decode_signal(const char *, int); | 1091 | static int decode_signal(const char *, int); |
| 1109 | 1092 | ||
| 1110 | static void shprocvar(void); | ||
| 1111 | static void deletefuncs(void); | ||
| 1112 | static void setparam(char **); | 1093 | static void setparam(char **); |
| 1113 | static void freeparam(volatile struct shparam *); | 1094 | static void freeparam(volatile struct shparam *); |
| 1114 | 1095 | ||
| 1115 | static void find_command(const char *, struct cmdentry *, int, const char *); | ||
| 1116 | |||
| 1117 | static 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); | |||
| 1583 | struct builtincmd { | 1560 | struct 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; | |||
| 1660 | static struct builtincmd *EVALCMD; | 1637 | static 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 */ | |||
| 1708 | static int curjob; /* current job */ | 1685 | static int curjob; /* current job */ |
| 1709 | static int jobctl; | 1686 | static int jobctl; |
| 1710 | #endif | 1687 | #endif |
| 1711 | static int intreceived; | ||
| 1712 | 1688 | ||
| 1713 | static struct job *makejob(const union node *, int); | 1689 | static struct job *makejob(const union node *, int); |
| 1714 | static int forkshell(struct job *, const union node *, int); | 1690 | static 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 | |||
| 1753 | static void hashcd(void); | ||
| 1754 | |||
| 1755 | static 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 | ||
| 1867 | static struct jmploc *handler; | 1855 | static struct jmploc *handler; |
| 1868 | static int exception; | 1856 | static 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 | ||
| 2102 | static void evalsubshell(const union node *, int); | 2089 | static void evalsubshell(const union node *, int); |
| 2103 | static void expredir(union node *); | 2090 | static void expredir(union node *); |
| 2091 | static void prehash(union node *); | ||
| 2104 | static void eprintlist(struct strlist *); | 2092 | static void eprintlist(struct strlist *); |
| 2105 | 2093 | ||
| 2106 | static union node *parsecmd(int); | 2094 | static 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 | ||
| 2317 | static inline void evalpipe(union node *n) | 2307 | static 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 | ||
| 2359 | static void find_command(const char *, struct cmdentry *, int, const char *); | ||
| 2360 | |||
| 2390 | static int isassignment(const char *word) | 2361 | static 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 | ||
| 2819 | static void evalsubshell(const union node *n, int flags) | 2777 | static 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 | |||
| 2896 | static 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 | ||
| 3135 | static 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 | |||
| 3194 | static int preadbuffer(void); | 3114 | static int preadbuffer(void); |
| 3195 | static void pushfile(void); | 3115 | static void pushfile(void); |
| 3196 | 3116 | ||
| @@ -3326,7 +3246,7 @@ static void setinputfile(const char *fname, int push) | |||
| 3326 | 3246 | ||
| 3327 | static void tryexec(char *cmd, char **argv, char **envp) | 3247 | static 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 | ||
| 3360 | static char *commandtext(const union node *); | 3284 | static 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 | |||
| 3434 | static int hashcmd(int argc, char **argv) | 3357 | static 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 | ||
| 3769 | static int bstrcmp(const void *name, const void *b) | ||
| 3770 | { | ||
| 3771 | return strcmp((const char *) name, (*(const char *const *) b) + 1); | ||
| 3772 | } | ||
| 3773 | |||
| 3774 | static struct builtincmd *find_builtin(const char *name) | 3692 | static 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 | ||
| 3789 | static inline void hashcd(void) | 3707 | static 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 | |||
| 3859 | static 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 | ||
| 3929 | static void delete_cmd_entry() | 3819 | static 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); | |||
| 4117 | static int subevalvar(char *, char *, int, int, int, int, int); | 4007 | static int subevalvar(char *, char *, int, int, int, int, int); |
| 4118 | static int varisset(char *, int); | 4008 | static int varisset(char *, int); |
| 4119 | static void strtodest(const char *, int, int); | 4009 | static void strtodest(const char *, int, int); |
| 4120 | static inline void varvalue(char *, int, int); | 4010 | static void varvalue(char *, int, int); |
| 4121 | static void recordregion(int, int, int); | 4011 | static void recordregion(int, int, int); |
| 4122 | static void removerecordregions(int); | 4012 | static void removerecordregions(int); |
| 4123 | static void ifsbreakup(char *, struct arglist *); | 4013 | static 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) |
| 4130 | static inline void addglob(const glob_t *); | 4020 | static 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 | ||
| 4437 | static char *exptilde(char *p, int flag) | 4326 | static 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 | ||
| 4860 | static inline void varvalue(char *name, int quoted, int flags) | 4748 | static 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) | |||
| 5059 | static void addfname(const char *name) | 4947 | static 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 | ||
| 5116 | static inline void addglob(const glob_t * pglob) | 5005 | static 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 *); | |||
| 6014 | static void freejob(struct job *); | 5902 | static void freejob(struct job *); |
| 6015 | static struct job *getjob(const char *); | 5903 | static struct job *getjob(const char *); |
| 6016 | static int dowait(int, struct job *); | 5904 | static int dowait(int, struct job *); |
| 6017 | static void waitonint(int); | ||
| 6018 | 5905 | ||
| 6019 | 5906 | ||
| 6020 | /* | 5907 | /* |
| @@ -6045,20 +5932,12 @@ static void dupredirect(const union node *, int, int fd1dup); | |||
| 6045 | 5932 | ||
| 6046 | static void setjobctl(int enable) | 5933 | static 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 | ||
| 7304 | static 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 | |||
| 8349 | static 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 | ||
| 8362 | static void sizenodelist(const struct nodelist *); | 8174 | static void sizenodelist(const struct nodelist *); |
| 8363 | static struct nodelist *copynodelist(const struct nodelist *); | 8175 | static struct nodelist *copynodelist(const struct nodelist *); |
| 8364 | static char *nodexstrdup(const char *); | 8176 | static 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 | ||
| 8734 | static char *nodexstrdup(const char *s) | 8546 | static 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 | |||
| 11170 | static void shtree(union node *, int, char *, FILE *); | 10985 | static void shtree(union node *, int, char *, FILE *); |
| 11171 | static void shcmd(union node *, FILE *); | 10986 | static void shcmd(union node *, FILE *); |
| 11172 | static void sharg(union node *, FILE *); | 10987 | static void sharg(union node *, FILE *); |
| @@ -11174,13 +10989,13 @@ static void indent(int, char *, FILE *); | |||
| 11174 | static void trstring(char *); | 10989 | static void trstring(char *); |
| 11175 | 10990 | ||
| 11176 | 10991 | ||
| 11177 | static void showtree(n) | 10992 | #if 0 |
| 11178 | unode *n; | 10993 | static 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 | ||
| 11185 | static void shtree(union node *n, int ind, char *pfx, FILE * fp) | 11000 | static 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 | |||
| 11235 | static void shcmd(union node *cmd, FILE * fp) | 11049 | static 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 | |||
| 11309 | static void sharg(union node *arg, FILE * fp) | 11124 | static 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 | |||
| 11405 | FILE *tracefile; | 11219 | FILE *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 | |||
| 12021 | static 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 | */ |
| 12340 | static int timescmd(int argc, char **argv) | 12116 | static int timescmd(int argc, char **argv) |
| 12341 | { | 12117 | { |
