diff --git a/src/cmd/fortune.c b/src/cmd/fortune.c new file mode 100644 index 00000000..f3acfca2 --- /dev/null +++ b/src/cmd/fortune.c @@ -0,0 +1,90 @@ +#include +#include +#include + +#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); +} diff --git a/src/cmd/win.c b/src/cmd/win.c new file mode 100644 index 00000000..ef8b7b61 --- /dev/null +++ b/src/cmd/win.c @@ -0,0 +1,656 @@ +#include +#include +#include +#include +#include + +#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= 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; inr; 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; i0 && (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; inr > 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); +}