diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2002-08-23 13:14:48 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2002-08-23 13:14:48 +0000 |
commit | 50812fff219a3d0b9eccb9ff9647d6d66a7934c7 (patch) | |
tree | 8bc85cb977beca060f7eefc8bf395b3e8dfdfca0 /shell | |
parent | de9e803149a6e3e2d8c7db03620dd94b48a55843 (diff) | |
download | busybox-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.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 | { |