aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 01:03:40 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 01:03:40 +0000
commit439c291be500b06d5052c1dc8507382bac8676cb (patch)
treedd28e83b8452df20cd13e8d83a5347741b977469 /shell
parent817ec0fbc18b22200c0cad5b5dbbb34c8c80ff56 (diff)
downloadbusybox-w32-439c291be500b06d5052c1dc8507382bac8676cb.tar.gz
busybox-w32-439c291be500b06d5052c1dc8507382bac8676cb.tar.bz2
busybox-w32-439c291be500b06d5052c1dc8507382bac8676cb.zip
ash: cleanup part 1
git-svn-id: svn://busybox.net/trunk/busybox@17953 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c1125
1 files changed, 539 insertions, 586 deletions
diff --git a/shell/ash.c b/shell/ash.c
index e262c0e13..379e8ab7f 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -503,6 +503,289 @@ errmsg(int e, const char *em)
503} 503}
504 504
505 505
506/* ============ Memory allocation */
507
508/*
509 * It appears that grabstackstr() will barf with such alignments
510 * because stalloc() will return a string allocated in a new stackblock.
511 */
512#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
513enum {
514 /* Most machines require the value returned from malloc to be aligned
515 * in some way. The following macro will get this right
516 * on many machines. */
517 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
518 /* Minimum size of a block */
519 MINSIZE = SHELL_ALIGN(504),
520};
521
522struct stack_block {
523 struct stack_block *prev;
524 char space[MINSIZE];
525};
526
527struct stackmark {
528 struct stack_block *stackp;
529 char *stacknxt;
530 size_t stacknleft;
531 struct stackmark *marknext;
532};
533
534static struct stack_block stackbase;
535static struct stack_block *stackp = &stackbase;
536static struct stackmark *markp;
537static char *stacknxt = stackbase.space;
538static size_t stacknleft = MINSIZE;
539static char *sstrend = stackbase.space + MINSIZE;
540static int herefd = -1;
541
542#define stackblock() ((void *)stacknxt)
543#define stackblocksize() stacknleft
544
545static void *
546ckrealloc(void * p, size_t nbytes)
547{
548 p = realloc(p, nbytes);
549 if (!p)
550 ash_msg_and_raise_error(bb_msg_memory_exhausted);
551 return p;
552}
553
554static void *
555ckmalloc(size_t nbytes)
556{
557 return ckrealloc(NULL, nbytes);
558}
559
560/*
561 * Make a copy of a string in safe storage.
562 */
563static char *
564ckstrdup(const char *s)
565{
566 char *p = strdup(s);
567 if (!p)
568 ash_msg_and_raise_error(bb_msg_memory_exhausted);
569 return p;
570}
571
572/*
573 * Parse trees for commands are allocated in lifo order, so we use a stack
574 * to make this more efficient, and also to avoid all sorts of exception
575 * handling code to handle interrupts in the middle of a parse.
576 *
577 * The size 504 was chosen because the Ultrix malloc handles that size
578 * well.
579 */
580static void *
581stalloc(size_t nbytes)
582{
583 char *p;
584 size_t aligned;
585
586 aligned = SHELL_ALIGN(nbytes);
587 if (aligned > stacknleft) {
588 size_t len;
589 size_t blocksize;
590 struct stack_block *sp;
591
592 blocksize = aligned;
593 if (blocksize < MINSIZE)
594 blocksize = MINSIZE;
595 len = sizeof(struct stack_block) - MINSIZE + blocksize;
596 if (len < blocksize)
597 ash_msg_and_raise_error(bb_msg_memory_exhausted);
598 INT_OFF;
599 sp = ckmalloc(len);
600 sp->prev = stackp;
601 stacknxt = sp->space;
602 stacknleft = blocksize;
603 sstrend = stacknxt + blocksize;
604 stackp = sp;
605 INT_ON;
606 }
607 p = stacknxt;
608 stacknxt += aligned;
609 stacknleft -= aligned;
610 return p;
611}
612
613static void
614stunalloc(void *p)
615{
616#if DEBUG
617 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
618 write(2, "stunalloc\n", 10);
619 abort();
620 }
621#endif
622 stacknleft += stacknxt - (char *)p;
623 stacknxt = p;
624}
625
626static void
627setstackmark(struct stackmark *mark)
628{
629 mark->stackp = stackp;
630 mark->stacknxt = stacknxt;
631 mark->stacknleft = stacknleft;
632 mark->marknext = markp;
633 markp = mark;
634}
635
636static void
637popstackmark(struct stackmark *mark)
638{
639 struct stack_block *sp;
640
641 INT_OFF;
642 markp = mark->marknext;
643 while (stackp != mark->stackp) {
644 sp = stackp;
645 stackp = sp->prev;
646 free(sp);
647 }
648 stacknxt = mark->stacknxt;
649 stacknleft = mark->stacknleft;
650 sstrend = mark->stacknxt + mark->stacknleft;
651 INT_ON;
652}
653
654/*
655 * When the parser reads in a string, it wants to stick the string on the
656 * stack and only adjust the stack pointer when it knows how big the
657 * string is. Stackblock (defined in stack.h) returns a pointer to a block
658 * of space on top of the stack and stackblocklen returns the length of
659 * this block. Growstackblock will grow this space by at least one byte,
660 * possibly moving it (like realloc). Grabstackblock actually allocates the
661 * part of the block that has been used.
662 */
663static void
664growstackblock(void)
665{
666 size_t newlen;
667
668 newlen = stacknleft * 2;
669 if (newlen < stacknleft)
670 ash_msg_and_raise_error(bb_msg_memory_exhausted);
671 if (newlen < 128)
672 newlen += 128;
673
674 if (stacknxt == stackp->space && stackp != &stackbase) {
675 struct stack_block *oldstackp;
676 struct stackmark *xmark;
677 struct stack_block *sp;
678 struct stack_block *prevstackp;
679 size_t grosslen;
680
681 INT_OFF;
682 oldstackp = stackp;
683 sp = stackp;
684 prevstackp = sp->prev;
685 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
686 sp = ckrealloc(sp, grosslen);
687 sp->prev = prevstackp;
688 stackp = sp;
689 stacknxt = sp->space;
690 stacknleft = newlen;
691 sstrend = sp->space + newlen;
692
693 /*
694 * Stack marks pointing to the start of the old block
695 * must be relocated to point to the new block
696 */
697 xmark = markp;
698 while (xmark != NULL && xmark->stackp == oldstackp) {
699 xmark->stackp = stackp;
700 xmark->stacknxt = stacknxt;
701 xmark->stacknleft = stacknleft;
702 xmark = xmark->marknext;
703 }
704 INT_ON;
705 } else {
706 char *oldspace = stacknxt;
707 int oldlen = stacknleft;
708 char *p = stalloc(newlen);
709
710 /* free the space we just allocated */
711 stacknxt = memcpy(p, oldspace, oldlen);
712 stacknleft += newlen;
713 }
714}
715
716static void
717grabstackblock(size_t len)
718{
719 len = SHELL_ALIGN(len);
720 stacknxt += len;
721 stacknleft -= len;
722}
723
724/*
725 * The following routines are somewhat easier to use than the above.
726 * The user declares a variable of type STACKSTR, which may be declared
727 * to be a register. The macro STARTSTACKSTR initializes things. Then
728 * the user uses the macro STPUTC to add characters to the string. In
729 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
730 * grown as necessary. When the user is done, she can just leave the
731 * string there and refer to it using stackblock(). Or she can allocate
732 * the space for it using grabstackstr(). If it is necessary to allow
733 * someone else to use the stack temporarily and then continue to grow
734 * the string, the user should use grabstack to allocate the space, and
735 * then call ungrabstr(p) to return to the previous mode of operation.
736 *
737 * USTPUTC is like STPUTC except that it doesn't check for overflow.
738 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
739 * is space for at least one character.
740 */
741static void *
742growstackstr(void)
743{
744 size_t len = stackblocksize();
745 if (herefd >= 0 && len >= 1024) {
746 full_write(herefd, stackblock(), len);
747 return stackblock();
748 }
749 growstackblock();
750 return stackblock() + len;
751}
752
753/*
754 * Called from CHECKSTRSPACE.
755 */
756static char *
757makestrspace(size_t newlen, char *p)
758{
759 size_t len = p - stacknxt;
760 size_t size = stackblocksize();
761
762 for (;;) {
763 size_t nleft;
764
765 size = stackblocksize();
766 nleft = size - len;
767 if (nleft >= newlen)
768 break;
769 growstackblock();
770 }
771 return stackblock() + len;
772}
773
774static char *
775stack_nputstr(const char *s, size_t n, char *p)
776{
777 p = makestrspace(n, p);
778 p = memcpy(p, s, n) + n;
779 return p;
780}
781
782static char *
783stack_putstr(const char *s, char *p)
784{
785 return stack_nputstr(s, strlen(s), p);
786}
787
788
506/* ============ Unsorted yet */ 789/* ============ Unsorted yet */
507 790
508 791
@@ -773,9 +1056,7 @@ static union node *redirnode;
773static struct heredoc *heredoc; 1056static struct heredoc *heredoc;
774static int quoteflag; /* set if (part of) last token was quoted */ 1057static int quoteflag; /* set if (part of) last token was quoted */
775 1058
776static union node *parsecmd(int);
777static void fixredir(union node *, const char *, int); 1059static void fixredir(union node *, const char *, int);
778static const char *const *findkwd(const char *);
779static char *endofname(const char *); 1060static char *endofname(const char *);
780 1061
781/* shell.h */ 1062/* shell.h */
@@ -867,7 +1148,8 @@ static const char *const tokname_array[] = {
867 "\1}", 1148 "\1}",
868}; 1149};
869 1150
870static const char *tokname(int tok) 1151static const char *
1152tokname(int tok)
871{ 1153{
872 static char buf[16]; 1154 static char buf[16];
873 1155
@@ -878,24 +1160,20 @@ static const char *tokname(int tok)
878 return buf; 1160 return buf;
879} 1161}
880 1162
881/* machdep.h */ 1163/* Wrapper around strcmp for qsort/bsearch/... */
882 1164static int
883/* 1165pstrcmp(const void *a, const void *b)
884 * Most machines require the value returned from malloc to be aligned 1166{
885 * in some way. The following macro will get this right on many machines. 1167 return strcmp((const char *) a, (*(const char *const *) b) + 1);
886 */ 1168}
887
888#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
889/*
890 * It appears that grabstackstr() will barf with such alignments
891 * because stalloc() will return a string allocated in a new stackblock.
892 */
893#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
894
895/*
896 * This file was generated by the mksyntax program.
897 */
898 1169
1170static const char *const *
1171findkwd(const char *s)
1172{
1173 return bsearch(s, tokname_array + KWDOFFSET,
1174 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
1175 sizeof(const char *), pstrcmp);
1176}
899 1177
900/* Syntax classes */ 1178/* Syntax classes */
901#define CWORD 0 /* character is nothing special */ 1179#define CWORD 0 /* character is nothing special */
@@ -1006,7 +1284,8 @@ static const char S_I_T[][3] = {
1006 1284
1007#define U_C(c) ((unsigned char)(c)) 1285#define U_C(c) ((unsigned char)(c))
1008 1286
1009static int SIT(int c, int syntax) 1287static int
1288SIT(int c, int syntax)
1010{ 1289{
1011 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~"; 1290 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
1012#if ENABLE_ASH_ALIAS 1291#if ENABLE_ASH_ALIAS
@@ -1392,13 +1671,8 @@ static void calcsize(union node *);
1392static void sizenodelist(struct nodelist *); 1671static void sizenodelist(struct nodelist *);
1393static union node *copynode(union node *); 1672static union node *copynode(union node *);
1394static struct nodelist *copynodelist(struct nodelist *); 1673static struct nodelist *copynodelist(struct nodelist *);
1395static char *nodesavestr(char *); 1674static char *nodeckstrdup(char *);
1396
1397 1675
1398static int evalstring(char *, int mask);
1399union node; /* BLETCH for ansi C */
1400static void evaltree(union node *, int);
1401static void evalbackcmd(union node *, struct backcmd *);
1402 1676
1403static int evalskip; /* set if we are skipping commands */ 1677static int evalskip; /* set if we are skipping commands */
1404static int skipcount; /* number of levels to skip */ 1678static int skipcount; /* number of levels to skip */
@@ -1637,16 +1911,16 @@ static void change_random(const char *);
1637# endif 1911# endif
1638#endif 1912#endif
1639 1913
1640/* init.h */
1641
1642static void reset(void);
1643
1644/* var.h */ 1914/* var.h */
1645 1915
1646/* 1916/*
1647 * Shell variables. 1917 * Shell variables.
1648 */ 1918 */
1649 1919
1920#if ENABLE_ASH_GETOPTS
1921static void getoptsreset(const char *);
1922#endif
1923
1650/* flags */ 1924/* flags */
1651#define VEXPORT 0x01 /* variable is exported */ 1925#define VEXPORT 0x01 /* variable is exported */
1652#define VREADONLY 0x02 /* variable cannot be modified */ 1926#define VREADONLY 0x02 /* variable cannot be modified */
@@ -1684,11 +1958,6 @@ static struct localvar *localvars;
1684/* 1958/*
1685 * Shell variables. 1959 * Shell variables.
1686 */ 1960 */
1687
1688#if ENABLE_ASH_GETOPTS
1689static void getoptsreset(const char *);
1690#endif
1691
1692#if ENABLE_LOCALE_SUPPORT 1961#if ENABLE_LOCALE_SUPPORT
1693static void change_lc_all(const char *value); 1962static void change_lc_all(const char *value);
1694static void change_lc_ctype(const char *value); 1963static void change_lc_ctype(const char *value);
@@ -1950,46 +2219,6 @@ static void showjobs(FILE *, int);
1950 2219
1951static void readcmdfile(char *); 2220static void readcmdfile(char *);
1952 2221
1953/* memalloc.h */
1954
1955
1956struct stackmark {
1957 struct stack_block *stackp;
1958 char *stacknxt;
1959 size_t stacknleft;
1960 struct stackmark *marknext;
1961};
1962
1963/* minimum size of a block */
1964#define MINSIZE SHELL_ALIGN(504)
1965
1966struct stack_block {
1967 struct stack_block *prev;
1968 char space[MINSIZE];
1969};
1970
1971static struct stack_block stackbase;
1972static struct stack_block *stackp = &stackbase;
1973static struct stackmark *markp;
1974static char *stacknxt = stackbase.space;
1975static size_t stacknleft = MINSIZE;
1976static char *sstrend = stackbase.space + MINSIZE;
1977static int herefd = -1;
1978
1979
1980static void *ckmalloc(size_t);
1981static void *ckrealloc(void *, size_t);
1982static char *savestr(const char *);
1983static void *stalloc(size_t);
1984static void stunalloc(void *);
1985static void setstackmark(struct stackmark *);
1986static void popstackmark(struct stackmark *);
1987static void growstackblock(void);
1988static void *growstackstr(void);
1989static char *makestrspace(size_t, char *);
1990static char *stnputs(const char *, size_t, char *);
1991static char *stputs(const char *, char *);
1992
1993 2222
1994static char *_STPUTC(int c, char *p) 2223static char *_STPUTC(int c, char *p)
1995{ 2224{
@@ -1999,8 +2228,6 @@ static char *_STPUTC(int c, char *p)
1999 return p; 2228 return p;
2000} 2229}
2001 2230
2002#define stackblock() ((void *)stacknxt)
2003#define stackblocksize() stacknleft
2004#define STARTSTACKSTR(p) ((p) = stackblock()) 2231#define STARTSTACKSTR(p) ((p) = stackblock())
2005#define STPUTC(c, p) ((p) = _STPUTC((c), (p))) 2232#define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
2006#define CHECKSTRSPACE(n, p) \ 2233#define CHECKSTRSPACE(n, p) \
@@ -2070,7 +2297,6 @@ static int nextopt(const char *);
2070#define REDIR_PUSH 01 /* save previous values of file descriptors */ 2297#define REDIR_PUSH 01 /* save previous values of file descriptors */
2071#define REDIR_SAVEFD2 03 /* set preverrout */ 2298#define REDIR_SAVEFD2 03 /* set preverrout */
2072 2299
2073union node;
2074static void redirect(union node *, int); 2300static void redirect(union node *, int);
2075static void popredir(int); 2301static void popredir(int);
2076static void clearredir(int); 2302static void clearredir(int);
@@ -2137,29 +2363,6 @@ static int is_safe_applet(char *name)
2137} 2363}
2138 2364
2139 2365
2140/*
2141 * This routine is called when an error or an interrupt occurs in an
2142 * interactive shell and control is returned to the main command loop.
2143 */
2144static void
2145reset(void)
2146{
2147 /* from eval.c: */
2148 evalskip = 0;
2149 loopnest = 0;
2150
2151 /* from input.c: */
2152 parselleft = parsenleft = 0; /* clear input buffer */
2153 popallfiles();
2154
2155 /* from parser.c: */
2156 tokpushback = 0;
2157 checkkwd = 0;
2158
2159 /* from redir.c: */
2160 clearredir(0);
2161}
2162
2163#if ENABLE_ASH_ALIAS 2366#if ENABLE_ASH_ALIAS
2164static struct alias *atab[ATABSIZE]; 2367static struct alias *atab[ATABSIZE];
2165 2368
@@ -2179,13 +2382,13 @@ setalias(const char *name, const char *val)
2179 if (!(ap->flag & ALIASINUSE)) { 2382 if (!(ap->flag & ALIASINUSE)) {
2180 free(ap->val); 2383 free(ap->val);
2181 } 2384 }
2182 ap->val = savestr(val); 2385 ap->val = ckstrdup(val);
2183 ap->flag &= ~ALIASDEAD; 2386 ap->flag &= ~ALIASDEAD;
2184 } else { 2387 } else {
2185 /* not found */ 2388 /* not found */
2186 ap = ckmalloc(sizeof(struct alias)); 2389 ap = ckmalloc(sizeof(struct alias));
2187 ap->name = savestr(name); 2390 ap->name = ckstrdup(name);
2188 ap->val = savestr(val); 2391 ap->val = ckstrdup(val);
2189 ap->flag = 0; 2392 ap->flag = 0;
2190 ap->next = 0; 2393 ap->next = 0;
2191 *app = ap; 2394 *app = ap;
@@ -2461,7 +2664,7 @@ static const char * updatepwd(const char *dir)
2461 if (*dir != '/') { 2664 if (*dir != '/') {
2462 if (curdir == nullstr) 2665 if (curdir == nullstr)
2463 return 0; 2666 return 0;
2464 new = stputs(curdir, new); 2667 new = stack_putstr(curdir, new);
2465 } 2668 }
2466 new = makestrspace(strlen(dir) + 2, new); 2669 new = makestrspace(strlen(dir) + 2, new);
2467 lim = stackblock() + 1; 2670 lim = stackblock() + 1;
@@ -2494,7 +2697,7 @@ static const char * updatepwd(const char *dir)
2494 break; 2697 break;
2495 /* fall through */ 2698 /* fall through */
2496 default: 2699 default:
2497 new = stputs(p, new); 2700 new = stack_putstr(p, new);
2498 USTPUTC('/', new); 2701 USTPUTC('/', new);
2499 } 2702 }
2500 p = strtok(0, "/"); 2703 p = strtok(0, "/");
@@ -2582,7 +2785,7 @@ setpwd(const char *val, int setold)
2582 if (!val) 2785 if (!val)
2583 dir = s; 2786 dir = s;
2584 } else 2787 } else
2585 dir = savestr(val); 2788 dir = ckstrdup(val);
2586 if (oldcur != dir && oldcur != nullstr) { 2789 if (oldcur != dir && oldcur != nullstr) {
2587 free(oldcur); 2790 free(oldcur);
2588 } 2791 }
@@ -2621,70 +2824,6 @@ static const struct builtincmd bltin = {
2621}; 2824};
2622 2825
2623 2826
2624/*
2625 * Called to reset things after an exception.
2626 */
2627
2628/*
2629 * The eval command.
2630 */
2631static int
2632evalcmd(int argc, char **argv)
2633{
2634 char *p;
2635 char *concat;
2636 char **ap;
2637
2638 if (argc > 1) {
2639 p = argv[1];
2640 if (argc > 2) {
2641 STARTSTACKSTR(concat);
2642 ap = argv + 2;
2643 for (;;) {
2644 concat = stputs(p, concat);
2645 p = *ap++;
2646 if (p == NULL)
2647 break;
2648 STPUTC(' ', concat);
2649 }
2650 STPUTC('\0', concat);
2651 p = grabstackstr(concat);
2652 }
2653 evalstring(p, ~SKIPEVAL);
2654
2655 }
2656 return exitstatus;
2657}
2658
2659
2660/*
2661 * Execute a command or commands contained in a string.
2662 */
2663static int
2664evalstring(char *s, int mask)
2665{
2666 union node *n;
2667 struct stackmark smark;
2668 int skip;
2669
2670 setinputstring(s);
2671 setstackmark(&smark);
2672
2673 skip = 0;
2674 while ((n = parsecmd(0)) != NEOF) {
2675 evaltree(n, 0);
2676 popstackmark(&smark);
2677 skip = evalskip;
2678 if (skip)
2679 break;
2680 }
2681 popfile();
2682
2683 skip &= mask;
2684 evalskip = skip;
2685 return skip;
2686}
2687
2688 2827
2689/* 2828/*
2690 * Evaluate a parse tree. The value is left in the global variable 2829 * Evaluate a parse tree. The value is left in the global variable
@@ -3993,15 +4132,6 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
3993 4132
3994 4133
3995/* 4134/*
3996 * Wrapper around strcmp for qsort/bsearch/...
3997 */
3998static int pstrcmp(const void *a, const void *b)
3999{
4000 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4001}
4002
4003
4004/*
4005 * Search the table of builtin commands. 4135 * Search the table of builtin commands.
4006 */ 4136 */
4007static struct builtincmd * 4137static struct builtincmd *
@@ -4606,7 +4736,7 @@ argstr(char *p, int flag)
4606 } 4736 }
4607 if (length > 0) { 4737 if (length > 0) {
4608 int newloc; 4738 int newloc;
4609 expdest = stnputs(p, length, expdest); 4739 expdest = stack_nputstr(p, length, expdest);
4610 newloc = expdest - (char *)stackblock(); 4740 newloc = expdest - (char *)stackblock();
4611 if (breakall && !inquotes && newloc > startloc) { 4741 if (breakall && !inquotes && newloc > startloc) {
4612 recordregion(startloc, newloc, 0); 4742 recordregion(startloc, newloc, 0);
@@ -7370,7 +7500,7 @@ commandtext(union node *n)
7370 name = stackblock(); 7500 name = stackblock();
7371 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n", 7501 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7372 name, cmdnextc, cmdnextc)); 7502 name, cmdnextc, cmdnextc));
7373 return savestr(name); 7503 return ckstrdup(name);
7374} 7504}
7375 7505
7376static void 7506static void
@@ -7753,79 +7883,11 @@ changemail(const char *val)
7753#endif /* ASH_MAIL */ 7883#endif /* ASH_MAIL */
7754 7884
7755/* 7885/*
7756 * Read and execute commands. "Top" is nonzero for the top level command
7757 * loop; it turns on prompting if the shell is interactive.
7758 */
7759static int
7760cmdloop(int top)
7761{
7762 union node *n;
7763 struct stackmark smark;
7764 int inter;
7765 int numeof = 0;
7766
7767 TRACE(("cmdloop(%d) called\n", top));
7768 for (;;) {
7769 int skip;
7770
7771 setstackmark(&smark);
7772#if JOBS
7773 if (jobctl)
7774 showjobs(stderr, SHOW_CHANGED);
7775#endif
7776 inter = 0;
7777 if (iflag && top) {
7778 inter++;
7779#if ENABLE_ASH_MAIL
7780 chkmail();
7781#endif
7782 }
7783 n = parsecmd(inter);
7784 /* showtree(n); DEBUG */
7785 if (n == NEOF) {
7786 if (!top || numeof >= 50)
7787 break;
7788 if (!stoppedjobs()) {
7789 if (!Iflag)
7790 break;
7791 out2str("\nUse \"exit\" to leave shell.\n");
7792 }
7793 numeof++;
7794 } else if (nflag == 0) {
7795 job_warning = (job_warning == 2) ? 1 : 0;
7796 numeof = 0;
7797 evaltree(n, 0);
7798 }
7799 popstackmark(&smark);
7800 skip = evalskip;
7801
7802 if (skip) {
7803 evalskip = 0;
7804 return skip & SKIPEVAL;
7805 }
7806 }
7807
7808 return 0;
7809}
7810
7811
7812/*
7813 * Read a file containing shell functions.
7814 */
7815static void
7816readcmdfile(char *name)
7817{
7818 setinputfile(name, INPUT_PUSH_FILE);
7819 cmdloop(0);
7820 popfile();
7821}
7822
7823
7824/*
7825 * Take commands from a file. To be compatible we should do a path 7886 * Take commands from a file. To be compatible we should do a path
7826 * search for the file, which is necessary to find sub-commands. 7887 * search for the file, which is necessary to find sub-commands.
7827 */ 7888 */
7828static char * find_dot_file(char *name) 7889static char *
7890find_dot_file(char *name)
7829{ 7891{
7830 char *fullname; 7892 char *fullname;
7831 const char *path = pathval(); 7893 const char *path = pathval();
@@ -7851,322 +7913,6 @@ static char * find_dot_file(char *name)
7851 /* NOTREACHED */ 7913 /* NOTREACHED */
7852} 7914}
7853 7915
7854static int dotcmd(int argc, char **argv)
7855{
7856 struct strlist *sp;
7857 volatile struct shparam saveparam;
7858 int status = 0;
7859
7860 for (sp = cmdenviron; sp; sp = sp->next)
7861 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
7862
7863 if (argc >= 2) { /* That's what SVR2 does */
7864 char *fullname;
7865
7866 fullname = find_dot_file(argv[1]);
7867
7868 if (argc > 2) {
7869 saveparam = shellparam;
7870 shellparam.malloc = 0;
7871 shellparam.nparam = argc - 2;
7872 shellparam.p = argv + 2;
7873 };
7874
7875 setinputfile(fullname, INPUT_PUSH_FILE);
7876 commandname = fullname;
7877 cmdloop(0);
7878 popfile();
7879
7880 if (argc > 2) {
7881 freeparam(&shellparam);
7882 shellparam = saveparam;
7883 };
7884 status = exitstatus;
7885 }
7886 return status;
7887}
7888
7889
7890static int
7891exitcmd(int argc, char **argv)
7892{
7893 if (stoppedjobs())
7894 return 0;
7895 if (argc > 1)
7896 exitstatus = number(argv[1]);
7897 raise_exception(EXEXIT);
7898 /* NOTREACHED */
7899}
7900
7901#if ENABLE_ASH_BUILTIN_ECHO
7902static int
7903echocmd(int argc, char **argv)
7904{
7905 return bb_echo(argv);
7906}
7907#endif
7908
7909#if ENABLE_ASH_BUILTIN_TEST
7910static int
7911testcmd(int argc, char **argv)
7912{
7913 return bb_test(argc, argv);
7914}
7915#endif
7916
7917/* memalloc.c */
7918
7919/*
7920 * Same for malloc, realloc, but returns an error when out of space.
7921 */
7922static void *
7923ckrealloc(void * p, size_t nbytes)
7924{
7925 p = realloc(p, nbytes);
7926 if (p == NULL)
7927 ash_msg_and_raise_error(bb_msg_memory_exhausted);
7928 return p;
7929}
7930
7931static void *
7932ckmalloc(size_t nbytes)
7933{
7934 return ckrealloc(NULL, nbytes);
7935}
7936
7937/*
7938 * Make a copy of a string in safe storage.
7939 */
7940static char *
7941savestr(const char *s)
7942{
7943 char *p = strdup(s);
7944 if (!p)
7945 ash_msg_and_raise_error(bb_msg_memory_exhausted);
7946 return p;
7947}
7948
7949
7950/*
7951 * Parse trees for commands are allocated in lifo order, so we use a stack
7952 * to make this more efficient, and also to avoid all sorts of exception
7953 * handling code to handle interrupts in the middle of a parse.
7954 *
7955 * The size 504 was chosen because the Ultrix malloc handles that size
7956 * well.
7957 */
7958static void *
7959stalloc(size_t nbytes)
7960{
7961 char *p;
7962 size_t aligned;
7963
7964 aligned = SHELL_ALIGN(nbytes);
7965 if (aligned > stacknleft) {
7966 size_t len;
7967 size_t blocksize;
7968 struct stack_block *sp;
7969
7970 blocksize = aligned;
7971 if (blocksize < MINSIZE)
7972 blocksize = MINSIZE;
7973 len = sizeof(struct stack_block) - MINSIZE + blocksize;
7974 if (len < blocksize)
7975 ash_msg_and_raise_error(bb_msg_memory_exhausted);
7976 INT_OFF;
7977 sp = ckmalloc(len);
7978 sp->prev = stackp;
7979 stacknxt = sp->space;
7980 stacknleft = blocksize;
7981 sstrend = stacknxt + blocksize;
7982 stackp = sp;
7983 INT_ON;
7984 }
7985 p = stacknxt;
7986 stacknxt += aligned;
7987 stacknleft -= aligned;
7988 return p;
7989}
7990
7991
7992static void
7993stunalloc(void *p)
7994{
7995#if DEBUG
7996 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
7997 write(2, "stunalloc\n", 10);
7998 abort();
7999 }
8000#endif
8001 stacknleft += stacknxt - (char *)p;
8002 stacknxt = p;
8003}
8004
8005
8006static void
8007setstackmark(struct stackmark *mark)
8008{
8009 mark->stackp = stackp;
8010 mark->stacknxt = stacknxt;
8011 mark->stacknleft = stacknleft;
8012 mark->marknext = markp;
8013 markp = mark;
8014}
8015
8016
8017static void
8018popstackmark(struct stackmark *mark)
8019{
8020 struct stack_block *sp;
8021
8022 INT_OFF;
8023 markp = mark->marknext;
8024 while (stackp != mark->stackp) {
8025 sp = stackp;
8026 stackp = sp->prev;
8027 free(sp);
8028 }
8029 stacknxt = mark->stacknxt;
8030 stacknleft = mark->stacknleft;
8031 sstrend = mark->stacknxt + mark->stacknleft;
8032 INT_ON;
8033}
8034
8035
8036/*
8037 * When the parser reads in a string, it wants to stick the string on the
8038 * stack and only adjust the stack pointer when it knows how big the
8039 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8040 * of space on top of the stack and stackblocklen returns the length of
8041 * this block. Growstackblock will grow this space by at least one byte,
8042 * possibly moving it (like realloc). Grabstackblock actually allocates the
8043 * part of the block that has been used.
8044 */
8045static void
8046growstackblock(void)
8047{
8048 size_t newlen;
8049
8050 newlen = stacknleft * 2;
8051 if (newlen < stacknleft)
8052 ash_msg_and_raise_error(bb_msg_memory_exhausted);
8053 if (newlen < 128)
8054 newlen += 128;
8055
8056 if (stacknxt == stackp->space && stackp != &stackbase) {
8057 struct stack_block *oldstackp;
8058 struct stackmark *xmark;
8059 struct stack_block *sp;
8060 struct stack_block *prevstackp;
8061 size_t grosslen;
8062
8063 INT_OFF;
8064 oldstackp = stackp;
8065 sp = stackp;
8066 prevstackp = sp->prev;
8067 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8068 sp = ckrealloc(sp, grosslen);
8069 sp->prev = prevstackp;
8070 stackp = sp;
8071 stacknxt = sp->space;
8072 stacknleft = newlen;
8073 sstrend = sp->space + newlen;
8074
8075 /*
8076 * Stack marks pointing to the start of the old block
8077 * must be relocated to point to the new block
8078 */
8079 xmark = markp;
8080 while (xmark != NULL && xmark->stackp == oldstackp) {
8081 xmark->stackp = stackp;
8082 xmark->stacknxt = stacknxt;
8083 xmark->stacknleft = stacknleft;
8084 xmark = xmark->marknext;
8085 }
8086 INT_ON;
8087 } else {
8088 char *oldspace = stacknxt;
8089 int oldlen = stacknleft;
8090 char *p = stalloc(newlen);
8091
8092 /* free the space we just allocated */
8093 stacknxt = memcpy(p, oldspace, oldlen);
8094 stacknleft += newlen;
8095 }
8096}
8097
8098static void grabstackblock(size_t len)
8099{
8100 len = SHELL_ALIGN(len);
8101 stacknxt += len;
8102 stacknleft -= len;
8103}
8104
8105
8106/*
8107 * The following routines are somewhat easier to use than the above.
8108 * The user declares a variable of type STACKSTR, which may be declared
8109 * to be a register. The macro STARTSTACKSTR initializes things. Then
8110 * the user uses the macro STPUTC to add characters to the string. In
8111 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8112 * grown as necessary. When the user is done, she can just leave the
8113 * string there and refer to it using stackblock(). Or she can allocate
8114 * the space for it using grabstackstr(). If it is necessary to allow
8115 * someone else to use the stack temporarily and then continue to grow
8116 * the string, the user should use grabstack to allocate the space, and
8117 * then call ungrabstr(p) to return to the previous mode of operation.
8118 *
8119 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8120 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8121 * is space for at least one character.
8122 */
8123static void *
8124growstackstr(void)
8125{
8126 size_t len = stackblocksize();
8127 if (herefd >= 0 && len >= 1024) {
8128 full_write(herefd, stackblock(), len);
8129 return stackblock();
8130 }
8131 growstackblock();
8132 return stackblock() + len;
8133}
8134
8135/*
8136 * Called from CHECKSTRSPACE.
8137 */
8138static char *
8139makestrspace(size_t newlen, char *p)
8140{
8141 size_t len = p - stacknxt;
8142 size_t size = stackblocksize();
8143
8144 for (;;) {
8145 size_t nleft;
8146
8147 size = stackblocksize();
8148 nleft = size - len;
8149 if (nleft >= newlen)
8150 break;
8151 growstackblock();
8152 }
8153 return stackblock() + len;
8154}
8155
8156static char *
8157stnputs(const char *s, size_t n, char *p)
8158{
8159 p = makestrspace(n, p);
8160 p = memcpy(p, s, n) + n;
8161 return p;
8162}
8163
8164static char *
8165stputs(const char *s, char *p)
8166{
8167 return stnputs(s, strlen(s), p);
8168}
8169
8170/* mystring.c */ 7916/* mystring.c */
8171 7917
8172/* 7918/*
@@ -8404,7 +8150,7 @@ copynode(union node *n)
8404 new->nif.test = copynode(n->nif.test); 8150 new->nif.test = copynode(n->nif.test);
8405 break; 8151 break;
8406 case NFOR: 8152 case NFOR:
8407 new->nfor.var = nodesavestr(n->nfor.var); 8153 new->nfor.var = nodeckstrdup(n->nfor.var);
8408 new->nfor.body = copynode(n->nfor.body); 8154 new->nfor.body = copynode(n->nfor.body);
8409 new->nfor.args = copynode(n->nfor.args); 8155 new->nfor.args = copynode(n->nfor.args);
8410 break; 8156 break;
@@ -8420,7 +8166,7 @@ copynode(union node *n)
8420 case NDEFUN: 8166 case NDEFUN:
8421 case NARG: 8167 case NARG:
8422 new->narg.backquote = copynodelist(n->narg.backquote); 8168 new->narg.backquote = copynodelist(n->narg.backquote);
8423 new->narg.text = nodesavestr(n->narg.text); 8169 new->narg.text = nodeckstrdup(n->narg.text);
8424 new->narg.next = copynode(n->narg.next); 8170 new->narg.next = copynode(n->narg.next);
8425 break; 8171 break;
8426 case NTO: 8172 case NTO:
@@ -8474,7 +8220,7 @@ copynodelist(struct nodelist *lp)
8474 8220
8475 8221
8476static char * 8222static char *
8477nodesavestr(char *s) 8223nodeckstrdup(char *s)
8478{ 8224{
8479 char *rtn = funcstring; 8225 char *rtn = funcstring;
8480 8226
@@ -8612,7 +8358,7 @@ setparam(char **argv)
8612 for (nparam = 0; argv[nparam]; nparam++); 8358 for (nparam = 0; argv[nparam]; nparam++);
8613 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap)); 8359 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8614 while (*argv) { 8360 while (*argv) {
8615 *ap++ = savestr(*argv++); 8361 *ap++ = ckstrdup(*argv++);
8616 } 8362 }
8617 *ap = NULL; 8363 *ap = NULL;
8618 freeparam(&shellparam); 8364 freeparam(&shellparam);
@@ -9411,7 +9157,8 @@ makename(void)
9411 return n; 9157 return n;
9412} 9158}
9413 9159
9414static void fixredir(union node *n, const char *text, int err) 9160static void
9161fixredir(union node *n, const char *text, int err)
9415{ 9162{
9416 TRACE(("Fix redir %s %d\n", text, err)); 9163 TRACE(("Fix redir %s %d\n", text, err));
9417 if (!err) 9164 if (!err)
@@ -9491,7 +9238,8 @@ parseheredoc(void)
9491 } 9238 }
9492} 9239}
9493 9240
9494static char peektoken(void) 9241static char
9242peektoken(void)
9495{ 9243{
9496 int t; 9244 int t;
9497 9245
@@ -10453,13 +10201,195 @@ static void setprompt(int whichprompt)
10453} 10201}
10454 10202
10455 10203
10456static const char *const *findkwd(const char *s) 10204/*
10205 * Execute a command or commands contained in a string.
10206 */
10207static int
10208evalstring(char *s, int mask)
10457{ 10209{
10458 return bsearch(s, tokname_array + KWDOFFSET, 10210 union node *n;
10459 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET, 10211 struct stackmark smark;
10460 sizeof(const char *), pstrcmp); 10212 int skip;
10213
10214 setinputstring(s);
10215 setstackmark(&smark);
10216
10217 skip = 0;
10218 while ((n = parsecmd(0)) != NEOF) {
10219 evaltree(n, 0);
10220 popstackmark(&smark);
10221 skip = evalskip;
10222 if (skip)
10223 break;
10224 }
10225 popfile();
10226
10227 skip &= mask;
10228 evalskip = skip;
10229 return skip;
10461} 10230}
10462 10231
10232/*
10233 * The eval command.
10234 */
10235static int
10236evalcmd(int argc, char **argv)
10237{
10238 char *p;
10239 char *concat;
10240 char **ap;
10241
10242 if (argc > 1) {
10243 p = argv[1];
10244 if (argc > 2) {
10245 STARTSTACKSTR(concat);
10246 ap = argv + 2;
10247 for (;;) {
10248 concat = stack_putstr(p, concat);
10249 p = *ap++;
10250 if (p == NULL)
10251 break;
10252 STPUTC(' ', concat);
10253 }
10254 STPUTC('\0', concat);
10255 p = grabstackstr(concat);
10256 }
10257 evalstring(p, ~SKIPEVAL);
10258
10259 }
10260 return exitstatus;
10261}
10262
10263/*
10264 * Read and execute commands. "Top" is nonzero for the top level command
10265 * loop; it turns on prompting if the shell is interactive.
10266 */
10267static int
10268cmdloop(int top)
10269{
10270 union node *n;
10271 struct stackmark smark;
10272 int inter;
10273 int numeof = 0;
10274
10275 TRACE(("cmdloop(%d) called\n", top));
10276 for (;;) {
10277 int skip;
10278
10279 setstackmark(&smark);
10280#if JOBS
10281 if (jobctl)
10282 showjobs(stderr, SHOW_CHANGED);
10283#endif
10284 inter = 0;
10285 if (iflag && top) {
10286 inter++;
10287#if ENABLE_ASH_MAIL
10288 chkmail();
10289#endif
10290 }
10291 n = parsecmd(inter);
10292 /* showtree(n); DEBUG */
10293 if (n == NEOF) {
10294 if (!top || numeof >= 50)
10295 break;
10296 if (!stoppedjobs()) {
10297 if (!Iflag)
10298 break;
10299 out2str("\nUse \"exit\" to leave shell.\n");
10300 }
10301 numeof++;
10302 } else if (nflag == 0) {
10303 job_warning = (job_warning == 2) ? 1 : 0;
10304 numeof = 0;
10305 evaltree(n, 0);
10306 }
10307 popstackmark(&smark);
10308 skip = evalskip;
10309
10310 if (skip) {
10311 evalskip = 0;
10312 return skip & SKIPEVAL;
10313 }
10314 }
10315 return 0;
10316}
10317
10318static int
10319dotcmd(int argc, char **argv)
10320{
10321 struct strlist *sp;
10322 volatile struct shparam saveparam;
10323 int status = 0;
10324
10325 for (sp = cmdenviron; sp; sp = sp->next)
10326 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10327
10328 if (argc >= 2) { /* That's what SVR2 does */
10329 char *fullname;
10330
10331 fullname = find_dot_file(argv[1]);
10332
10333 if (argc > 2) {
10334 saveparam = shellparam;
10335 shellparam.malloc = 0;
10336 shellparam.nparam = argc - 2;
10337 shellparam.p = argv + 2;
10338 };
10339
10340 setinputfile(fullname, INPUT_PUSH_FILE);
10341 commandname = fullname;
10342 cmdloop(0);
10343 popfile();
10344
10345 if (argc > 2) {
10346 freeparam(&shellparam);
10347 shellparam = saveparam;
10348 };
10349 status = exitstatus;
10350 }
10351 return status;
10352}
10353
10354static int
10355exitcmd(int argc, char **argv)
10356{
10357 if (stoppedjobs())
10358 return 0;
10359 if (argc > 1)
10360 exitstatus = number(argv[1]);
10361 raise_exception(EXEXIT);
10362 /* NOTREACHED */
10363}
10364
10365#if ENABLE_ASH_BUILTIN_ECHO
10366static int
10367echocmd(int argc, char **argv)
10368{
10369 return bb_echo(argv);
10370}
10371#endif
10372
10373#if ENABLE_ASH_BUILTIN_TEST
10374static int
10375testcmd(int argc, char **argv)
10376{
10377 return bb_test(argc, argv);
10378}
10379#endif
10380
10381/*
10382 * Read a file containing shell functions.
10383 */
10384static void
10385readcmdfile(char *name)
10386{
10387 setinputfile(name, INPUT_PUSH_FILE);
10388 cmdloop(0);
10389 popfile();
10390}
10391
10392
10463/* redir.c */ 10393/* redir.c */
10464 10394
10465/* 10395/*
@@ -10477,7 +10407,8 @@ static const char *const *findkwd(const char *s)
10477 * Open a file in noclobber mode. 10407 * Open a file in noclobber mode.
10478 * The code was copied from bash. 10408 * The code was copied from bash.
10479 */ 10409 */
10480static int noclobberopen(const char *fname) 10410static int
10411noclobberopen(const char *fname)
10481{ 10412{
10482 int r, fd; 10413 int r, fd;
10483 struct stat finfo, finfo2; 10414 struct stat finfo, finfo2;
@@ -10536,7 +10467,8 @@ static int noclobberopen(const char *fname)
10536 * data to a pipe. If the document is short, we can stuff the data in 10467 * data to a pipe. If the document is short, we can stuff the data in
10537 * the pipe without forking. 10468 * the pipe without forking.
10538 */ 10469 */
10539static int openhere(union node *redir) 10470static int
10471openhere(union node *redir)
10540{ 10472{
10541 int pip[2]; 10473 int pip[2];
10542 size_t len = 0; 10474 size_t len = 0;
@@ -10633,7 +10565,8 @@ openredirect(union node *redir)
10633 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "No such file")); 10565 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "No such file"));
10634} 10566}
10635 10567
10636static void dupredirect(union node *redir, int f) 10568static void
10569dupredirect(union node *redir, int f)
10637{ 10570{
10638 int fd = redir->nfile.fd; 10571 int fd = redir->nfile.fd;
10639 10572
@@ -11208,7 +11141,7 @@ trapcmd(int argc, char **argv)
11208 if (LONE_DASH(action)) 11141 if (LONE_DASH(action))
11209 action = NULL; 11142 action = NULL;
11210 else 11143 else
11211 action = savestr(action); 11144 action = ckstrdup(action);
11212 } 11145 }
11213 if (trap[signo]) 11146 if (trap[signo])
11214 free(trap[signo]); 11147 free(trap[signo]);
@@ -11614,7 +11547,7 @@ setvareq(char *s, int flags)
11614 *vpp = vp; 11547 *vpp = vp;
11615 } 11548 }
11616 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE))) 11549 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
11617 s = savestr(s); 11550 s = ckstrdup(s);
11618 vp->text = s; 11551 vp->text = s;
11619 vp->flags = flags; 11552 vp->flags = flags;
11620} 11553}
@@ -13311,6 +13244,26 @@ read_profile(const char *name)
13311 exitshell(); 13244 exitshell();
13312} 13245}
13313 13246
13247/*
13248 * This routine is called when an error or an interrupt occurs in an
13249 * interactive shell and control is returned to the main command loop.
13250 */
13251static void
13252reset(void)
13253{
13254 /* from eval.c: */
13255 evalskip = 0;
13256 loopnest = 0;
13257 /* from input.c: */
13258 parselleft = parsenleft = 0; /* clear input buffer */
13259 popallfiles();
13260 /* from parser.c: */
13261 tokpushback = 0;
13262 checkkwd = 0;
13263 /* from redir.c: */
13264 clearredir(0);
13265}
13266
13314#if PROFILE 13267#if PROFILE
13315static short profile_buf[16384]; 13268static short profile_buf[16384];
13316extern int etext(); 13269extern int etext();
@@ -13404,9 +13357,9 @@ int ash_main(int argc, char **argv)
13404 state = 3; 13357 state = 3;
13405 if ( 13358 if (
13406#ifndef linux 13359#ifndef linux
13407 getuid() == geteuid() && getgid() == getegid() && 13360 getuid() == geteuid() && getgid() == getegid() &&
13408#endif 13361#endif
13409 iflag 13362 iflag
13410 ) { 13363 ) {
13411 shinit = lookupvar("ENV"); 13364 shinit = lookupvar("ENV");
13412 if (shinit != NULL && *shinit != '\0') { 13365 if (shinit != NULL && *shinit != '\0') {