tmaintain $path and $PATH simultaneously - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit a9eaaa03e043ba8e1b2f67d7c8c7ba471db6ba4b
 (DIR) parent 7b0c2f155dc4ac20d65c6a9899ae223053379fcd
 (HTM) Author: rsc <devnull@localhost>
       Date:   Wed, 12 Jan 2005 16:59:50 +0000
       
       maintain $path and $PATH simultaneously
       
       Diffstat:
         M src/cmd/rc/exec.c                   |      10 ++++++++--
         M src/cmd/rc/fns.h                    |       3 +++
         M src/cmd/rc/rc.h                     |       1 +
         M src/cmd/rc/simple.c                 |       2 +-
         M src/cmd/rc/var.c                    |      62 ++++++++++++++++++++++++++++++-
       
       5 files changed, 74 insertions(+), 4 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c
       t@@ -117,6 +117,7 @@ main(int argc, char *argv[])
                Trapinit();
                Vinit();
                itoa(num, mypid=getpid());
       +        pathinit();
                setvar("pid", newword(num, (word *)0));
                setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
                                        :(word *)0);
       t@@ -369,7 +370,7 @@ void Xwrite(void){
                runq->pc++;
                poplist();
        }
       -char *list2str(word *words){
       +char *_list2str(word *words, int c){
                char *value, *s, *t;
                int len=0;
                word *ap;
       t@@ -379,12 +380,15 @@ char *list2str(word *words){
                s=value;
                for(ap=words;ap;ap=ap->next){
                        for(t=ap->word;*t;) *s++=*t++;
       -                *s++=' ';
       +                *s++=c;
                }
                if(s==value) *s='\0';
                else s[-1]='\0';
                return value;
        }
       +char *list2str(word *words){
       +        return _list2str(words, ' ');
       +}
        void Xmatch(void){
                word *p;
                char *subject;
       t@@ -464,6 +468,8 @@ void Xassign(void){
                freewords(v->val);
                v->val=runq->argv->words;
                v->changed=1;
       +        if(v->changefn)
       +                v->changefn(v);
                runq->argv->words=0;
                poplist();
        }
 (DIR) diff --git a/src/cmd/rc/fns.h b/src/cmd/rc/fns.h
       t@@ -27,6 +27,7 @@ void        cleanhere(char*);
        void        codefree(code*);
        int        compile(tree*);
        char *        list2str(word*);
       +char *        _list2str(word*, int);
        int        count(word*);
        void        deglob(char*);
        void        dotrap(void);
       t@@ -39,6 +40,7 @@ void        kinit(void);
        int        match(char*, char*, int);
        int        matchfn(char*, char*);
        void        panic(char*, int);
       +void        pathinit(void);
        void        poplist(void);
        void        popword(void);
        void        pprompt(void);
       t@@ -48,6 +50,7 @@ void        pushword(char*);
        void        readhere(void);
        void        setstatus(char*);
        void        setvar(char*, word*);
       +void        _setvar(char*, word*, int);
        void        skipnl(void);
        void        start(code*, int, var*);
        int        truestatus(void);
 (DIR) diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h
       t@@ -84,6 +84,7 @@ struct var{
                int fnchanged;
                int pc;                        /* pc of start of function */
                var *next;        /* next on hash or local list */
       +        void        (*changefn)(var*);
        };
        var *vlook(char*), *gvlook(char*), *newvar(char*, var*);
        #define        NVAR        521
 (DIR) diff --git a/src/cmd/rc/simple.c b/src/cmd/rc/simple.c
       t@@ -168,7 +168,7 @@ void execcd(void){
                        if(cdpath==0) pfmt(err, "Can't cd %s: %r\n", a->next->word);
                        break;
                case 1:
       -                a=vlook("home")->val;
       +                a=vlook("HOME")->val;
                        if(count(a)>=1){
                                if(dochdir(a->word)>=0)
                                        setstatus("");
 (DIR) diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c
       t@@ -62,10 +62,70 @@ var *vlook(char *name)
                                if(strcmp(v->name, name)==0) return v;
                return gvlook(name);
        }
       -void setvar(char *name, word *val)
       +void _setvar(char *name, word *val, int callfn)
        {
                register struct var *v=vlook(name);
                freewords(v->val);
                v->val=val;
                v->changed=1;
       +        if(callfn && v->changefn)
       +                v->changefn(v);
       +}
       +void setvar(char *name, word *val)
       +{
       +        _setvar(name, val, 1);
       +}
       +void bigpath(var *v)
       +{
       +        /* convert $PATH to $path */
       +        char *p, *q;
       +        word **l, *w;
       +
       +        if(v->val == nil){
       +                _setvar("path", nil, 0);
       +                return;
       +        }
       +        p = v->val->word;
       +        w = nil;
       +        l = &w;
       +        /*
       +         * Doesn't handle escaped colon nonsense.
       +         */
       +        if(p[0] == 0)
       +                p = nil;
       +        while(p){
       +                q = strchr(p, ':');
       +                if(q)
       +                        *q = 0;
       +                *l = newword(p[0] ? p : ".", nil);
       +                l = &(*l)->next;
       +                if(q){
       +                        *q = ':';
       +                        p = q+1;
       +                }else
       +                        p = nil;
       +        }
       +        _setvar("path", w, 0);
       +}
       +void littlepath(var *v)
       +{
       +        /* convert $path to $PATH */
       +        char *p;
       +        word *w;
       +
       +        p = _list2str(v->val, ':');
       +        w = new(word);
       +        w->word = p;
       +        w->next = nil;
       +        _setvar("PATH", w, 1);        /* 1: recompute $path to expose colon problems */
       +}
       +void pathinit(void)
       +{
       +        var *v;
       +
       +        v = gvlook("path");
       +        v->changefn = littlepath;
       +        v = gvlook("PATH");
       +        v->changefn = bigpath;
       +        bigpath(v);
        }