Make some 64 bit warnings go away on x86-64.
[oweals/busybox.git] / shell / msh.c
index 22a617095365f25c4cf65f62848d161cf85aa199..bd4b8fdb22bb4a7bdfe33900545ba804849041f5 100644 (file)
@@ -27,6 +27,7 @@
  * Original copyright notice is retained at the end of this file.
  */
 
+#include "busybox.h"
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
@@ -46,7 +47,6 @@
 #include <sys/wait.h>
 
 #include "cmdedit.h"
-#include "busybox.h"
 
 
 /* Conditional use of "register" keyword */
@@ -93,6 +93,15 @@ int mshdbg_rc = 0;
 #endif                                                 /* MSHDEBUG */
 
 
+#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
+# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
+# define DEFAULT_USER_PROMPT "\\u:\\w$ "
+#else
+# define DEFAULT_ROOT_PROMPT "# "
+# define DEFAULT_USER_PROMPT "$ "
+#endif
+
+
 /* -------- sh.h -------- */
 /*
  * shell
@@ -162,7 +171,8 @@ struct op {
 #define        TDOT    17
 
 /* Strings for names to make debug easier */
-char *T_CMD_NAMES[] = {
+#ifdef MSHDEBUG
+static char *T_CMD_NAMES[] = {
        "PLACEHOLDER",
        "TCOM",
        "TPAREN",
@@ -182,7 +192,7 @@ char *T_CMD_NAMES[] = {
        "TASYNC",
        "TDOT",
 };
-
+#endif
 
 /*
  * actions determining the environment of a process
@@ -299,7 +309,7 @@ static int rlookup(char *n);
 static struct wdblock *glob(char *cp, struct wdblock *wb);
 static int my_getc(int ec);
 static int subgetc(int ec, int quoted);
-static char **makenv(int all);
+static char **makenv(int all, struct wdblock *wb);
 static char **eval(char **ap, int f);
 static int setstatus(int s);
 static int waitfor(int lastpid, int canintr);
@@ -334,9 +344,9 @@ static void sig(int i);                     /* default signal handler */
 #define GROWBY   (256)
 /* #define     SHRINKBY   (64) */
 #undef SHRINKBY
-#define FREE     (32767)
-#define BUSY     (0)
-#define        ALIGN     (sizeof(int)-1)
+#define FREE     (32767)
+#define BUSY     (0)
+#define        ALIGN     (sizeof(int)-1)
 
 
 struct region {
@@ -513,7 +523,7 @@ static int eofc(void);
 static int readc(void);
 static void unget(int c);
 static void ioecho(int c);
-static void prs(char *s);
+static void prs(const char *s);
 static void prn(unsigned u);
 static void closef(int i);
 static void closeall(void);
@@ -621,7 +631,7 @@ struct here {
        struct here *h_next;
 };
 
-static char *signame[] = {
+static const char * const signame[] = {
        "Signal 0",
        "Hangup",
        (char *) NULL,                          /* interrupt */
@@ -643,10 +653,10 @@ static char *signame[] = {
 #define        NSIGNAL (sizeof(signame)/sizeof(signame[0]))
 
 struct res {
-       char *r_name;
+       const char *r_name;
        int r_val;
 };
-static struct res restab[] = {
+static const struct res restab[] = {
        {"for", FOR},
        {"case", CASE},
        {"esac", ESAC},
@@ -698,8 +708,7 @@ static const struct builtincmd builtincmds[] = {
        {0, 0}
 };
 
-static int expand_dotnode(struct op *);
-struct op *scantree(struct op *);
+static struct op *scantree(struct op *);
 static struct op *dowholefile(int, int);
 
 /* Globals */
@@ -709,7 +718,7 @@ static char **dolv;
 static int dolc;
 static int exstat;
 static char gflg;
-static int interactive = 0;            /* Is this an interactive shell */
+static int interactive;                        /* Is this an interactive shell */
 static int execflg;
 static int multiline;                  /* \n changed to ; */
 static struct op *outtree;             /* result from parser */
@@ -776,10 +785,11 @@ static struct env e = {
 };
 
 #ifdef MSHDEBUG
+void print_t(struct op *t);
 void print_t(struct op *t)
 {
-       DBGPRINTF(("T: t=0x%x, type %s, words=0x%x, IOword=0x%x\n", t,
-                          T_CMD_NAMES[t->type], t->words, t->ioact));
+       DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
+                 T_CMD_NAMES[t->type], t->words, t->ioact));
 
        if (t->words) {
                DBGPRINTF(("T: W1: %s", t->words[0]));
@@ -788,6 +798,7 @@ void print_t(struct op *t)
        return;
 }
 
+void print_tree(struct op *head);
 void print_tree(struct op *head)
 {
        if (head == NULL) {
@@ -795,7 +806,7 @@ void print_tree(struct op *head)
                return;
        }
 
-       DBGPRINTF(("NODE: 0x%x,  left 0x%x, right 0x%x\n", head, head->left,
+       DBGPRINTF(("NODE: %p,  left %p, right %p\n", head, head->left,
                           head->right));
 
        if (head->left)
@@ -819,7 +830,7 @@ static char *current_prompt;
  */
 
 
-extern int msh_main(int argc, char **argv)
+int msh_main(int argc, char **argv)
 {
        REGISTER int f;
        REGISTER char *s;
@@ -827,7 +838,7 @@ extern int msh_main(int argc, char **argv)
        char *name, **ap;
        int (*iof) (struct ioarg *);
 
-       DBGPRINTF(("MSH_MAIN: argc %d, environ 0x%x\n", argc, environ));
+       DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
 
        initarea();
        if ((ap = environ) != NULL) {
@@ -841,7 +852,7 @@ extern int msh_main(int argc, char **argv)
 
        shell = lookup("SHELL");
        if (shell->value == null)
-               setval(shell, DEFAULT_SHELL);
+               setval(shell, (char *)DEFAULT_SHELL);
        export(shell);
 
        homedir = lookup("HOME");
@@ -875,9 +886,9 @@ extern int msh_main(int argc, char **argv)
 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
        if (prompt->value == null)
 #endif
-               setval(prompt, "$ ");
+               setval(prompt, DEFAULT_USER_PROMPT);
        if (geteuid() == 0) {
-               setval(prompt, "# ");
+               setval(prompt, DEFAULT_ROOT_PROMPT);
                prompt->status &= ~EXPORT;
        }
        cprompt = lookup("PS2");
@@ -956,9 +967,9 @@ extern int msh_main(int argc, char **argv)
                        interactive++;
 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
 #ifdef MSHDEBUG
-                       printf("\n\n" BB_BANNER " Built-in shell (msh with debug)\n");
+                       printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
 #else
-                       printf("\n\n" BB_BANNER " Built-in shell (msh)\n");
+                       printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
 #endif
                        printf("Enter 'help' for a list of built-in commands.\n\n");
 #endif
@@ -992,7 +1003,7 @@ extern int msh_main(int argc, char **argv)
        }
        setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
 
-       DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop 0x%x, iostack 0x%x\n", interactive, e.iop, iostack));
+       DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
 
        for (;;) {
                if (interactive && e.iop <= iostack) {
@@ -1047,23 +1058,6 @@ REGISTER char *s;
 }
 
 
-static int expand_dotnode(node)
-struct op *node;
-{
-       struct op *outtree_save = outtree;
-
-       node->type = TDOT;
-       newfile(node->words[1]);
-
-       node->left = dowholefile(TDOT, 0);
-
-       node->right = NULL;
-
-       outtree = outtree_save;
-
-       return (1);
-}
-
 struct op *scantree(head)
 struct op *head;
 {
@@ -1087,10 +1081,10 @@ struct op *head;
        if (head->words == NULL)
                return (NULL);
 
-       DBGPRINTF5(("SCANTREE: checking node 0x%x\n", head));
+       DBGPRINTF5(("SCANTREE: checking node %p\n", head));
 
        if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {
-               DBGPRINTF5(("SCANTREE: dot found in node 0x%x\n", head));
+               DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
                return (head);
        }
 
@@ -1103,7 +1097,7 @@ static void onecommand()
        REGISTER int i;
        jmp_buf m1;
 
-       DBGPRINTF(("ONECOMMAND: enter, outtree=0x%x\n", outtree));
+       DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
 
        while (e.oenv)
                quitenv();
@@ -1143,7 +1137,7 @@ static void onecommand()
        execflg = 0;
 
        if (!flag['n']) {
-               DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=0x%x\n",
+               DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
                                   outtree));
                execute(outtree, NOPIPE, NOPIPE, 0);
        }
@@ -1234,7 +1228,7 @@ static void quitenv()
        REGISTER struct env *ep;
        REGISTER int fd;
 
-       DBGPRINTF(("QUITENV: e.oenv=0x%x\n", e.oenv));
+       DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
 
        if ((ep = e.oenv) != NULL) {
                fd = e.iofd;
@@ -1636,10 +1630,10 @@ REGISTER int sub;
 
 static void initarea()
 {
-       brkaddr = malloc(AREASIZE);
+       brkaddr = xmalloc(AREASIZE);
        brktop = brkaddr + AREASIZE;
 
-       while ((int) sbrk(0) & ALIGN)
+       while ((long) sbrk(0) & ALIGN)
                sbrk(1);
        areabot = (struct region *) sbrk(REGSIZE);
 
@@ -1807,7 +1801,7 @@ int cf;
 
        t = command(cf);
 
-       DBGPRINTF9(("PIPELINE: t=0x%x\n", t));
+       DBGPRINTF9(("PIPELINE: t=%p\n", t));
 
        if (t != NULL) {
                while ((c = yylex(0)) == '|') {
@@ -1826,7 +1820,7 @@ int cf;
                peeksym = c;
        }
 
-       DBGPRINTF7(("PIPELINE: returning t=0x%x\n", t));
+       DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
        return (t);
 }
 
@@ -1839,7 +1833,7 @@ static struct op *andor()
 
        t = pipeline(0);
 
-       DBGPRINTF9(("ANDOR: t=0x%x\n", t));
+       DBGPRINTF9(("ANDOR: t=%p\n", t));
 
        if (t != NULL) {
                while ((c = yylex(0)) == LOGAND || c == LOGOR) {
@@ -1854,7 +1848,7 @@ static struct op *andor()
                peeksym = c;
        }
 
-       DBGPRINTF7(("ANDOR: returning t=0x%x\n", t));
+       DBGPRINTF7(("ANDOR: returning t=%p\n", t));
        return (t);
 }
 
@@ -1886,7 +1880,7 @@ static struct op *c_list()
                peeksym = c;
        }
        /* IF */
-       DBGPRINTF7(("C_LIST: returning t=0x%x\n", t));
+       DBGPRINTF7(("C_LIST: returning t=%p\n", t));
        return (t);
 }
 
@@ -2077,7 +2071,7 @@ int cf;
        t = namelist(t);
        iolist = iosave;
 
-       DBGPRINTF(("COMMAND: returning 0x%x\n", t));
+       DBGPRINTF(("COMMAND: returning %p\n", t));
 
        return (t);
 }
@@ -2094,7 +2088,7 @@ int mark;
        t = c_list();
        multiline--;
        t = block(type, t, NOBLOCK, NOWORDS);
-       DBGPRINTF(("DOWHOLEFILE: return t=0x%x\n", t));
+       DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
        return (t);
 }
 
@@ -2166,7 +2160,7 @@ static struct op *caselist()
                t = list(t, casepart());
        }
 
-       DBGPRINTF(("CASELIST, returning t=0x%x\n", t));
+       DBGPRINTF(("CASELIST, returning t=%p\n", t));
        return (t);
 }
 
@@ -2184,7 +2178,7 @@ static struct op *casepart()
        if ((peeksym = yylex(CONTIN)) != ESAC)
                musthave(BREAK, CONTIN);
 
-       DBGPRINTF7(("CASEPART: made newtp(TPAT, t=0x%x)\n", t));
+       DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
 
        return (t);
 }
@@ -2227,7 +2221,7 @@ static char **wordlist()
 static struct op *list(t1, t2)
 REGISTER struct op *t1, *t2;
 {
-       DBGPRINTF7(("LIST: enter, t1=0x%x, t2=0x%x\n", t1, t2));
+       DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
 
        if (t1 == NULL)
                return (t2);
@@ -2252,7 +2246,7 @@ char **wp;
        t->right = t2;
        t->words = wp;
 
-       DBGPRINTF7(("BLOCK: inserted 0x%x between 0x%x and 0x%x\n", t, t1,
+       DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
                                t2));
 
        return (t);
@@ -2262,7 +2256,7 @@ char **wp;
 static int rlookup(n)
 REGISTER char *n;
 {
-       REGISTER struct res *rp;
+       REGISTER const struct res *rp;
 
        DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
 
@@ -2288,7 +2282,7 @@ static struct op *newtp()
        t->right = NULL;
        t->str = NULL;
 
-       DBGPRINTF3(("NEWTP: allocated 0x%x\n", t));
+       DBGPRINTF3(("NEWTP: allocated %p\n", t));
 
        return (t);
 }
@@ -2297,7 +2291,7 @@ static struct op *namelist(t)
 REGISTER struct op *t;
 {
 
-       DBGPRINTF7(("NAMELIST: enter, t=0x%x, type %s, iolist=0x%x\n", t,
+       DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
                                T_CMD_NAMES[t->type], iolist));
 
        if (iolist) {
@@ -2634,7 +2628,7 @@ int act;
                return (0);
        }
 
-       DBGPRINTF(("EXECUTE: t=0x%x, t->type=%d (%s), t->words is %s\n", t,
+       DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
                           t->type, T_CMD_NAMES[t->type],
                           ((t->words == NULL) ? "NULL" : t->words[0])));
 
@@ -2647,7 +2641,7 @@ int act;
 /* Hard to know how many words there are, be careful of garbage pointer values */
 /* They are likely to cause "PCI bus fault" errors */
 #if 0
-       DBGPRINTF(("EXECUTE: t->left=0x%x, t->right=0x%x, t->words[1] is %s\n",
+       DBGPRINTF(("EXECUTE: t->left=%p, t->right=%p, t->words[1] is %s\n",
                           t->left, t->right,
                           ((t->words[1] == NULL) ? "NULL" : t->words[1])));
        DBGPRINTF7(("EXECUTE: t->words[2] is %s, t->words[3] is %s\n",
@@ -2731,7 +2725,7 @@ int act;
                                interactive = 0;
                                if (pin == NULL) {
                                        close(0);
-                                       open("/dev/null", 0);
+                                       open(bb_dev_null, 0);
                                }
                                _exit(execute(t->left, pin, pout, FEXEC));
                        }
@@ -2796,9 +2790,9 @@ int act;
                                        ((cp == NULL) ? "NULL" : cp)));
 
                if ((t1 = findcase(t->left, cp)) != NULL) {
-                       DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=0x%x, t1=0x%x)...\n", t, t1));
+                       DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
                        rv = execute(t1, pin, pout, 0);
-                       DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=0x%x, t1=0x%x)...\n", t, t1));
+                       DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
                }
                break;
 
@@ -2833,7 +2827,7 @@ int act;
                runtrap(i);
        }
 
-       DBGPRINTF(("EXECUTE: returning from t=0x%x, rv=%d\n", t, rv));
+       DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
        return (rv);
 }
 
@@ -2869,7 +2863,7 @@ forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
        (void) &owp;
 #endif
 
-       DBGPRINTF(("FORKEXEC: t=0x%x, pin 0x%x, pout 0x%x, act %d\n", t, pin,
+       DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
                           pout, act));
        DBGPRINTF7(("FORKEXEC: t->words is %s\n",
                                ((t->words == NULL) ? "NULL" : t->words[0])));
@@ -2899,7 +2893,7 @@ forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
                /* strip all initial assignments */
                /* not correct wrt PATH=yyy command  etc */
                if (flag['x']) {
-                       DBGPRINTF9(("FORKEXEC: echo'ing, cp=0x%x, wp=0x%x, owp=0x%x\n",
+                       DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
                                                cp, wp, owp));
                        echo(cp ? wp : owp);
                }
@@ -2929,7 +2923,7 @@ forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
                                ((t->words == NULL) ? "NULL" : t->words[0]),
                                ((t->words == NULL) ? "NULL" : t->words[1])));
 #endif
-       DBGPRINTF(("FORKEXEC: shcom 0x%x, f&FEXEC 0x%x, owp 0x%x\n", shcom,
+       DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
                           f & FEXEC, owp));
 
        if (shcom == NULL && (f & FEXEC) == 0) {
@@ -2975,7 +2969,7 @@ forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
                }
 
                /* Must be the child process, pid should be 0 */
-               DBGPRINTF(("FORKEXEC: child process, shcom=0x%x\n", shcom));
+               DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
 
                if (interactive) {
                        signal(SIGINT, SIG_IGN);
@@ -3043,6 +3037,10 @@ forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
        if (resetsig) {
                signal(SIGINT, SIG_DFL);
                signal(SIGQUIT, SIG_DFL);
+       } else {
+               /* put non-interactive processes into a different process group.
+                * we don't support jobs, but this is at least sane: see Bug 659 */
+               bb_setpgrp;
        }
 
        if (t->type == TPAREN)
@@ -3050,7 +3048,7 @@ forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
        if (wp[0] == NULL)
                _exit(0);
 
-       cp = rexecve(wp[0], wp, makenv(0));
+       cp = rexecve(wp[0], wp, makenv(0, NULL));
        prs(wp[0]);
        prs(": ");
        err(cp);
@@ -3075,7 +3073,7 @@ int pipein, pipeout;
        REGISTER int u = -1;
        char *cp = NULL, *msg;
 
-       DBGPRINTF(("IOSETUP: iop 0x%x, pipein 0x%x, pipeout 0x%x\n", iop,
+       DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
                           pipein, pipeout));
 
        if (iop->io_unit == IODEFAULT)  /* take default */
@@ -3179,7 +3177,7 @@ char *w;
 
        if (t->type == TLIST) {
                if ((tp = find1case(t->left, w)) != NULL) {
-                       DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=0x%x\n", tp));
+                       DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
                        return (tp);
                }
                t1 = t->right;                  /* TPAT */
@@ -3188,7 +3186,7 @@ char *w;
 
        for (wp = t1->words; *wp;)
                if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) {
-                       DBGPRINTF3(("FIND1CASE: returning &t1->left= 0x%x.\n",
+                       DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
                                                &t1->left));
                        return (&t1->left);
                }
@@ -3308,12 +3306,11 @@ char *c, **v, **envp;
                /* We have to exec here since we vforked.  Running
                 * run_applet_by_name() won't work and bad things
                 * will happen. */
-               execve("/proc/self/exe", v, envp);
-               execve("busybox", v, envp);
+               execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
        }
 #endif
 
-       DBGPRINTF(("REXECVE: c=0x%x, v=0x%x, envp=0x%x\n", c, v, envp));
+       DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
 
        sp = any('/', c) ? "" : path->value;
        asis = *sp == '\0';
@@ -3374,7 +3371,7 @@ static int run(struct ioarg *argp, int (*f) (struct ioarg *))
        (void) &rv;
 #endif
 
-       DBGPRINTF(("RUN: enter, areanum %d, outtree 0x%x, failpt 0x%x\n",
+       DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
                           areanum, outtree, failpt));
 
        areanum++;
@@ -3504,7 +3501,7 @@ struct op *t;
                signal(SIGINT, SIG_DFL);
                signal(SIGQUIT, SIG_DFL);
        }
-       cp = rexecve(t->words[0], t->words, makenv(0));
+       cp = rexecve(t->words[0], t->words, makenv(0, NULL));
        prs(t->words[0]);
        prs(": ");
        err(cp);
@@ -3559,7 +3556,7 @@ struct op *t;
        char *cp;
        int maltmp;
 
-       DBGPRINTF(("DODOT: enter, t=0x%x, tleft 0x%x, tright 0x%x, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep)));
+       DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep)));
 
        if ((cp = t->words[1]) == NULL) {
                DBGPRINTF(("DODOT: bad args, ret 0\n"));
@@ -3778,7 +3775,7 @@ struct op *t;
        if ((cp = t->words[1]) != NULL)
                setstatus(getn(cp));
 
-       DBGPRINTF(("DOEXIT: calling leave(), t=0x%x\n", t));
+       DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
 
        leave();
        /* NOTREACHED */
@@ -3801,7 +3798,7 @@ struct op *t;
 
 static void rdexp(char **wp, void (*f) (struct var *), int key)
 {
-       DBGPRINTF6(("RDEXP: enter, wp=0x%x, func=0x%x, key=%d\n", wp, f, key));
+       DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
        DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
 
        if (*wp != NULL) {
@@ -3972,14 +3969,12 @@ static char **eval(char **ap, int f)
  * names in the dictionary. Keyword assignments
  * will already have been done.
  */
-static char **makenv(int all)
+static char **makenv(int all, struct wdblock *wb)
 {
-       REGISTER struct wdblock *wb;
        REGISTER struct var *vp;
 
        DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
 
-       wb = NULL;
        for (vp = vlist; vp; vp = vp->next)
                if (all || vp->status & EXPORT)
                        wb = addword(vp->name, wb);
@@ -3993,7 +3988,7 @@ int f;
 {
        struct wdblock *wb;
 
-       DBGPRINTF6(("EVALSTR: enter, cp=0x%x, f=%d\n", cp, f));
+       DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
 
        wb = NULL;
        if (expand(cp, &wb, f)) {
@@ -4269,6 +4264,7 @@ int quoted;
        int ignore;
        int ignore_once;
        char *argument_list[4];
+       struct wdblock *wb = NULL;
 
 #if __GNUC__
        /* Avoid longjmp clobbering */
@@ -4309,7 +4305,7 @@ int quoted;
                        }
 
                        var_name[var_index++] = *src++;
-                       while (isalnum(*src))
+                       while (isalnum(*src) || *src=='_')
                                var_name[var_index++] = *src++;
                        var_name[var_index] = 0;
 
@@ -4341,22 +4337,47 @@ int quoted;
                                src++;
                        }
 
-                       vp = lookup(var_name);
-                       if (vp->value != null)
-                               value = (operator == '+') ? alt_value : vp->value;
-                       else if (operator == '?') {
-                               err(alt_value);
-                               return (0);
-                       } else if (alt_index && (operator != '+')) {
-                               value = alt_value;
-                               if (operator == '=')
-                                       setval(vp, value);
-                       } else
-                               continue;
+                       if (isalpha(*var_name)) {
+                               /* let subshell handle it instead */
+
+                               char *namep = var_name;
+
+                               *dest++ = '$';
+                               if (braces)
+                                       *dest++ = '{';
+                               while (*namep)
+                                       *dest++ = *namep++;
+                               if (operator) {
+                                       char *altp = alt_value;
+                                       *dest++ = operator;
+                                       while (*altp)
+                                               *dest++ = *altp++;
+                               }
+                               if (braces)
+                                       *dest++ = '}';
 
-                       while (*value && (count < LINELIM)) {
-                               *dest++ = *value++;
-                               count++;
+                               wb = addword(lookup(var_name)->name, wb);
+                       } else {
+                               /* expand */
+
+                               vp = lookup(var_name);
+                               if (vp->value != null)
+                                       value = (operator == '+') ?
+                                               alt_value : vp->value;
+                               else if (operator == '?') {
+                                       err(alt_value);
+                                       return (0);
+                               } else if (alt_index && (operator != '+')) {
+                                       value = alt_value;
+                                       if (operator == '=')
+                                               setval(vp, value);
+                               } else
+                                       continue;
+
+                               while (*value && (count < LINELIM)) {
+                                       *dest++ = *value++;
+                                       count++;
+                               }
                        }
                } else {
                        *dest++ = *src++;
@@ -4371,7 +4392,7 @@ int quoted;
 
        while ((i = vfork()) == -1 && errno == EAGAIN);
 
-       DBGPRINTF3(("GRAVE: i is %d\n", io));
+       DBGPRINTF3(("GRAVE: i is %p\n", io));
 
        if (i < 0) {
                closepipe(pf);
@@ -4401,7 +4422,7 @@ int quoted;
        argument_list[2] = child_cmd;
        argument_list[3] = 0;
 
-       cp = rexecve(argument_list[0], argument_list, makenv(1));
+       cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
        prs(argument_list[0]);
        prs(": ");
        err(cp);
@@ -4632,8 +4653,8 @@ REGISTER struct wdblock *wb;
        return (wd);
 }
 
-int (*func) (char *, char *);
-int globv;
+static int (*func) (char *, char *);
+static int globv;
 
 static void glob0(a0, a1, a2, a3)
 char *a0;
@@ -4795,10 +4816,10 @@ static int readc()
 {
        REGISTER int c;
 
-       RCPRINTF(("READC: e.iop 0x%x, e.iobase 0x%x\n", e.iop, e.iobase));
+       RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
 
        for (; e.iop >= e.iobase; e.iop--) {
-               RCPRINTF(("READC: e.iop 0x%x, peekc 0x%x\n", e.iop, e.iop->peekc));
+               RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
                if ((c = e.iop->peekc) != '\0') {
                        e.iop->peekc = 0;
                        return (c);
@@ -4836,7 +4857,7 @@ static int readc()
        }                                                       /* FOR */
 
        if (e.iop >= iostack) {
-               RCPRINTF(("READC: return 0, e.iop 0x%x\n", e.iop));
+               RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
                return (0);
        }
 
@@ -4857,7 +4878,7 @@ char c;
 
 static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
 {
-       DBGPRINTF(("PUSHIO: argp 0x%x, argp->afid 0x%x, e.iop 0x%x\n", argp,
+       DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
                           argp->afid, e.iop));
 
        /* Set env ptr for io source to next array spot and check for array overflow */
@@ -4897,9 +4918,9 @@ static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
                        e.iop->argp->afid = bufid;      /* assign buffer id */
                }
 
-               DBGPRINTF(("PUSHIO: iostack 0x%x,  e.iop 0x%x, afbuf 0x%x\n",
+               DBGPRINTF(("PUSHIO: iostack %p,  e.iop %p, afbuf %p\n",
                                   iostack, e.iop, e.iop->argp->afbuf));
-               DBGPRINTF(("PUSHIO: mbuf 0x%x, sbuf 0x%x, bid %d, e.iop 0x%x\n",
+               DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
                                   &mainbuf, &sharedbuf, bufid, e.iop));
 
        }
@@ -5119,7 +5140,7 @@ struct io *iop;
 {
        REGISTER int c;
 
-       DBGPRINTF3(("QGRAVECHAR: enter, ap=0x%x, iop=0x%x\n", ap, iop));
+       DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
 
        if (iop->xchar) {
                if (iop->nlcount) {
@@ -5159,7 +5180,7 @@ REGISTER struct ioarg *ap;
 }
 
 static void prs(s)
-REGISTER char *s;
+REGISTER const char *s;
 {
        if (*s)
                write(2, s, strlen(s));
@@ -5252,7 +5273,7 @@ struct ioword *iop;
 {
        REGISTER struct here *h, *lh;
 
-       DBGPRINTF7(("MARKHERE: enter, s=0x%x\n", s));
+       DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
 
        h = (struct here *) space(sizeof(struct here));
        if (h == 0)
@@ -5312,7 +5333,7 @@ int ec;
        char myline[LINELIM + 1];
        char *thenext;
 
-       DBGPRINTF7(("READHERE: enter, name=0x%x, s=0x%x\n", name, s));
+       DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
 
        tf = mkstemp(tname);
        if (tf < 0)