tmissing programs - 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 6e2cec77b292cc2285e369ec01faa877ea91dbdd
 (DIR) parent 34ca7ee3bff4fca54164345f20a16a1958bddcc2
 (HTM) Author: rsc <devnull@localhost>
       Date:   Tue,  2 Mar 2004 16:55:27 +0000
       
       missing programs
       
       Diffstat:
         A src/cmd/fortune.c                   |      90 +++++++++++++++++++++++++++++++
         A src/cmd/win.c                       |     656 +++++++++++++++++++++++++++++++
       
       2 files changed, 746 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/fortune.c b/src/cmd/fortune.c
       t@@ -0,0 +1,90 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <bio.h>
       +
       +#define index findex
       +char choice[2048];
       +char index[] = "/sys/games/lib/fortunes.index";
       +char fortunes[] = "/sys/games/lib/fortunes";
       +
       +#define lrand rand
       +
       +void
       +main(int argc, char *argv[])
       +{
       +        int i;
       +        long offs;
       +        uchar off[4];
       +        int ix, nix;
       +        int newindex, oldindex;
       +        char *p;
       +        Dir *fbuf, *ixbuf;
       +        Biobuf *f, g;
       +
       +        newindex = 0;
       +        oldindex = 0;
       +        ix = offs = 0;
       +        if((f=Bopen(argc>1?argv[1]:fortunes, OREAD)) == 0){
       +                print("Misfortune!\n");
       +                exits("misfortune");
       +        }
       +        ixbuf = nil;
       +        if(argc == 1){
       +                ix = open(index, OREAD);
       +                if(ix>=0){
       +                        oldindex = 1;
       +                        ixbuf = dirfstat(ix);
       +                        fbuf = dirfstat(Bfildes(f));
       +                        if(ixbuf == nil || fbuf == nil){
       +                                print("Misfortune?\n");
       +                                exits("misfortune");
       +                        }
       +                        if(fbuf->mtime > ixbuf->mtime){
       +                                nix = create(index, OWRITE, 0666);
       +                                if(nix >= 0){
       +                                        close(ix);
       +                                        ix = nix;
       +                                        newindex = 1;
       +                                        oldindex = 0;
       +                                }
       +                        }
       +                }else{
       +                        ix = create(index, OWRITE, 0666);
       +                        if(ix >= 0)
       +                                newindex = 1;
       +                }
       +        }
       +        if(oldindex){
       +                seek(ix, lrand()%(ixbuf->length/sizeof(offs))*sizeof(offs), 0);
       +                read(ix, off, sizeof(off));
       +                Bseek(f, off[0]|(off[1]<<8)|(off[2]<<16)|(off[3]<<24), 0);
       +                p = Brdline(f, '\n');
       +                if(p){
       +                        p[Blinelen(f)-1] = 0;
       +                        strcpy(choice, p);
       +                }else
       +                        strcpy(choice, "Misfortune!");
       +        }else{
       +                Binit(&g, ix, 1);
       +                srand(getpid());
       +                for(i=1;;i++){
       +                        if(newindex)
       +                                offs = Boffset(f);
       +                        p = Brdline(f, '\n');
       +                        if(p == 0)
       +                                break;
       +                        p[Blinelen(f)-1] = 0;
       +                        if(newindex){
       +                                off[0] = offs;
       +                                off[1] = offs>>8;
       +                                off[2] = offs>>16;
       +                                off[3] = offs>>24;
       +                                Bwrite(&g, off, sizeof(off));
       +                        }
       +                        if(lrand()%i==0)
       +                                strcpy(choice, p);
       +                }
       +        }
       +        print("%s\n", choice);
       +        exits(0);
       +}
 (DIR) diff --git a/src/cmd/win.c b/src/cmd/win.c
       t@@ -0,0 +1,656 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <thread.h>
       +#include <fcall.h>
       +#include <fs.h>
       +
       +#define        EVENTSIZE        256
       +#define        STACK        32768
       +
       +typedef struct Event Event;
       +typedef struct Q Q;
       +
       +struct Event
       +{
       +        int        c1;
       +        int        c2;
       +        int        q0;
       +        int        q1;
       +        int        flag;
       +        int        nb;
       +        int        nr;
       +        char        b[EVENTSIZE*UTFmax+1];
       +        Rune        r[EVENTSIZE+1];
       +};
       +
       +Event blank = {
       +        'M',
       +        'X',
       +        0, 0, 0, 1, 1,
       +        { ' ', 0 },
       +        { ' ', 0 },
       +};
       +
       +struct Q
       +{
       +        QLock        lk;
       +        int                p;
       +        int                k;
       +};
       +
       +Q        q;
       +
       +int eventfd;
       +int addrfd;
       +int datafd;
       +int ctlfd;
       +int bodyfd;
       +
       +char        *typing;
       +int        ntypeb;
       +int        ntyper;
       +int        ntypebreak;
       +int        debug;
       +
       +char **prog;
       +int p[2];
       +Channel *cpid;
       +int pid = -1;
       +
       +void        error(char*);
       +void        stdinproc(void*);
       +void        stdoutproc(void*);
       +void        type(Event*, int, int, int);
       +void        sende(Event*, int, int, int, int, int);
       +char        *onestring(int, char**);
       +int        delete(Event*);
       +void        deltype(uint, uint);
       +void        runproc(void*);
       +
       +void
       +usage(void)
       +{
       +        fprint(2, "usage: win cmd args...\n");
       +        threadexitsall("usage");
       +}
       +
       +int
       +nopipes(void *v, char *msg)
       +{
       +        USED(v);
       +        if(strcmp(msg, "sys: write on closed pipe") == 0)
       +                return 1;
       +        return 0;
       +}
       +
       +void
       +threadmain(int argc, char **argv)
       +{
       +        int fd, id;
       +        char buf[256];
       +        char buf1[128];
       +        char *name;
       +        Fsys *fs;
       +
       +        ARGBEGIN{
       +        case 'd':
       +                debug = 1;
       +                break;
       +        default:
       +                usage();
       +        }ARGEND
       +
       +        prog = argv;
       +
       +        if(argc > 0)
       +                name = argv[0];
       +        else
       +                name = "gnot";
       +
       +        threadnotify(nopipes, 1);
       +        if((fs = nsmount("acme", "")) < 0)
       +                sysfatal("nsmount acme: %r");
       +        ctlfd = fsopenfd(fs, "new/ctl", ORDWR|OCEXEC);
       +        if(ctlfd < 0 || read(ctlfd, buf, 12) != 12)
       +                sysfatal("ctl: %r");
       +        id = atoi(buf);
       +        sprint(buf, "%d/tag", id);
       +        fd = fsopenfd(fs, buf, OWRITE|OCEXEC);
       +        write(fd, " Send Delete", 12);
       +        close(fd);
       +        sprint(buf, "%d/event", id);
       +        eventfd = fsopenfd(fs, buf, ORDWR|OCEXEC);
       +        sprint(buf, "%d/addr", id);
       +        addrfd = fsopenfd(fs, buf, ORDWR|OCEXEC);
       +        sprint(buf, "%d/data", id);
       +        datafd = fsopenfd(fs, buf, ORDWR|OCEXEC);
       +        sprint(buf, "%d/body", id);
       +        bodyfd = fsopenfd(fs, buf, ORDWR|OCEXEC);
       +        if(eventfd<0 || addrfd<0 || datafd<0 || bodyfd<0)
       +                sysfatal("data files: %r");
       +        fsunmount(fs);
       +
       +        if(pipe(p) < 0)
       +                sysfatal("pipe: %r");
       +
       +        cpid = chancreate(sizeof(ulong), 1);
       +        threadcreate(runproc, nil, STACK);
       +        pid = recvul(cpid);
       +        if(pid == -1)
       +                sysfatal("exec failed");
       +
       +        getwd(buf1, sizeof buf1);
       +        sprint(buf, "name %s/-%s\n0\n", buf1, name);
       +        write(ctlfd, buf, strlen(buf));
       +        sprint(buf, "dumpdir %s/\n", buf1);
       +        write(ctlfd, buf, strlen(buf));
       +        sprint(buf, "dump %s\n", onestring(argc, argv));
       +        write(ctlfd, buf, strlen(buf));
       +        
       +//        proccreate(stdoutproc, nil, STACK);
       +        stdinproc(nil);
       +}
       +
       +char *shell[] = { "rc", "-i", 0 };
       +void
       +runproc(void *v)
       +{
       +        int fd[3];
       +        char *sh;
       +
       +        USED(v);
       +
       +        fd[0] = p[1];
       +        fd[1] = bodyfd;
       +        fd[2] = bodyfd;
       +//        fd[1] = p[1];
       +//        fd[2] = p[1];
       +
       +        if(prog[0] == nil){
       +                prog = shell;
       +                if((sh = getenv("SHELL")) != nil)
       +                        shell[0] = sh;
       +        }
       +        threadexec(cpid, fd, prog[0], prog);
       +        threadexits(nil);
       +}
       +
       +void
       +error(char *s)
       +{
       +        if(s)
       +                fprint(2, "win: %s: %r\n", s);
       +        else
       +                s = "kill";
       +        if(pid != -1)
       +                postnote(PNGROUP, pid, "hangup");
       +        threadexitsall(s);
       +}
       +
       +char*
       +onestring(int argc, char **argv)
       +{
       +        char *p;
       +        int i, n;
       +        static char buf[1024];
       +
       +        if(argc == 0)
       +                return "";
       +        p = buf;
       +        for(i=0; i<argc; i++){
       +                n = strlen(argv[i]);
       +                if(p+n+1 >= buf+sizeof buf)
       +                        break;
       +                memmove(p, argv[i], n);
       +                p += n;
       +                *p++ = ' ';
       +        }
       +        p[-1] = 0;
       +        return buf;
       +}
       +
       +int
       +getec(int efd)
       +{
       +        static char buf[8192];
       +        static char *bufp;
       +        static int nbuf;
       +
       +        if(nbuf == 0){
       +                nbuf = read(efd, buf, sizeof buf);
       +                if(nbuf <= 0)
       +                        error(nil);
       +                bufp = buf;
       +        }
       +        --nbuf;
       +        return *bufp++;
       +}
       +
       +int
       +geten(int efd)
       +{
       +        int n, c;
       +
       +        n = 0;
       +        while('0'<=(c=getec(efd)) && c<='9')
       +                n = n*10+(c-'0');
       +        if(c != ' ')
       +                error("event number syntax");
       +        return n;
       +}
       +
       +int
       +geter(int efd, char *buf, int *nb)
       +{
       +        Rune r;
       +        int n;
       +
       +        r = getec(efd);
       +        buf[0] = r;
       +        n = 1;
       +        if(r < Runeself)
       +                goto Return;
       +        while(!fullrune(buf, n))
       +                buf[n++] = getec(efd);
       +        chartorune(&r, buf);
       +    Return:
       +        *nb = n;
       +        return r;
       +}
       +
       +void
       +gete(int efd, Event *e)
       +{
       +        int i, nb;
       +
       +        e->c1 = getec(efd);
       +        e->c2 = getec(efd);
       +        e->q0 = geten(efd);
       +        e->q1 = geten(efd);
       +        e->flag = geten(efd);
       +        e->nr = geten(efd);
       +        if(e->nr > EVENTSIZE)
       +                error("event string too long");
       +        e->nb = 0;
       +        for(i=0; i<e->nr; i++){
       +                e->r[i] = geter(efd, e->b+e->nb, &nb);
       +                e->nb += nb;
       +        }
       +        e->r[e->nr] = 0;
       +        e->b[e->nb] = 0;
       +        if(getec(efd) != '\n')
       +                error("event syntax 2");
       +}
       +
       +int
       +nrunes(char *s, int nb)
       +{
       +        int i, n;
       +        Rune r;
       +
       +        n = 0;
       +        for(i=0; i<nb; n++)
       +                i += chartorune(&r, s+i);
       +        return n;
       +}
       +
       +void
       +stdinproc(void *v)
       +{
       +        int cfd = ctlfd;
       +        int efd = eventfd;
       +        int dfd = datafd;
       +        int afd = addrfd;
       +        int fd0 = p[0];
       +        Event e, e2, e3, e4;
       +
       +        USED(v);
       +
       +        for(;;){
       +                if(debug)
       +                        fprint(2, "typing[%d,%d)\n", q.p, q.p+ntyper);
       +                gete(efd, &e);
       +                if(debug)
       +                        fprint(2, "msg %c%c q[%d,%d)... ", e.c1, e.c2, e.q0, e.q1);
       +                qlock(&q.lk);
       +                switch(e.c1){
       +                default:
       +                Unknown:
       +                        print("unknown message %c%c\n", e.c1, e.c2);
       +                        break;
       +
       +                case 'E':        /* write to body; can't affect us */
       +                        if(debug)
       +                                fprint(2, "shift typing %d... ", e.q1-e.q0);
       +                        q.p += e.q1-e.q0;
       +                        break;
       +
       +                case 'F':        /* generated by our actions; ignore */
       +                        break;
       +
       +                case 'K':
       +                case 'M':
       +                        switch(e.c2){
       +                        case 'I':
       +                                if(e.q0 < q.p){
       +                                        if(debug)
       +                                                fprint(2, "shift typing %d... ", e.q1-e.q0);
       +                                        q.p += e.q1-e.q0;
       +                                }
       +                                else if(e.q0 <= q.p+ntyper){
       +                                        if(debug)
       +                                                fprint(2, "type... ");
       +                                        type(&e, fd0, afd, dfd);
       +                                }
       +                                break;
       +
       +                        case 'D':
       +                                q.p -= delete(&e);
       +                                break;
       +
       +                        case 'x':
       +                        case 'X':
       +                                if(e.flag & 2)
       +                                        gete(efd, &e2);
       +                                if(e.flag & 8){
       +                                        gete(efd, &e3);
       +                                        gete(efd, &e4);
       +                                }
       +                                if(e.flag&1 || (e.c2=='x' && e.nr==0 && e2.nr==0)){
       +                                        /* send it straight back */
       +                                        fprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
       +                                        break;
       +                                }
       +                                if(e.q0==e.q1 && (e.flag&2)){
       +                                        e2.flag = e.flag;
       +                                        e = e2;
       +                                }
       +                                if(e.flag & 8){
       +                                        if(e.q1 != e.q0){
       +                                                sende(&e, fd0, cfd, afd, dfd, 0);
       +                                                sende(&blank, fd0, cfd, afd, dfd, 0);
       +                                        }
       +                                        sende(&e3, fd0, cfd, afd, dfd, 1);
       +                                }else         if(e.q1 != e.q0)
       +                                        sende(&e, fd0, cfd, afd, dfd, 1);
       +                                break;
       +
       +                        case 'l':
       +                        case 'L':
       +                                /* just send it back */
       +                                if(e.flag & 2)
       +                                        gete(efd, &e2);
       +                                fprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
       +                                break;
       +
       +                        case 'd':
       +                        case 'i':
       +                                break;
       +
       +                        default:
       +                                goto Unknown;
       +                        }
       +                }
       +                qunlock(&q.lk);
       +        }
       +}
       +
       +void
       +stdoutproc(void *v)
       +{
       +        int fd1 = p[0];
       +        int afd = addrfd;
       +        int dfd = datafd;
       +        int n, m, w, npart;
       +        char *buf, *s, *t;
       +        Rune r;
       +        char x[16], hold[UTFmax];
       +
       +        USED(v);
       +        threadnotify(nopipes, 1);
       +        buf = malloc(8192+UTFmax+1);
       +        npart = 0;
       +        for(;;){
       +                n = read(fd1, buf+npart, 8192);
       +                if(n < 0)
       +                        error(nil);
       +                if(n == 0)
       +                        continue;
       +
       +                /* squash NULs */
       +                s = memchr(buf+npart, 0, n);
       +                if(s){
       +                        for(t=s; s<buf+npart+n; s++)
       +                                if(*t = *s)        /* assign = */
       +                                        t++;
       +                        n = t-(buf+npart);
       +                }
       +
       +                n += npart;
       +
       +                /* hold on to final partial rune */
       +                npart = 0;
       +                while(n>0 && (buf[n-1]&0xC0)){
       +                        --n;
       +                        npart++;
       +                        if((buf[n]&0xC0)!=0x80){
       +                                if(fullrune(buf+n, npart)){
       +                                        w = chartorune(&r, buf+n);
       +                                        n += w;
       +                                        npart -= w;
       +                                }
       +                                break;
       +                        }
       +                }
       +                if(n > 0){
       +                        memmove(hold, buf+n, npart);
       +                        buf[n] = 0;
       +                        qlock(&q.lk);
       +                        m = sprint(x, "#%d", q.p);
       +                        if(write(afd, x, m) != m)
       +                                error("stdout writing address");
       +                        if(write(dfd, buf, n) != n)
       +                                error("stdout writing body");
       +                        q.p += nrunes(buf, n);
       +                        qunlock(&q.lk);
       +                        memmove(buf, hold, npart);
       +                }
       +        }
       +}
       +
       +int
       +delete(Event *e)
       +{
       +        uint q0, q1;
       +        int deltap;
       +
       +        q0 = e->q0;
       +        q1 = e->q1;
       +        if(q1 <= q.p)
       +                return e->q1-e->q0;
       +        if(q0 >= q.p+ntyper)
       +                return 0;
       +        deltap = 0;
       +        if(q0 < q.p){
       +                deltap = q.p-q0;
       +                q0 = 0;
       +        }else
       +                q0 -= q.p;
       +        if(q1 > q.p+ntyper)
       +                q1 = ntyper;
       +        else
       +                q1 -= q.p;
       +        deltype(q0, q1);
       +        return deltap;
       +}
       +
       +void
       +addtype(int c, uint p0, char *b, int nb, int nr)
       +{
       +        int i, w;
       +        Rune r;
       +        uint p;
       +        char *b0;
       +
       +        for(i=0; i<nb; i+=w){
       +                w = chartorune(&r, b+i);
       +                if((r==0x7F||r==3) && c=='K'){
       +                        postnote(PNGROUP, pid, "interrupt");
       +                        /* toss all typing */
       +                        q.p += ntyper+nr;
       +                        ntypebreak = 0;
       +                        ntypeb = 0;
       +                        ntyper = 0;
       +                        /* buglet:  more than one delete ignored */
       +                        return;
       +                }
       +                if(r=='\n' || r==0x04)
       +                        ntypebreak++;
       +        }
       +        typing = realloc(typing, ntypeb+nb);
       +        if(typing == nil)
       +                error("realloc");
       +        if(p0 == ntyper)
       +                memmove(typing+ntypeb, b, nb);
       +        else{
       +                b0 = typing;
       +                for(p=0; p<p0 && b0<typing+ntypeb; p++){
       +                        w = chartorune(&r, b0+i);
       +                        b0 += w;
       +                }
       +                if(p != p0)
       +                        error("typing: findrune");
       +                memmove(b0+nb, b0, (typing+ntypeb)-b0);
       +                memmove(b0, b, nb);
       +        }
       +        ntypeb += nb;
       +        ntyper += nr;
       +}
       +
       +void
       +sendtype(int fd0)
       +{
       +        int i, n, nr;
       +
       +        while(ntypebreak){
       +                for(i=0; i<ntypeb; i++)
       +                        if(typing[i]=='\n' || typing[i]==0x04){
       +                                n = i + (typing[i] == '\n');
       +                                i++;
       +                                if(write(fd0, typing, n) != n)
       +                                        error("sending to program");
       +                                nr = nrunes(typing, i);
       +                                q.p += nr;
       +                                ntyper -= nr;
       +                                ntypeb -= i;
       +                                memmove(typing, typing+i, ntypeb);
       +                                ntypebreak--;
       +                                goto cont2;
       +                        }
       +                print("no breakchar\n");
       +                ntypebreak = 0;
       +cont2:
       +        }
       +}
       +
       +void
       +deltype(uint p0, uint p1)
       +{
       +        int w;
       +        uint p, b0, b1;
       +        Rune r;
       +
       +        /* advance to p0 */
       +        b0 = 0;
       +        for(p=0; p<p0 && b0<ntypeb; p++){
       +                w = chartorune(&r, typing+b0);
       +                b0 += w;
       +        }
       +        if(p != p0)
       +                error("deltype 1");
       +        /* advance to p1 */
       +        b1 = b0;
       +        for(; p<p1 && b1<ntypeb; p++){
       +                w = chartorune(&r, typing+b1);
       +                b1 += w;
       +                if(r=='\n' || r==0x04)
       +                        ntypebreak--;
       +        }
       +        if(p != p1)
       +                error("deltype 2");
       +        memmove(typing+b0, typing+b1, ntypeb-b1);
       +        ntypeb -= b1-b0;
       +        ntyper -= p1-p0;
       +}
       +
       +void
       +type(Event *e, int fd0, int afd, int dfd)
       +{
       +        int m, n, nr;
       +        char buf[128];
       +
       +        if(e->nr > 0)
       +                addtype(e->c1, e->q0-q.p, e->b, e->nb, e->nr);
       +        else{
       +                m = e->q0;
       +                while(m < e->q1){
       +                        n = sprint(buf, "#%d", m);
       +                        write(afd, buf, n);
       +                        n = read(dfd, buf, sizeof buf);
       +                        nr = nrunes(buf, n);
       +                        while(m+nr > e->q1){
       +                                do; while(n>0 && (buf[--n]&0xC0)==0x80);
       +                                --nr;
       +                        }
       +                        if(n == 0)
       +                                break;
       +                        addtype(e->c1, m-q.p, buf, n, nr);
       +                        m += nr;
       +                }
       +        }
       +        sendtype(fd0);
       +}
       +
       +void
       +sende(Event *e, int fd0, int cfd, int afd, int dfd, int donl)
       +{
       +        int l, m, n, nr, lastc, end;
       +        char abuf[16], buf[128];
       +
       +        end = q.p+ntyper;
       +        l = sprint(abuf, "#%d", end);
       +        write(afd, abuf, l);
       +        if(e->nr > 0){
       +                write(dfd, e->b, e->nb);
       +                addtype(e->c1, ntyper, e->b, e->nb, e->nr);
       +                lastc = e->r[e->nr-1];
       +        }else{
       +                m = e->q0;
       +                lastc = 0;
       +                while(m < e->q1){
       +                        n = sprint(buf, "#%d", m);
       +                        write(afd, buf, n);
       +                        n = read(dfd, buf, sizeof buf);
       +                        nr = nrunes(buf, n);
       +                        while(m+nr > e->q1){
       +                                do; while(n>0 && (buf[--n]&0xC0)==0x80);
       +                                --nr;
       +                        }
       +                        if(n == 0)
       +                                break;
       +                        l = sprint(abuf, "#%d", end);
       +                        write(afd, abuf, l);
       +                        write(dfd, buf, n);
       +                        addtype(e->c1, ntyper, buf, n, nr);
       +                        lastc = buf[n-1];
       +                        m += nr;
       +                        end += nr;
       +                }
       +        }
       +        if(donl && lastc!='\n'){
       +                write(dfd, "\n", 1);
       +                addtype(e->c1, ntyper, "\n", 1, 1);
       +        }
       +        write(cfd, "dot=addr", 8);
       +        sendtype(fd0);
       +}