URI: 
       tadd new | syntax. syntax will change. - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 9aa1c92f743a7bf2ac0b062b0c075dc610b3e335
   DIR parent 02f38ca68ce484b2aad15fad4d59c4d43ef7eb1b
  HTML Author: rsc <devnull@localhost>
       Date:   Tue,  4 Jan 2005 22:41:27 +0000
       
       add new | syntax.
       syntax will change.
       
       Diffstat:
         M src/cmd/mk/fns.h                    |      17 +++++++++--------
         M src/cmd/mk/graph.c                  |       2 +-
         M src/cmd/mk/lex.c                    |       6 +++---
         M src/cmd/mk/main.c                   |       1 +
         M src/cmd/mk/match.c                  |       4 ++--
         M src/cmd/mk/mk.c                     |       6 +++---
         M src/cmd/mk/mk.h                     |      23 ++++++++++++++++++-----
         M src/cmd/mk/mkfile.test              |      15 +++++++++++----
         M src/cmd/mk/parse.c                  |      40 ++++++++++++++++++++++----------
         M src/cmd/mk/rc.c                     |      35 ++++++++++++++++++++++++-------
         M src/cmd/mk/rule.c                   |       7 +++++--
         M src/cmd/mk/run.c                    |       6 +++---
         M src/cmd/mk/sh.c                     |      41 ++++++++++++++++++++++---------
         A src/cmd/mk/shell.c                  |      76 +++++++++++++++++++++++++++++++
         M src/cmd/mk/shprint.c                |       4 ++--
         A src/cmd/mk/sys.std.h                |      22 ++++++++++++++++++++++
         M src/cmd/mk/unix.c                   |      53 ++++++++++++++++++++++---------
         M src/cmd/mk/varsub.c                 |       4 ++--
         M src/cmd/mk/word.c                   |       2 +-
       
       19 files changed, 281 insertions(+), 83 deletions(-)
       ---
   DIR diff --git a/src/cmd/mk/fns.h b/src/cmd/mk/fns.h
       t@@ -11,10 +11,8 @@ void        atouch(char*);
        void        bufcpy(Bufblock *, char *, int);
        Envy        *buildenv(Job*, int);
        void        catchnotes(void);
       -char         *charin(char *, char *);
        int        chgtime(char*);
        void        clrmade(Node*);
       -char        *copyq(char*, Rune, Bufblock*);
        void        delete(char*);
        void        delword(Word*);
        int        dorecipe(Node*);
       t@@ -24,24 +22,23 @@ void        dumpn(char*, Node*);
        void        dumpr(char*, Rule*);
        void        dumpv(char*);
        void        dumpw(char*, Word*);
       -int        escapetoken(Biobuf*, Bufblock*, int, int);
        void        execinit(void);
       -int        execsh(char*, char*, Bufblock*, Envy*);
       +int        execsh(char*, char*, Bufblock*, Envy*, Shell*, Word*);
        void        Exit(void);
       -char        *expandquote(char*, Rune, Bufblock*);
        void        expunge(int, char*);
        void        freebuf(Bufblock*);
        void        front(char*);
        Node        *graph(char*);
        void        growbuf(Bufblock *);
        void        initenv(void);
       +void        initshell(void);
        void        insert(Bufblock *, int);
        void        ipop(void);
        void        ipush(void);
        void        killchildren(char*);
        void        *Malloc(int);
        char        *maketmp(int*);
       -int        match(char*, char*, char*);
       +int        match(char*, char*, char*, Shell*);
        char *membername(char*, int, char*);
        void        mk(char*);
        ulong        mkmtime(char*);
       t@@ -56,17 +53,21 @@ void        nproc(void);
        void        nrep(void);
        int        outofdate(Node*, Arc*, int);
        void        parse(char*, int, int);
       -int        pipecmd(char*, Envy*, int*);
       +int        pipecmd(char*, Envy*, int*, Shell*, Word*);
       +void        popshell(void);
        void        prusage(void);
       +void        pushshell(void);
        void        rcopy(char**, Resub*, int);
        void        readenv(void);
        void        *Realloc(void*, int);
        void        rinsert(Bufblock *, Rune);
        char        *rulecnt(void);
        void        run(Job*);
       +char        *setshell(Word*);
        void        setvar(char*, void*);
       +int        shargv(Word*, int, char***);
        char        *shname(char*);
       -void        shprint(char*, Envy*, Bufblock*);
       +void        shprint(char*, Envy*, Bufblock*, Shell*);
        Word        *stow(char*);
        void        subst(char*, char*, char*);
        void        symdel(char*, int);
   DIR diff --git a/src/cmd/mk/graph.c b/src/cmd/mk/graph.c
       t@@ -84,7 +84,7 @@ applyrules(char *target, char *cnt)
                                if(regexec(r->pat, node->name, rmatch, NREGEXP) == 0)
                                        continue;
                        } else {
       -                        if(!match(node->name, r->target, stem)) continue;
       +                        if(!match(node->name, r->target, stem, r->shellt)) continue;
                        }
                        if(cnt[r->rule] >= nreps) continue;
                        cnt[r->rule]++;
   DIR diff --git a/src/cmd/mk/lex.c b/src/cmd/mk/lex.c
       t@@ -28,7 +28,7 @@ assline(Biobuf *bp, Bufblock *buf)
                        case '\'':
                        case '"':
                                rinsert(buf, c);
       -                        if (escapetoken(bp, buf, 1, c) == 0)
       +                        if (shellt->escapetoken(bp, buf, 1, c) == 0)
                                        Exit();
                                break;
                        case '`':
       t@@ -87,14 +87,14 @@ bquote(Biobuf *bp, Bufblock *buf)
                                insert(buf,0);
                                buf->current = buf->start+start;
                                execinit();
       -                        execsh(0, buf->current, buf, envy);
       +                        execsh(0, buf->current, buf, envy, shellt, shellcmd);
                                return 1;
                        }
                        if(c == '\n')
                                break;
                        if(c == '\'' || c == '"' || c == '\\'){
                                insert(buf, c);
       -                        if(!escapetoken(bp, buf, 1, c))
       +                        if(!shellt->escapetoken(bp, buf, 1, c))
                                        return 0;
                                continue;
                        }
   DIR diff --git a/src/cmd/mk/main.c b/src/cmd/mk/main.c
       t@@ -39,6 +39,7 @@ main(int argc, char **argv)
                 *  instead of sharing them
                 */
        
       +        initshell();
                Binit(&bout, 1, OWRITE);
                buf = newbuf();
                whatif = 0;
   DIR diff --git a/src/cmd/mk/match.c b/src/cmd/mk/match.c
       t@@ -1,7 +1,7 @@
        #include        "mk.h"
        
        int
       -match(char *name, char *template, char *stem)
       +match(char *name, char *template, char *stem, Shell *sh)
        {
                Rune r;
                int n;
       t@@ -24,7 +24,7 @@ match(char *name, char *template, char *stem)
                strncpy(stem, name, n);
                stem[n] = 0;
                if(*template == '&')
       -                return !charin(stem, "./");
       +                return !sh->charin(stem, "./");
                return 1;
        }
        
   DIR diff --git a/src/cmd/mk/mk.c b/src/cmd/mk/mk.c
       t@@ -192,14 +192,14 @@ update(int fake, Node *node)
        }
        
        static int
       -pcmp(char *prog, char *p, char *q)
       +pcmp(char *prog, char *p, char *q, Shell *sh, Word *shcmd)
        {
                char buf[3*NAMEBLOCK];
                int pid;
        
                Bflush(&bout);
                snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q);
       -        pid = pipecmd(buf, 0, 0);
       +        pid = pipecmd(buf, 0, 0, sh, shcmd);
                while(waitup(-3, &pid) >= 0)
                        ;
                return(pid? 2:1);
       t@@ -219,7 +219,7 @@ outofdate(Node *node, Arc *arc, int eval)
                        if(sym == 0 || eval){
                                if(sym == 0)
                                        str = strdup(buf);
       -                        ret = pcmp(arc->prog, node->name, arc->n->name);
       +                        ret = pcmp(arc->prog, node->name, arc->n->name, arc->r->shellt, arc->r->shellcmd);
                                if(sym)
                                        sym->value = (void *)ret;
                                else
   DIR diff --git a/src/cmd/mk/mk.h b/src/cmd/mk/mk.h
       t@@ -26,6 +26,18 @@ typedef struct Envy
        
        extern Envy *envy;
        
       +typedef struct Shell
       +{
       +        char *name;
       +        char        *termchars;        /* used in parse.c to isolate assignment attribute */
       +        int        iws;                        /* inter-word separator in environment */
       +        char        *(*charin)(char*, char*);        /* search for unescaped characters */
       +        char        *(*expandquote)(char*, Rune, Bufblock*);        /* extract escaped token */
       +        int        (*escapetoken)(Biobuf*, Bufblock*, int, int);        /* input escaped token */
       +        char        *(*copyq)(char*, Rune, Bufblock*);        /* check for quoted strings */
       +        int        (*matchname)(char*);        /* does name match */
       +} Shell;
       +
        typedef struct Rule
        {
                char                 *target;        /* one target */
       t@@ -40,6 +52,8 @@ typedef struct Rule
                char                *prog;                /* to use in out of date */
                struct Rule        *chain;                /* hashed per target */
                struct Rule        *next;
       +        Shell                *shellt;        /* shell to use with this rule */
       +        Word        *shellcmd;
        } Rule;
        
        extern Rule *rules, *metarules, *patrule;
       t@@ -143,11 +157,10 @@ extern        int        mkinline;
        extern        char        *infile;
        extern        int        nreps;
        extern        char        *explain;
       -extern        char        *termchars;
       -extern        int        IWS;
       -extern        char         *shell;
       -extern        char         *shellname;
       -extern        char         *shflags;
       +extern        Shell        *shellt;
       +extern        Word        *shellcmd;
       +
       +extern        Shell        shshell, rcshell;
        
        #define        SYNERR(l)        (fprint(2, "mk: %s:%d: syntax error; ", infile, ((l)>=0)?(l):mkinline))
        #define        RERR(r)                (fprint(2, "mk: %s:%d: rule error; ", (r)->file, (r)->line))
   DIR diff --git a/src/cmd/mk/mkfile.test b/src/cmd/mk/mkfile.test
       t@@ -1,5 +1,12 @@
       -a: b
       -        cp b a
       +|$PLAN9/bin/rc
       +use-rc:V:
       +        for(i in a b c)
       +                echo $i
       +
       +|/bin/sh
       +use-sh:V:
       +        for i in a b c
       +        do
       +                echo $i
       +        done
        
       -c:V:
       -        echo hello world
   DIR diff --git a/src/cmd/mk/parse.c b/src/cmd/mk/parse.c
       t@@ -17,11 +17,13 @@ parse(char *f, int fd, int varoverride)
                int newfd;
                Biobuf in;
                Bufblock *buf;
       +        char *err;
        
                if(fd < 0){
                        fprint(2, "open %s: %r\n", f);
                        Exit();
                }
       +        pushshell();
                ipush();
                infile = strdup(f);
                mkinline = 1;
       t@@ -52,7 +54,7 @@ parse(char *f, int fd, int varoverride)
                                        Exit();
                                }
                                execinit();
       -                        pid=pipecmd(p, envy, &newfd);
       +                        pid=pipecmd(p, envy, &newfd, shellt, shellcmd);
                                if(newfd < 0){
                                        fprint(2, "warning: skipping missing program file %s: %r\n", p);
                                } else
       t@@ -93,6 +95,14 @@ cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);
                                if(attr)
                                        symlook(head->s, S_NOEXPORT, (void *)"");
                                break;
       +                case 'S':
       +                        if((err = setshell(tail)) != nil){
       +                                SYNERR(hline);
       +                                fprint(2, "%s\n", err);
       +                                Exit();
       +                                break;
       +                        }
       +                        break;
                        default:
                                SYNERR(hline);
                                fprint(2, "expected one of :<=\n");
       t@@ -103,6 +113,7 @@ cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);
                close(fd);
                freebuf(buf);
                ipop();
       +        popshell();
        }
        
        void
       t@@ -114,7 +125,7 @@ addrules(Word *head, Word *tail, char *body, int attr, int hline, char *prog)
                        /* tuck away first non-meta rule as default target*/
                if(target1 == 0 && !(attr&REGEXP)){
                        for(w = head; w; w = w->next)
       -                        if(charin(w->s, "%&"))
       +                        if(shellt->charin(w->s, "%&"))
                                        break;
                        if(w == 0)
                                target1 = wdup(head);
       t@@ -133,19 +144,24 @@ rhead(char *line, Word **h, Word **t, int *attr, char **prog)
                int n;
                Word *w;
        
       -        p = charin(line,":=<");
       -        if(p == 0)
       -                return('?');
       -        sep = *p;
       -        *p++ = 0;
       -        if(sep == '<' && *p == '|'){
       -                sep = '|';
       -                p++;
       +        if(*line == '|'){
       +                sep = 'S';        /* shell */
       +                p = line+1;
       +        }else{
       +                p = shellt->charin(line,":=<");
       +                if(p == 0)
       +                        return('?');
       +                sep = *p;
       +                *p++ = 0;
       +                if(sep == '<' && *p == '|'){
       +                        sep = '|';
       +                        p++;
       +                }
                }
                *attr = 0;
                *prog = 0;
                if(sep == '='){
       -                pp = charin(p, termchars);        /* termchars is shell-dependent */
       +                pp = shellt->charin(p, shellt->termchars);        /* termchars is shell-dependent */
                        if (pp && *pp == '=') {
                                while (p != pp) {
                                        n = chartorune(&r, p);
       t@@ -219,7 +235,7 @@ rhead(char *line, Word **h, Word **t, int *attr, char **prog)
                        }
                }
                *h = w = stow(line);
       -        if(*w->s == 0 && sep != '<' && sep != '|') {
       +        if(*w->s == 0 && sep != '<' && sep != '|' && sep != 'S') {
                        SYNERR(mkinline-1);
                        fprint(2, "no var on left side of assignment/rule\n");
                        Exit();
   DIR diff --git a/src/cmd/mk/rc.c b/src/cmd/mk/rc.c
       t@@ -1,9 +1,5 @@
        #include        "mk.h"
        
       -char        *termchars = "'= \t";        /*used in parse.c to isolate assignment attribute*/
       -char        *shflags = "-I";        /* rc flag to force non-interactive mode */
       -int        IWS = '\1';                /* inter-word separator in env - not used in plan 9 */
       -
        /*
         *        This file contains functions that depend on rc's syntax.  Most
         *        of the routines extract strings observing rc's escape conventions
       t@@ -38,7 +34,7 @@ squote(char *cp)
         *        characters in quotes and variable generators are escaped
         */
        char *
       -charin(char *cp, char *pat)
       +rccharin(char *cp, char *pat)
        {
                Rune r;
                int n, vargen;
       t@@ -82,7 +78,7 @@ charin(char *cp, char *pat)
         *        others are just inserted into the receiving buffer.
         */
        char*
       -expandquote(char *s, Rune r, Bufblock *b)
       +rcexpandquote(char *s, Rune r, Bufblock *b)
        {
                if (r != '\'') {
                        rinsert(b, r);
       t@@ -108,7 +104,7 @@ expandquote(char *s, Rune r, Bufblock *b)
         *        rc; the others are just inserted into the receiving buffer.
         */
        int
       -escapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
       +rcescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
        {
                int c, line;
        
       t@@ -155,7 +151,7 @@ copysingle(char *s, Bufblock *buf)
         *        s points to char after opening quote, q.
         */
        char *
       -copyq(char *s, Rune q, Bufblock *buf)
       +rccopyq(char *s, Rune q, Bufblock *buf)
        {
                if(q == '\'')                                /* copy quoted string */
                        return copysingle(s, buf);
       t@@ -173,3 +169,26 @@ copyq(char *s, Rune q, Bufblock *buf)
                }
                return s;
        }
       +
       +static int
       +rcmatchname(char *name)
       +{
       +        char *p;
       +
       +        if((p = strchr(name, '/')) != nil)
       +                name = p+1;
       +        if(name[0] == 'r' && name[1] == 'c')
       +                return 1;
       +        return 0;
       +}
       +
       +Shell rcshell = {
       +        "rc",
       +        "'= \t",
       +        '\1',
       +        rccharin,
       +        rcexpandquote,
       +        rcescapetoken,
       +        rccopyq,
       +        rcmatchname,
       +};
   DIR diff --git a/src/cmd/mk/rule.c b/src/cmd/mk/rule.c
       t@@ -23,6 +23,8 @@ addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int hline, ch
                }
                if(r == 0)
                        r = (Rule *)Malloc(sizeof(Rule));
       +        r->shellt = shellt;
       +        r->shellcmd = shellcmd;
                r->target = head;
                r->tail = tail;
                r->recipe = body;
       t@@ -42,7 +44,7 @@ addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int hline, ch
                }
                if(!reuse)
                        r->next = 0;
       -        if((attr&REGEXP) || charin(head, "%&")){
       +        if((attr&REGEXP) || shellt->charin(head, "%&")){
                        r->attr |= META;
                        if(reuse)
                                return;
       t@@ -72,7 +74,8 @@ addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int hline, ch
        void
        dumpr(char *s, Rule *r)
        {
       -        Bprint(&bout, "%s: start=%ld\n", s, r);
       +        Bprint(&bout, "%s: start=%ld shelltype=%s shellcmd=%s\n", 
       +                s, r, r->shellt->name, wtos(r->shellcmd, ' '));
                for(; r; r = r->next){
                        Bprint(&bout, "\tRule %ld: %s[%d] attr=%x next=%ld chain=%ld alltarget='%s'",
                                r, r->file, r->line, r->attr, r->next, r->chain, wtos(r->alltargets, ' '));
   DIR diff --git a/src/cmd/mk/run.c b/src/cmd/mk/run.c
       t@@ -59,7 +59,7 @@ sched(void)
                events[slot].job = j;
                buf = newbuf();
                e = buildenv(j, slot);
       -        shprint(j->r->recipe, e, buf);
       +        shprint(j->r->recipe, e, buf, j->r->shellt);
                if(!tflag && (nflag || !(j->r->attr&QUIET)))
                        Bwrite(&bout, buf->start, (long)strlen(buf->start));
                freebuf(buf);
       t@@ -82,7 +82,7 @@ sched(void)
                                flags = 0;
                        else
                                flags = "-e";
       -                events[slot].pid = execsh(flags, j->r->recipe, 0, e);
       +                events[slot].pid = execsh(flags, j->r->recipe, 0, e, j->r->shellt, j->r->shellcmd);
                        usage();
                        nrunning++;
                        if(DEBUG(D_EXEC))
       t@@ -145,7 +145,7 @@ again:                /* rogue processes */
                if(buf[0]){
                        e = buildenv(j, slot);
                        bp = newbuf();
       -                shprint(j->r->recipe, e, bp);
       +                shprint(j->r->recipe, e, bp, j->r->shellt);
                        front(bp->start);
                        fprint(2, "mk: %s: exit status=%s", bp->start, buf);
                        freebuf(bp);
   DIR diff --git a/src/cmd/mk/sh.c b/src/cmd/mk/sh.c
       t@@ -1,9 +1,5 @@
        #include        "mk.h"
        
       -char        *termchars = "\"'= \t";        /*used in parse.c to isolate assignment attribute*/
       -char        *shflags = 0;
       -int        IWS = ' ';                /* inter-word separator in env */
       -
        /*
         *        This file contains functions that depend on the shell's syntax.  Most
         *        of the routines extract strings observing the shell's escape conventions.
       t@@ -34,8 +30,8 @@ squote(char *cp, int c)
        /*
         *        search a string for unescaped characters in a pattern set
         */
       -char *
       -charin(char *cp, char *pat)
       +static char *
       +shcharin(char *cp, char *pat)
        {
                Rune r;
                int n, vargen;
       t@@ -82,8 +78,8 @@ charin(char *cp, char *pat)
         *        extract an escaped token.  Possible escape chars are single-quote,
         *        double-quote,and backslash.
         */
       -char*
       -expandquote(char *s, Rune esc, Bufblock *b)
       +static char*
       +shexpandquote(char *s, Rune esc, Bufblock *b)
        {
                Rune r;
        
       t@@ -110,8 +106,8 @@ expandquote(char *s, Rune esc, Bufblock *b)
         *        Input an escaped token.  Possible escape chars are single-quote,
         *        double-quote and backslash.
         */
       -int
       -escapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
       +static int
       +shescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
        {
                int c, line;
        
       t@@ -168,8 +164,8 @@ copysingle(char *s, Rune q, Bufblock *buf)
         *        check for quoted strings.  backquotes are handled here; single quotes above.
         *        s points to char after opening quote, q.
         */
       -char *
       -copyq(char *s, Rune q, Bufblock *buf)
       +static char *
       +shcopyq(char *s, Rune q, Bufblock *buf)
        {
                if(q == '\'' || q == '"')                /* copy quoted string */
                        return copysingle(s, q, buf);
       t@@ -187,3 +183,24 @@ copyq(char *s, Rune q, Bufblock *buf)
                }
                return s;
        }
       +
       +static int
       +shmatchname(char *name)
       +{
       +        USED(name);
       +
       +        return 1;
       +}
       +
       +
       +Shell shshell = {
       +        "sh",
       +        "\"'= \t",        /*used in parse.c to isolate assignment attribute*/
       +        ' ',        /* inter-word separator in env */
       +        shcharin,
       +        shexpandquote,
       +        shescapetoken,
       +        shcopyq,
       +        shmatchname,
       +};
       +
   DIR diff --git a/src/cmd/mk/shell.c b/src/cmd/mk/shell.c
       t@@ -0,0 +1,76 @@
       +#include "mk.h"
       +
       +static Shell *shells[] = {
       +        &shshell,
       +        &rcshell
       +};
       +
       +Shell *shellt;
       +Word *shellcmd;
       +
       +typedef struct Shellstack Shellstack;
       +struct Shellstack
       +{
       +        Shell *t;
       +        Word *w;
       +        Shellstack *next;
       +};
       +
       +Shellstack *shellstack;
       +
       +char*
       +setshell(Word *w)
       +{
       +        int i;
       +
       +        if(w->s == nil)
       +                return "shell name not found on line";
       +
       +        for(i=0; i<nelem(shells); i++)
       +                if(shells[i]->matchname(w->s))
       +                        break;
       +        if(i == nelem(shells))
       +                return "cannot determine shell type";
       +        shellt = shells[i];
       +        shellcmd = w;
       +        return nil;
       +}
       +
       +void
       +initshell(void)
       +{
       +        shellcmd = stow(shells[0]->name);
       +        shellt = shells[0];
       +}
       +
       +void
       +pushshell(void)
       +{
       +        Shellstack *s;
       +
       +        /* save */
       +        s = Malloc(sizeof *s);
       +        s->t = shellt;
       +        s->w = shellcmd;
       +        s->next = shellstack;
       +        shellstack = s;
       +
       +        initshell();        /* reset to defaults */
       +}
       +
       +void
       +popshell(void)
       +{
       +        Shellstack *s;
       +
       +        if(shellstack == nil){
       +                fprint(2, "internal shellstack error\n");
       +                Exit();
       +        }
       +
       +        s = shellstack;
       +        shellstack = s->next;
       +        shellt = s->t;
       +        shellcmd = s->w;
       +        free(s);
       +}
   DIR diff --git a/src/cmd/mk/shprint.c b/src/cmd/mk/shprint.c
       t@@ -40,7 +40,7 @@ getfields(char *str, char **args, int max, int mflag, char *set)
        }
        
        void
       -shprint(char *s, Envy *env, Bufblock *buf)
       +shprint(char *s, Envy *env, Bufblock *buf, Shell *sh)
        {
                int n;
                Rune r;
       t@@ -52,7 +52,7 @@ shprint(char *s, Envy *env, Bufblock *buf)
                        else {
                                rinsert(buf, r);
                                s += n;
       -                        s = copyq(s, r, buf);        /*handle quoted strings*/
       +                        s = sh->copyq(s, r, buf);        /*handle quoted strings*/
                        }
                }
                insert(buf, 0);
   DIR diff --git a/src/cmd/mk/sys.std.h b/src/cmd/mk/sys.std.h
       t@@ -0,0 +1,22 @@
       +#include <utf.h>
       +#include <fmt.h>
       +#include <bio.h>
       +#include <regexp9.h>
       +#include <stdlib.h>
       +#include <unistd.h>
       +#include <fcntl.h>
       +#include <string.h>
       +#include <ctype.h>
       +#include <time.h>
       +
       +#define OREAD                O_RDONLY
       +#define OWRITE        O_WRONLY
       +#define ORDWR        O_RDWR
       +#define nil 0
       +#define nelem(x) sizeof((x)/sizeof((x)[0]))
       +#define seek lseek
       +#define remove unlink
       +#define exits(x)        exit(x && *(char*)x ? 1 : 0)
       +#define USED(x)        if(x){}else
       +#define create(name, mode, perm)        open(name, mode|O_CREAT, perm)
       +#define ERRMAX        256
   DIR diff --git a/src/cmd/mk/unix.c b/src/cmd/mk/unix.c
       t@@ -51,7 +51,7 @@ readenv(void)
         *        to exec immediately after this.
         */
        void
       -exportenv(Envy *e)
       +exportenv(Envy *e, Shell *sh)
        {
                int i;
                char **p;
       t@@ -61,7 +61,7 @@ exportenv(Envy *e)
                for(i = 0; e->name; e++, i++) {
                        p = (char**) Realloc(p, (i+2)*sizeof(char*));
                        if(e->values)
       -                        snprint(buf, sizeof buf, "%s=%s", e->name,  wtos(e->values, IWS));
       +                        snprint(buf, sizeof buf, "%s=%s", e->name,  wtos(e->values, sh->iws));
                        else
                                snprint(buf, sizeof buf, "%s=", e->name);
                        p[i] = strdup(buf);
       t@@ -102,9 +102,29 @@ expunge(int pid, char *msg)
        int mypid;
        
        int
       -execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
       +shargv(Word *cmd, int extra, char ***pargv)
        {
       -        char *p;
       +        char **argv;
       +        int i, n;
       +        Word *w;
       +
       +        n = 0;
       +        for(w=cmd; w; w=w->next)
       +                n++;
       +        
       +        argv = Malloc((n+extra+1)*sizeof(argv[0]));
       +        i = 0;
       +        for(w=cmd; w; w=w->next)
       +                argv[i++] = w->s;
       +        argv[n] = 0;
       +        *pargv = argv;
       +        return n;
       +}        
       +
       +int
       +execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)
       +{
       +        char *p, **argv;
                int tot, n, pid, in[2], out[2];
        
                if(buf && pipe(out) < 0){
       t@@ -138,11 +158,11 @@ execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
                                close(in[0]);
                                close(in[1]);
                                if (e)
       -                                exportenv(e);
       -                        if(shflags)
       -                                execl(shell, shellname, shflags, args, 0);
       -                        else
       -                                execl(shell, shellname, args, 0);
       +                                exportenv(e, sh);
       +                        n = shargv(shellcmd, 1, &argv);
       +                        argv[n++] = args;
       +                        argv[n] = 0;
       +                        execvp(argv[0], argv);
                                mkperror(shell);
                                _exit(1);
                        }
       t@@ -180,9 +200,11 @@ execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
        }
        
        int
       -pipecmd(char *cmd, Envy *e, int *fd)
       +pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd)
        {
                int pid, pfd[2];
       +        int n;
       +        char **argv;
        
                if(DEBUG(D_EXEC))
                        fprint(1, "pipecmd='%s'\n", cmd);/**/
       t@@ -203,11 +225,12 @@ pipecmd(char *cmd, Envy *e, int *fd)
                                close(pfd[1]);
                        }
                        if(e)
       -                        exportenv(e);
       -                if(shflags)
       -                        execl(shell, shellname, shflags, "-c", cmd, 0);
       -                else
       -                        execl(shell, shellname, "-c", cmd, 0);
       +                        exportenv(e, sh);
       +                n = shargv(shellcmd, 2, &argv);
       +                argv[n++] = "-c";
       +                argv[n++] = cmd;
       +                argv[n] = 0;
       +                execvp(argv[0], argv);
                        mkperror(shell);
                        _exit(1);
                }
   DIR diff --git a/src/cmd/mk/varsub.c b/src/cmd/mk/varsub.c
       t@@ -103,7 +103,7 @@ expandvar(char **s)
                        return 0;
                }
                cp++;
       -        end = charin(cp , "}");
       +        end = shellt->charin(cp , "}");
                if(end == 0){
                        SYNERR(-1);
                        fprint(2, "missing '}': %s\n", begin);
       t@@ -128,7 +128,7 @@ extractpat(char *s, char **r, char *term, char *end)
                char *cp;
                Word *w;
        
       -        cp = charin(s, term);
       +        cp = shellt->charin(s, term);
                if(cp){
                        *r = cp;
                        if(cp == s)
   DIR diff --git a/src/cmd/mk/word.c b/src/cmd/mk/word.c
       t@@ -114,7 +114,7 @@ nextword(char **s)
                        case '\\':
                        case '\'':
                        case '"':
       -                        cp = expandquote(cp, r, b);
       +                        cp = shellt->expandquote(cp, r, b);
                                if(cp == 0){
                                        fprint(2, "missing closing quote: %s\n", *s);
                                        Exit();