static void connproc(void *v) { VtSconn *sc; VtConn *c; Packet *p; VtReq *r; int fd; static int first=1; if(first && chattyventi){ first=0; fmtinstall('F', vtfcallfmt); } r = nil; sc = v; sc->c = nil; if(0) fprint(2, "new call %s on %d\n", sc->dir, sc->ctl); fd = accept(sc->ctl, sc->dir); close(sc->ctl); if(fd < 0){ fprint(2, "accept %s: %r\n", sc->dir); goto out; } c = vtconn(fd, fd); sc->c = c; if(vtversion(c) < 0){ fprint(2, "vtversion %s: %r\n", sc->dir); goto out; } if(vtsrvhello(c) < 0){ fprint(2, "vtsrvhello %s: %r\n", sc->dir); goto out; } if(0) fprint(2, "new proc %s\n", sc->dir); proccreate(vtsendproc, c, STACK); qlock(&c->lk); while(!c->writeq) rsleep(&c->rpcfork); qunlock(&c->lk); while((p = vtrecv(c)) != nil){ r = vtmallocz(sizeof(VtReq)); if(vtfcallunpack(&r->tx, p) < 0){ vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv bad packet %p: %r<br>\n", c->addr, p); fprint(2, "bad packet on %s: %r\n", sc->dir); packetfree(p); continue; } vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv packet %p (%F)<br>\n", c->addr, p, &r->tx); if(chattyventi) fprint(2, "%s <- %F\n", argv0, &r->tx); packetfree(p); if(r->tx.msgtype == VtTgoodbye) break; r->rx.tag = r->tx.tag; r->sc = sc; scincref(sc); if(_vtqsend(sc->srv->q, r) < 0){ scdecref(sc); fprint(2, "hungup queue\n"); break; } r = nil; } if(0) fprint(2, "eof on %s\n", sc->dir); out: if(r){ vtfcallclear(&r->tx); vtfree(r); } if(0) fprint(2, "freed %s\n", sc->dir); scdecref(sc); return; }
int ethermain(Dev *dev, int argc, char **argv) { int epin, epout, i, devid; Ether *e; uchar ea[Eaddrlen]; devid = dev->id; memset(ea, 0, Eaddrlen); ARGBEGIN{ case 'a': if(parseaddr(ea, EARGF(usage())) < 0) return usage(); break; case 'd': if(etherdebug == 0) fprint(2, "ether debug on\n"); etherdebug++; break; case 'N': devid = atoi(EARGF(usage())); break; default: return usage(); }ARGEND if(argc != 0) { return usage(); } e = dev->aux = emallocz(sizeof(Ether), 1); e->dev = dev; dev->free = etherdevfree; memmove(e->addr, ea, Eaddrlen); e->name = "cdc"; for(i = 0; i < nelem(ethers); i++) if(ethers[i](e) == 0) break; if(i == nelem(ethers)) return -1; if(e->init == nil) e->init = etherinit; if(e->init(e, &epin, &epout) < 0) return -1; if(e->bwrite == nil) e->bwrite = etherbwrite; if(e->bread == nil) e->bread = etherbread; if(e->bufsize == 0) e->bufsize = Maxpkt; if(openeps(e, epin, epout) < 0) return -1; if(kernelproxy(e) == 0) return 0; e->fs = etherfs; snprint(e->fs.name, sizeof(e->fs.name), "etherU%d", devid); e->fs.dev = dev; e->fs.aux = e; e->bc = chancreate(sizeof(Buf*), Nbufs); e->rc = chancreate(sizeof(Buf*), Nconns/2); e->wc = chancreate(sizeof(Buf*), Nconns*2); incref(e->dev); proccreate(etherwriteproc, e, 16*1024); incref(e->dev); proccreate(etherreadproc, e, 16*1024); deprint(2, "%s: dev ref %ld\n", argv0, dev->ref); incref(e->dev); usbfsadd(&e->fs); return 0; }
void threadmain(int argc, char **argv) { char *devdir; int i; long value[8], volume[8]; Audiocontrol *c; char *p; extern int attachok; Ep *ep; int csps[] = { Audiocsp, 0}; devdir = nil; volume[0] = Undef; for(i = 0; i<8; i++) value[i] = 0; fmtinstall('A', Aconv); fmtinstall('U', Ufmt); quotefmtinstall(); ARGBEGIN{ case 'N': p = EARGF(usage()); /* ignore dev nb */ break; case 'd': usbdebug++; verbose++; break; case 'm': mntpt = EARGF(usage()); break; case 'p': attachok++; break; case 's': srvpost = EARGF(usage()); break; case 'v': volume[0] = strtol(EARGF(usage()), &p, 0); for(i = 1; i < 8; i++) volume[i] = volume[0]; break; case 'V': verbose++; break; default: usage(); }ARGEND switch(argc){ case 0: break; case 1: devdir = argv[0]; break; default: usage(); } if(devdir == nil) if(finddevs(matchdevcsp, csps, &devdir, 1) < 1){ fprint(2, "No usb audio\n"); threadexitsall("usbaudio not found"); } ad = opendev(devdir); if(ad == nil) sysfatal("opendev: %r"); if(configdev(ad) < 0) sysfatal("configdev: %r"); for(i = 0; i < nelem(ad->usb->ddesc); i++) if(ad->usb->ddesc[i] != nil) switch(ad->usb->ddesc[i]->data.bDescriptorType){ case AUDIO_INTERFACE: audio_interface(ad, ad->usb->ddesc[i]); break; case AUDIO_ENDPOINT: audio_endpoint(ad, ad->usb->ddesc[i]); break; } controlchan = chancreate(sizeof(char*), 8); for(i = 0; i < nelem(ad->usb->ep); i++) if((ep = ad->usb->ep[i]) != nil){ if(ep->iface->csp == CSP(Claudio, 2, 0) && ep->dir == Eout) endpt[0] = ep->id; if(ep->iface->csp == CSP(Claudio, 2, 0) && ep->dir == Ein) endpt[1] = ep->id; if(buttonendpt<0 && Class(ep->iface->csp) == Clhid) buttonendpt = ep->id; } if(endpt[0] != -1){ if(verbose) fprint(2, "usb/audio: playback on ep %d\n", endpt[0]); interface[0] = ad->usb->ep[endpt[0]]->iface->id; } if(endpt[1] != -1){ if(verbose) fprint(2, "usb/audio: record on ep %d\n", endpt[0]); interface[1] = ad->usb->ep[endpt[1]]->iface->id; } if(verbose && buttonendpt >= 0) fprint(2, "usb/audio: buttons on ep %d\n", buttonendpt); if(endpt[Play] >= 0){ if(verbose) fprint(2, "Setting default play parameters: %d Hz, %d channels at %d bits\n", defaultspeed[Play], 2, 16); if(findalt(Play, 2, 16, defaultspeed[Play]) < 0){ if(findalt(Play, 2, 16, 48000) < 0) sysfatal("Can't configure playout for %d or %d Hz", defaultspeed[Play], 48000); fprint(2, "Warning, can't configure playout for %d Hz, configuring for %d Hz instead\n", defaultspeed[Play], 48000); defaultspeed[Play] = 48000; } value[0] = 2; if(setcontrol(Play, "channels", value) == Undef) sysfatal("Can't set play channels"); value[0] = 16; if(setcontrol(Play, "resolution", value) == Undef) sysfatal("Can't set play resolution"); } if(endpt[Record] >= 0){ setrec = 1; if(verbose) fprint(2, "Setting default record parameters: " "%d Hz, %d channels at %d bits\n", defaultspeed[Record], 2, 16); i = 2; while(findalt(Record, i, 16, defaultspeed[Record]) < 0) if(i == 2 && controls[Record][Channel_control].max == 1){ fprint(2, "Warning, can't configure stereo " "recording, configuring mono instead\n"); i = 1; }else break; if(findalt(Record, i, 16, 48000) < 0){ endpt[Record] = -1; /* disable recording */ setrec = 0; fprint(2, "Warning, can't configure record for %d Hz or %d Hz\n", defaultspeed[Record], 48000); }else fprint(2, "Warning, can't configure record for %d Hz, " "configuring for %d Hz instead\n", defaultspeed[Record], 48000); defaultspeed[Record] = 48000; if(setrec){ value[0] = i; if(setcontrol(Record, "channels", value) == Undef) sysfatal("Can't set record channels"); value[0] = 16; if(setcontrol(Record, "resolution", value) == Undef) sysfatal("Can't set record resolution"); } } getcontrols(); /* Get the initial value of all controls */ value[0] = defaultspeed[Play]; if(endpt[Play] >= 0 && setcontrol(Play, "speed", value) < 0) sysfatal("can't set play speed"); value[0] = defaultspeed[Record]; if(endpt[Record] >= 0 && setcontrol(Record, "speed", value) < 0) fprint(2, "%s: can't set record speed\n", argv0); value[0] = 0; setcontrol(Play, "mute", value); if(volume[0] != Undef){ c = &controls[Play][Volume_control]; if(*p == '%' && c->min != Undef) for(i = 0; i < 8; i++) volume[i] = (volume[i]*c->max + (100-volume[i])*c->min)/100; if(c->settable) setcontrol(Play, "volume", volume); c = &controls[Record][Volume_control]; if(c->settable && setrec) setcontrol(Record, "volume", volume); } if(buttonendpt > 0){ buttondev = openep(ad, buttonendpt); if(buttondev == nil) sysfatal("openep: buttons: %r"); if(opendevdata(buttondev, OREAD) < 0) sysfatal("open buttons fd: %r"); proccreate(buttonproc, nil, STACKSIZE); } proccreate(controlproc, nil, STACKSIZE); proccreate(serve, nil, STACKSIZE); threadexits(nil); }
void threadmain(int argc, char **argv) { int fd, i, nd; char *err, *mnt, *srv; Dir *d; srv = "usb"; mnt = "/dev"; ARGBEGIN{ case 'D': usbfsdebug++; break; case 'd': usbdebug++; break; case 's': srv = EARGF(usage()); break; case 'i': pollms = atoi(EARGF(usage())); break; case 'm': mnt = EARGF(usage()); break; default: usage(); }ARGEND; if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0) sysfatal("#u: %r"); args(); fmtinstall('U', Ufmt); quotefmtinstall(); rfork(RFNOTEG); portc = chancreate(sizeof(char *), 0); if(portc == nil) sysfatal("chancreate"); proccreate(work, portc, Stack); if(argc == 0){ fd = open("/dev/usb", OREAD); if(fd < 0) sysfatal("/dev/usb: %r"); nd = dirreadall(fd, &d); close(fd); if(nd < 2) sysfatal("/dev/usb: no hubs"); for(i = 0; i < nd; i++) if(strcmp(d[i].name, "ctl") != 0) sendp(portc, smprint("/dev/usb/%s", d[i].name)); free(d); }else for(i = 0; i < argc; i++) sendp(portc, strdup(argv[i])); sendp(portc, nil); err = recvp(portc); chanfree(portc); usbfsexits(0); usbfsinit(srv, mnt, &usbdirfs, MAFTER); snprint(ctlfs.name, sizeof(ctlfs.name), "usbdctl"); usbfsadd(&ctlfs); threadexits(err); }
void mesgctl(void *v) { Message *m; Window *w; Event *e, *eq, *e2, *ea; int na, nopen, i, j; char *os, *s, *t, *buf; m = v; w = m->w; threadsetname("mesgctl"); proccreate(wineventproc, w, STACK); for(;;){ e = recvp(w->cevent); switch(e->c1){ default: Unk: print("unknown message %c%c\n", e->c1, e->c2); break; case 'E': /* write to body; can't affect us */ break; case 'F': /* generated by our actions; ignore */ break; case 'K': /* type away; we don't care */ case 'M': switch(e->c2){ case 'x': /* mouse only */ case 'X': ea = nil; eq = e; if(e->flag & 2){ e2 = recvp(w->cevent); eq = e2; } if(e->flag & 8){ ea = recvp(w->cevent); recvp(w->cevent); na = ea->nb; }else na = 0; if(eq->q1>eq->q0 && eq->nb==0){ s = emalloc((eq->q1-eq->q0)*UTFmax+1); winread(w, eq->q0, eq->q1, s); }else s = estrdup(eq->b); if(na){ t = emalloc(strlen(s)+1+na+1); sprint(t, "%s %s", s, ea->b); free(s); s = t; } if(!mesgcommand(m, s)) /* send it back */ winwriteevent(w, e); break; case 'l': /* mouse only */ case 'L': buf = nil; eq = e; if(e->flag & 2){ e2 = recvp(w->cevent); eq = e2; } s = eq->b; if(eq->q1>eq->q0 && eq->nb==0){ buf = emalloc((eq->q1-eq->q0)*UTFmax+1); winread(w, eq->q0, eq->q1, buf); s = buf; } os = s; nopen = 0; do{ /* skip mail box name if present */ if(strncmp(s, mbox.name, strlen(mbox.name)) == 0) s += strlen(mbox.name); if(strstr(s, "body") != nil){ /* strip any known extensions */ for(i=0; exts[i].ext!=nil; i++){ j = strlen(exts[i].ext); if(strlen(s)>j && strcmp(s+strlen(s)-j, exts[i].ext)==0){ s[strlen(s)-j] = '\0'; break; } } if(strlen(s)>5 && strcmp(s+strlen(s)-5, "/body")==0) s[strlen(s)-4] = '\0'; /* leave / in place */ } nopen += mesgopen(&mbox, mbox.name, s, m, 0, nil); while(*s!=0 && *s++!='\n') ; }while(*s); if(nopen == 0 && e->c1 == 'L') nopen += replytoaddr(w, m, e, os); if(nopen == 0) winwriteevent(w, e); free(buf); break; case 'I': /* modify away; we don't care */ case 'D': mesgtagpost(m); /* fall through */ case 'd': case 'i': break; default: goto Unk; } } } }
void threadmain(int argc, char *argv[]) { char *defsrv, *srvname; int p[2], fd; int stdio; char *host = nil; ulong mem; mem = 16<<20; stdio = 0; fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); defmnt = nil; defsrv = nil; ARGBEGIN{ case 'd': fmtinstall('F', fcallfmt); dflag = 1; break; case 'i': defmnt = nil; stdio = 1; mfd[0] = 0; mfd[1] = 1; break; case 'h': host = EARGF(usage()); break; case 'S': defsrv = EARGF(usage()); break; case 's': defsrv = "vacfs"; break; case 'M': mem = unittoull(EARGF(usage())); break; case 'm': defmnt = EARGF(usage()); break; case 'p': noperm = 1; break; case 'V': chattyventi = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); #ifdef PLAN9PORT if(defsrv == nil && defmnt == nil && !stdio){ srvname = strchr(argv[0], '/'); if(srvname) srvname++; else srvname = argv[0]; defsrv = vtmalloc(6+strlen(srvname)+1); strcpy(defsrv, "vacfs."); strcat(defsrv, srvname); if(strcmp(defsrv+strlen(defsrv)-4, ".vac") == 0) defsrv[strlen(defsrv)-4] = 0; } #else if(defsrv == nil && defmnt == nil && !stdio) defmnt = "/n/vac"; #endif if(stdio && defmnt) sysfatal("cannot use -m with -i"); initfcalls(); notify(notifyf); user = getuser(); conn = vtdial(host); if(conn == nil) sysfatal("could not connect to server: %r"); if(vtconnect(conn) < 0) sysfatal("vtconnect: %r"); fs = vacfsopen(conn, argv[0], VtOREAD, mem); if(fs == nil) sysfatal("vacfsopen: %r"); if(!stdio){ if(pipe(p) < 0) sysfatal("pipe failed: %r"); mfd[0] = p[0]; mfd[1] = p[0]; srvfd = p[1]; #ifndef PLAN9PORT if(defsrv){ srvname = smprint("/srv/%s", defsrv); fd = create(srvname, OWRITE|ORCLOSE, 0666); if(fd < 0) sysfatal("create %s: %r", srvname); if(fprint(fd, "%d", srvfd) < 0) sysfatal("write %s: %r", srvname); free(srvname); } #endif } #ifdef PLAN9PORT USED(fd); proccreate(srv, 0, 32 * 1024); if(!stdio && post9pservice(p[1], defsrv, defmnt) < 0) sysfatal("post9pservice"); #else procrfork(srv, 0, 32 * 1024, RFFDG|RFNAMEG|RFNOTEG); if(!stdio){ close(p[0]); if(defmnt){ if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0) sysfatal("mount %s: %r", defmnt); } } #endif threadexits(0); }
void threadmain(int argc, char **argv) { char *pref, *mountname, *mountplace; uchar score[VtScoreSize], prev[VtScoreSize]; int i, fd, csize; vlong bsize; Tm tm; VtEntry e; VtBlock *b; VtCache *c; VtRoot root; char *tmp, *tmpnam; fmtinstall('F', vtfcallfmt); fmtinstall('H', encodefmt); fmtinstall('T', timefmt); fmtinstall('V', vtscorefmt); mountname = sysname(); mountplace = nil; ARGBEGIN{ default: usage(); break; case 'D': debug++; break; case 'V': chattyventi = 1; break; case 'f': fastwrites = 1; break; case 'i': incremental = 1; break; case 'm': mountname = EARGF(usage()); break; case 'M': mountplace = EARGF(usage()); i = strlen(mountplace); if(i > 0 && mountplace[i-1] == '/') mountplace[i-1] = 0; break; case 'n': nop = 1; break; case 's': statustime = atoi(EARGF(usage())); break; case 'v': verbose = 1; break; case 'w': nwritethread = atoi(EARGF(usage())); break; }ARGEND if(argc != 1 && argc != 2) usage(); if(statustime) print("# %T vbackup %s %s\n", argv[0], argc>=2 ? argv[1] : ""); /* * open fs */ if((disk = diskopenfile(argv[0])) == nil) sysfatal("diskopen: %r"); if((disk = diskcache(disk, 32768, 2*MAXQ+16)) == nil) sysfatal("diskcache: %r"); if((fsys = fsysopen(disk)) == nil) sysfatal("fsysopen: %r"); /* * connect to venti */ if((z = vtdial(nil)) == nil) sysfatal("vtdial: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); /* * set up venti block cache */ zero = vtmallocz(fsys->blocksize); bsize = fsys->blocksize; csize = 50; /* plenty; could probably do with 5 */ if(verbose) fprint(2, "cache %d blocks\n", csize); c = vtcachealloc(z, bsize*csize); zcache = c; /* * parse starting score */ memset(prev, 0, sizeof prev); if(argc == 1){ vfile = vtfilecreateroot(c, (fsys->blocksize/VtScoreSize)*VtScoreSize, fsys->blocksize, VtDataType); if(vfile == nil) sysfatal("vtfilecreateroot: %r"); vtfilelock(vfile, VtORDWR); if(vtfilewrite(vfile, zero, 1, bsize*fsys->nblock-1) != 1) sysfatal("vtfilewrite: %r"); if(vtfileflush(vfile) < 0) sysfatal("vtfileflush: %r"); }else{ if(vtparsescore(argv[1], &pref, score) < 0) sysfatal("bad score: %r"); if(pref!=nil && strcmp(pref, fsys->type) != 0) sysfatal("score is %s but fsys is %s", pref, fsys->type); b = vtcacheglobal(c, score, VtRootType, VtRootSize); if(b){ if(vtrootunpack(&root, b->data) < 0) sysfatal("bad root: %r"); if(strcmp(root.type, fsys->type) != 0) sysfatal("root is %s but fsys is %s", root.type, fsys->type); memmove(prev, score, VtScoreSize); memmove(score, root.score, VtScoreSize); vtblockput(b); } b = vtcacheglobal(c, score, VtDirType, VtEntrySize); if(b == nil) sysfatal("vtcacheglobal %V: %r", score); if(vtentryunpack(&e, b->data, 0) < 0) sysfatal("%V: vtentryunpack failed", score); if(verbose) fprint(2, "entry: size %llud psize %d dsize %d\n", e.size, e.psize, e.dsize); vtblockput(b); if((vfile = vtfileopenroot(c, &e)) == nil) sysfatal("vtfileopenroot: %r"); vtfilelock(vfile, VtORDWR); if(e.dsize != bsize) sysfatal("file system block sizes don't match %d %lld", e.dsize, bsize); if(e.size != fsys->nblock*bsize) sysfatal("file system block counts don't match %lld %lld", e.size, fsys->nblock*bsize); } tmpnam = nil; if(incremental){ if(vtfilegetentry(vfile, &e) < 0) sysfatal("vtfilegetentry: %r"); if((vscores = vtfileopenroot(c, &e)) == nil) sysfatal("vtfileopenroot: %r"); vtfileunlock(vfile); }else{ /* * write scores of blocks into temporary file */ if((tmp = getenv("TMP")) != nil){ /* okay, good */ }else if(access("/var/tmp", 0) >= 0) tmp = "/var/tmp"; else tmp = "/tmp"; tmpnam = smprint("%s/vbackup.XXXXXX", tmp); if(tmpnam == nil) sysfatal("smprint: %r"); if((fd = opentemp(tmpnam, ORDWR|ORCLOSE)) < 0) sysfatal("opentemp %s: %r", tmpnam); if(statustime) print("# %T reading scores into %s\n", tmpnam); if(verbose) fprint(2, "read scores into %s...\n", tmpnam); Binit(&bscores, fd, OWRITE); for(i=0; i<fsys->nblock; i++){ if(vtfileblockscore(vfile, i, score) < 0) sysfatal("vtfileblockhash %d: %r", i); if(Bwrite(&bscores, score, VtScoreSize) != VtScoreSize) sysfatal("Bwrite: %r"); } Bterm(&bscores); vtfileunlock(vfile); /* * prep scores for rereading */ seek(fd, 0, 0); Binit(&bscores, fd, OREAD); } /* * start the main processes */ if(statustime) print("# %T starting procs\n"); qcmp = qalloc(); qventi = qalloc(); rlock(&endlk); proccreate(fsysproc, nil, STACK); rlock(&endlk); proccreate(ventiproc, nil, STACK); rlock(&endlk); proccreate(cmpproc, nil, STACK); if(statustime){ rlock(&endlk); proccreate(statusproc, nil, STACK); } /* * wait for processes to finish */ wlock(&endlk); qfree(qcmp); qfree(qventi); if(statustime) print("# %T procs exited: %d of %d %d-byte blocks changed, " "%d read, %d written, %d skipped, %d copied\n", nchange, fsys->nblock, fsys->blocksize, vtcachenread, vtcachenwrite, nskip, vtcachencopy); /* * prepare root block */ if(incremental) vtfileclose(vscores); vtfilelock(vfile, -1); if(vtfileflush(vfile) < 0) sysfatal("vtfileflush: %r"); if(vtfilegetentry(vfile, &e) < 0) sysfatal("vtfilegetentry: %r"); vtfileunlock(vfile); vtfileclose(vfile); b = vtcacheallocblock(c, VtDirType, VtEntrySize); if(b == nil) sysfatal("vtcacheallocblock: %r"); vtentrypack(&e, b->data, 0); if(vtblockwrite(b) < 0) sysfatal("vtblockwrite: %r"); memset(&root, 0, sizeof root); strecpy(root.name, root.name+sizeof root.name, argv[0]); strecpy(root.type, root.type+sizeof root.type, fsys->type); memmove(root.score, b->score, VtScoreSize); root.blocksize = fsys->blocksize; memmove(root.prev, prev, VtScoreSize); vtblockput(b); b = vtcacheallocblock(c, VtRootType, VtRootSize); if(b == nil) sysfatal("vtcacheallocblock: %r"); vtrootpack(&root, b->data); if(vtblockwrite(b) < 0) sysfatal("vtblockwrite: %r"); tm = *localtime(time(0)); tm.year += 1900; tm.mon++; if(mountplace == nil) mountplace = guessmountplace(argv[0]); print("mount /%s/%d/%02d%02d%s %s:%V %d/%02d%02d/%02d%02d\n", mountname, tm.year, tm.mon, tm.mday, mountplace, root.type, b->score, tm.year, tm.mon, tm.mday, tm.hour, tm.min); print("# %T %s %s:%V\n", argv[0], root.type, b->score); if(statustime) print("# %T venti sync\n"); vtblockput(b); if(vtsync(z) < 0) sysfatal("vtsync: %r"); if(statustime) print("# %T synced\n"); fsysclose(fsys); diskclose(disk); vtcachefree(zcache); // Vtgoodbye hangs on Linux - not sure why. // Probably vtfcallrpc doesn't quite get the // remote hangup right. Also probably related // to the vtrecvproc problem below. // vtgoodbye(z); // Leak here, because I can't seem to make // the vtrecvproc exit. // vtfreeconn(z); free(tmpnam); z = nil; zcache = nil; fsys = nil; disk = nil; threadexitsall(nil); }
void threadmain(int argc, char *argv[]) { char *s, *name; char err[ERRMAX], *cmd; int i, newdir; Fmt fmt; doquote = needsrcquote; quotefmtinstall(); /* open these early so we won't miss notification of new mail messages while we read mbox */ if((plumbsendfd = plumbopenfid("send", OWRITE|OCEXEC)) == nil) fprint(2, "warning: open plumb/send: %r\n"); if((plumbseemailfd = plumbopenfid("seemail", OREAD|OCEXEC)) == nil) fprint(2, "warning: open plumb/seemail: %r\n"); if((plumbshowmailfd = plumbopenfid("showmail", OREAD|OCEXEC)) == nil) fprint(2, "warning: open plumb/showmail: %r\n"); shortmenu = 0; srvname = "mail"; ARGBEGIN{ case 's': shortmenu = 1; break; case 'S': shortmenu = 2; break; case 'o': outgoing = EARGF(usage()); break; case 'm': smprint(maildir, "%s/", EARGF(usage())); break; case 'n': srvname = EARGF(usage()); break; default: usage(); }ARGEND acmefs = nsmount("acme",nil); if(acmefs == nil) error("cannot mount acme: %r"); mailfs = nsmount(srvname, nil); if(mailfs == nil) error("cannot mount %s: %r", srvname); name = "mbox"; newdir = 1; if(argc > 0){ i = strlen(argv[0]); if(argc>2 || i==0) usage(); /* see if the name is that of an existing /mail/fs directory */ if(argc==1 && argv[0][0] != '/' && ismaildir(argv[0])){ name = argv[0]; mboxname = estrdup(name); newdir = 0; }else{ if(argv[0][i-1] == '/') argv[0][i-1] = '\0'; s = strrchr(argv[0], '/'); if(s == nil) mboxname = estrdup(argv[0]); else{ *s++ = '\0'; if(*s == '\0') usage(); mailboxdir = argv[0]; mboxname = estrdup(s); } if(argc > 1) name = argv[1]; else name = mboxname; } } user = getenv("user"); if(user == nil) user = "******"; home = getenv("home"); if(home == nil) home = getenv("HOME"); if(home == nil) error("can't find $home"); if(mailboxdir == nil) mailboxdir = estrstrdup(home, "/mail"); if(outgoing == nil) outgoing = estrstrdup(mailboxdir, "/outgoing"); mbox.ctlfd = fsopen(mailfs, estrstrdup(mboxname, "/ctl"), OWRITE); if(mbox.ctlfd == nil) error("can't open %s: %r", estrstrdup(mboxname, "/ctl")); fsname = estrdup(name); if(newdir && argc > 0){ s = emalloc(5+strlen(mailboxdir)+strlen(mboxname)+strlen(name)+10+1); for(i=0; i<10; i++){ sprint(s, "open %s/%s %s", mailboxdir, mboxname, fsname); if(fswrite(mbox.ctlfd, s, strlen(s)) >= 0) break; err[0] = '\0'; errstr(err, sizeof err); if(strstr(err, "mbox name in use") == nil) error("can't create directory %s for mail: %s", name, err); free(fsname); fsname = emalloc(strlen(name)+10); sprint(fsname, "%s-%d", name, i); } if(i == 10) error("can't open %s/%s: %r", mailboxdir, mboxname); free(s); } s = estrstrdup(fsname, "/"); mbox.name = estrstrdup(maildir, s); mbox.level= 0; readmbox(&mbox, maildir, s); home = getenv("home"); if(home == nil) home = "/"; wbox = newwindow(); winname(wbox, mbox.name); wintagwrite(wbox, "Put Mail Delmesg ", 3+1+4+1+7+1); threadcreate(mainctl, wbox, STACK); fmtstrinit(&fmt); fmtprint(&fmt, "Mail"); if(shortmenu) fmtprint(&fmt, " -%c", "sS"[shortmenu-1]); if(outgoing) fmtprint(&fmt, " -o %s", outgoing); fmtprint(&fmt, " %s", name); cmd = fmtstrflush(&fmt); if(cmd == nil) sysfatal("out of memory"); winsetdump(wbox, "/acme/mail", cmd); mbox.w = wbox; mesgmenu(wbox, &mbox); winclean(wbox); /* wctlfd = open("/dev/wctl", OWRITE|OCEXEC); /* for acme window */ wctlfd = -1; cplumb = chancreate(sizeof(Plumbmsg*), 0); cplumbshow = chancreate(sizeof(Plumbmsg*), 0); if(strcmp(name, "mbox") == 0){ /* * Avoid creating multiple windows to send mail by only accepting * sendmail plumb messages if we're reading the main mailbox. */ plumbsendmailfd = plumbopenfid("sendmail", OREAD|OCEXEC); cplumbsend = chancreate(sizeof(Plumbmsg*), 0); proccreate(plumbsendproc, nil, STACK); threadcreate(plumbsendthread, nil, STACK); } /* start plumb reader as separate proc ... */ proccreate(plumbproc, nil, STACK); proccreate(plumbshowproc, nil, STACK); threadcreate(plumbshowthread, nil, STACK); fswrite(mbox.ctlfd, "refresh", 7); /* ... and use this thread to read the messages */ plumbthread(); }
int spawngs(GSInfo *g, char *safer) { Channel *cp; char *args[16]; char tb[32], gb[32]; int i, nargs; int devnull; int stdinp[2]; int stdoutp[2]; int dataout[2]; int errout[2]; /* * spawn gs * * gs's standard input is fed from stdinout. * gs output written to fd-2 (i.e. output we generate intentionally) is fed to stdinout. * gs output written to fd 1 (i.e. ouptut gs generates on error) is fed to errout. * gs data output is written to fd 3, which is dataout. */ if(pipe(stdinp)<0 || pipe(stdoutp)<0 || pipe(dataout)<0 || pipe(errout)<0) return -1; nargs = 0; args[nargs++] = "gs"; args[nargs++] = "-dNOPAUSE"; args[nargs++] = "-dNOPROMPT"; args[nargs++] = "-dDELAYSAFER"; args[nargs++] = "-dQUIET"; args[nargs++] = "-sDEVICE=bmp16m"; args[nargs++] = "-sOutputFile=/dev/fd/3"; args[nargs++] = "-r100"; sprint(tb, "-dTextAlphaBits=%d", textbits); sprint(gb, "-dGraphicsAlphaBits=%d", gfxbits); if(textbits) args[nargs++] = tb; if(gfxbits) args[nargs++] = gb; args[nargs] = nil; gspid = fork(); if(gspid == 0) { close(stdinp[1]); close(stdoutp[0]); close(dataout[0]); close(errout[0]); /* * Horrible problem: we want to dup fd's 0-4 below, * but some of the source fd's might have those small numbers. * So we need to reallocate those. In order to not step on * anything else, we'll dup the fd's to higher ones using * dup(x, -1), but we need to use up the lower ones first. */ while((devnull = open("/dev/null", ORDWR)) < 5) ; stdinp[0] = dup(stdinp[0], -1); stdoutp[1] = dup(stdoutp[1], -1); errout[1] = dup(errout[1], -1); dataout[1] = dup(dataout[1], -1); dup(stdinp[0], 0); dup(errout[1], 1); dup(devnull, 2); /* never anything useful */ dup(dataout[1], 3); dup(stdoutp[1], 4); for(i=5; i<20; i++) close(i); execvp("gs", args); wexits("exec"); } close(stdinp[0]); close(stdoutp[1]); close(errout[1]); close(dataout[1]); atexit(killgs); cp = chancreate(sizeof(int), 0); if(teegs) { proccreate(spawnreader, cp, mainstacksize); send(cp, &stdoutp[0]); recv(cp, &stdoutp[0]); } gsfd = g->gsfd = stdinp[1]; g->gspid = gspid; g->g.fd = dataout[0]; g->g.name = "gs pipe"; g->g.type = Ibmp; proccreate(spawnmonitor, cp, mainstacksize); send(cp, &errout[0]); chanfree(cp); Binit(&g->gsrd, stdoutp[0], OREAD); gscmd(g, "/PAGEOUT (/dev/fd/4) (w) file def\n"); if(!strcmp(safer, "-dSAFER")) gscmd(g, ".setsafe\n"); gscmd(g, "/PAGE== { PAGEOUT exch write==only PAGEOUT (\\n) writestring PAGEOUT flushfile } def\n"); waitgs(g); return 0; }
void threadmain(int argc, char *argv[]) { int i; char *p, *loadfile; char buf[256]; Column *c; int ncol; Display *d; static void *arg[1]; rfork(RFENVG|RFNAMEG); ncol = -1; loadfile = nil; ARGBEGIN{ case 'a': globalautoindent = TRUE; break; case 'b': bartflag = TRUE; break; case 'c': p = ARGF(); if(p == nil) goto Usage; ncol = atoi(p); if(ncol <= 0) goto Usage; break; case 'f': fontnames[0] = ARGF(); if(fontnames[0] == nil) goto Usage; break; case 'F': fontnames[1] = ARGF(); if(fontnames[1] == nil) goto Usage; break; case 'l': loadfile = ARGF(); if(loadfile == nil) goto Usage; break; default: Usage: fprint(2, "usage: acme [-ab] [-c ncol] [-f font] [-F fixedfont] [-l loadfile | file...]\n"); exits("usage"); }ARGEND if(fontnames[0] == nil) fontnames[0] = getenv("font"); if(fontnames[0] == nil) fontnames[0] = "/lib/font/bit/vga/unicode.font"; if(access(fontnames[0], 0) < 0){ fprint(2, "acme: can't access %s: %r\n", fontnames[0]); exits("font open"); } if(fontnames[1] == nil) fontnames[1] = fontnames[0]; fontnames[0] = estrdup(fontnames[0]); fontnames[1] = estrdup(fontnames[1]); quotefmtinstall(); cputype = getenv("cputype"); objtype = getenv("objtype"); home = getenv("home"); p = getenv("tabstop"); if(p != nil){ maxtab = strtoul(p, nil, 0); free(p); } if(maxtab == 0) maxtab = 4; if(loadfile) rowloadfonts(loadfile); putenv("font", fontnames[0]); snarffd = open("/dev/snarf", OREAD|OCEXEC); if(cputype){ sprint(buf, "/acme/bin/%s", cputype); bind(buf, "/bin", MBEFORE); } bind("/acme/bin", "/bin", MBEFORE); getwd(wdir, sizeof wdir); if(geninitdraw(nil, derror, fontnames[0], "acme", nil, Refnone) < 0){ fprint(2, "acme: can't open display: %r\n"); exits("geninitdraw"); } d = display; font = d->defaultfont; reffont.f = font; reffonts[0] = &reffont; incref(&reffont); /* one to hold up 'font' variable */ incref(&reffont); /* one to hold up reffonts[0] */ fontcache = emalloc(sizeof(Reffont*)); nfontcache = 1; fontcache[0] = &reffont; iconinit(); timerinit(); rxinit(); cwait = threadwaitchan(); ccommand = chancreate(sizeof(Command**), 0); ckill = chancreate(sizeof(Rune*), 0); cxfidalloc = chancreate(sizeof(Xfid*), 0); cxfidfree = chancreate(sizeof(Xfid*), 0); cnewwindow = chancreate(sizeof(Channel*), 0); cerr = chancreate(sizeof(char*), 0); cedit = chancreate(sizeof(int), 0); cexit = chancreate(sizeof(int), 0); cwarn = chancreate(sizeof(void*), 1); if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil || cwarn==nil){ fprint(2, "acme: can't create initial channels: %r\n"); threadexitsall("channels"); } mousectl = initmouse(nil, screen); if(mousectl == nil){ fprint(2, "acme: can't initialize mouse: %r\n"); threadexitsall("mouse"); } mouse = mousectl; keyboardctl = initkeyboard(nil); if(keyboardctl == nil){ fprint(2, "acme: can't initialize keyboard: %r\n"); threadexitsall("keyboard"); } mainpid = getpid(); plumbeditfd = plumbopen("edit", OREAD|OCEXEC); if(plumbeditfd >= 0){ cplumb = chancreate(sizeof(Plumbmsg*), 0); proccreate(plumbproc, nil, STACK); } plumbsendfd = plumbopen("send", OWRITE|OCEXEC); fsysinit(); #define WPERCOL 8 disk = diskinit(); if(!loadfile || !rowload(&row, loadfile, TRUE)){ rowinit(&row, screen->clipr); if(ncol < 0){ if(argc == 0) ncol = 2; else{ ncol = (argc+(WPERCOL-1))/WPERCOL; if(ncol < 2) ncol = 2; } } if(ncol == 0) ncol = 2; for(i=0; i<ncol; i++){ c = rowadd(&row, nil, -1); if(c==nil && i==0) error("initializing columns"); } c = row.col[row.ncol-1]; if(argc == 0) readfile(c, wdir); else for(i=0; i<argc; i++){ p = utfrrune(argv[i], '/'); if((p!=nil && strcmp(p, "/guide")==0) || i/WPERCOL>=row.ncol) readfile(c, argv[i]); else readfile(row.col[i/WPERCOL], argv[i]); } } flushimage(display, 1); acmeerrorinit(); threadcreate(keyboardthread, nil, STACK); threadcreate(mousethread, nil, STACK); threadcreate(waitthread, nil, STACK); threadcreate(xfidallocthread, nil, STACK); threadcreate(newwindowthread, nil, STACK); threadnotify(shutdown, 1); recvul(cexit); killprocs(); threadexitsall(nil); }
void hoststart(void) { hostc = chancreate(sizeof(int), 0); proccreate(hostproc, hostc, 1024); }
char * tcs(char *cs, char *s, long *np) { Channel *sync; Exec *e; Rune r; long i, n; void **a; uchar *us; char buf[BUFSIZE], cmd[50]; char *t, *u; int p[2], q[2]; if(s==nil || *s=='\0' || *np==0){ werrstr("tcs failed: no data"); return s; } if(cs == nil){ werrstr("tcs failed: no charset"); return s; } if(cistrncmp(cs, "utf-8", 5)==0 || cistrncmp(cs, "utf8", 4)==0) return s; for(i=0; tcstab[i].mime!=nil; i++) if(cistrncmp(cs, tcstab[i].mime, strlen(tcstab[i].mime)) == 0) break; if(tcstab[i].mime == nil){ fprint(2, "abaco: charset: %s not supported\n", cs); goto latin1; } if(cistrcmp(tcstab[i].tcs, "8859-1")==0 || cistrcmp(tcstab[i].tcs, "ascii")==0){ latin1: n = 0; for(us=(uchar*)s; *us; us++) n += runelen(*us); n++; t = emalloc(n); for(us=(uchar*)s, u=t; *us; us++){ if(*us>=Winstart && *us<=Winend) *u++ = winchars[*us-Winstart]; else{ r = *us; u += runetochar(u, &r); } } *u = 0; free(s); return t; } if(pipe(p)<0 || pipe(q)<0) error("can't create pipe"); sync = chancreate(sizeof(ulong), 0); if(sync == nil) error("can't create channel"); snprint(cmd, sizeof cmd, "tcs -f %s", tcstab[i].tcs); e = emalloc(sizeof(Exec)); e->p[0] = p[0]; e->p[1] = p[1]; e->q[0] = q[0]; e->q[1] = q[1]; e->cmd = cmd; e->sync = sync; proccreate(execproc, e, STACK); recvul(sync); chanfree(sync); close(p[0]); close(q[1]); /* in case tcs fails */ t = s; sync = chancreate(sizeof(ulong), 0); if(sync == nil) error("can't create channel"); a = emalloc(4*sizeof(void *)); a[0] = sync; a[1] = (void *)p[1]; a[2] = s; a[3] = (void *)*np; proccreate(writeproc, a, STACK); s = nil; while((n = read(q[0], buf, sizeof(buf))) > 0){ s = erealloc(s, i+n+1); memmove(s+i, buf, n); i += n; s[i] = '\0'; } n = recvul(sync); if(n != *np) fprint(2, "tcs: did not write %ld; wrote %uld\n", *np, n); *np = i; chanfree(sync); close(q[0]); if(s == nil){ fprint(2, "tcs failed: can't convert charset=%s to %s\n", cs, tcstab[i].tcs); return t; } free(t); return s; }
void threadmain(int argc, char *argv[]) { int serveudp, servetcp; char *service; serveudp = 0; servetcp = 0; service = "dns"; ARGBEGIN{ case 'd': debug = 1; traceactivity = 1; break; case 'f': dbfile = EARGF(usage()); break; case 'x': service = EARGF(usage()); break; case 'r': resolver = 1; break; case 's': serveudp = 1; cachedb = 1; break; case 't': servetcp = 1; cachedb = 1; break; case 'a': maxage = atoi(EARGF(usage())); break; case 'z': zonerefreshprogram = EARGF(usage()); break; case 'n': sendnotifies = 1; break; case 'U': udpaddr = estrdup(netmkaddr(EARGF(usage()), "udp", "domain")); break; case 'T': tcpaddr = estrdup(netmkaddr(EARGF(usage()), "tcp", "domain")); break; default: usage(); }ARGEND if(argc) usage(); if(serveudp && servetcp) checkaddress(); rfork(RFNOTEG); /* start syslog before we fork */ fmtinstall('F', fcallfmt); dninit(); if(myipaddr(ipaddr, mntpt) < 0) sysfatal("can't read my ip address"); syslog(0, logfile, "starting dns on %I", ipaddr); opendatabase(); mountinit(service); now = time(0); srand(now*getpid()); db2cache(1); if(serveudp) proccreate(dnudpserver, nil, STACK); if(servetcp) proccreate(dntcpserver, nil, STACK); if(sendnotifies) proccreate(notifyproc, nil, STACK); io(); }
int vtproc(void (*fn)(void*), void *arg) { proccreate(fn, arg, 256*1024); return 0; }
void mesgsend(Message *m) { char *s, *body, *to; int i, j, h, n, natt, p[2]; struct Exec *e; Channel *sync; int first, nfld, delit, ofd; char *copy, *fld[100], *now; body = winreadbody(m->w, &n); /* assemble to: list from first line, to: line, and cc: line */ nto = 0; natt = 0; ncc = 0; nbcc = 0; first = 1; to = body; for(;;){ for(s=to; *s!='\n'; s++) if(*s == '\0'){ free(body); return; } if(s++ == to) /* blank line */ break; /* make copy of line to tokenize */ copy = emalloc(s-to); memmove(copy, to, s-to); copy[s-to-1] = '\0'; nfld = tokenizec(copy, fld, nelem(fld), ", \t"); if(nfld == 0){ free(copy); break; } n -= s-to; switch(h = whichheader(fld[0])){ case TO: case FROM: delit = 1; commas(to+strlen(fld[0]), s-1); for(i=1; i<nfld && nto<nelem(tolist); i++) if(!addressed(fld[i])) tolist[nto++] = estrdup(fld[i]); break; case BCC: delit = 1; commas(to+strlen(fld[0]), s-1); for(i=1; i<nfld && nbcc<nelem(bcclist); i++) if(!addressed(fld[i])) bcclist[nbcc++] = estrdup(fld[i]); break; case CC: delit = 1; commas(to+strlen(fld[0]), s-1); for(i=1; i<nfld && ncc<nelem(cclist); i++) if(!addressed(fld[i])) cclist[ncc++] = estrdup(fld[i]); break; case ATTACH: case INCLUDE: delit = 1; for(i=1; i<nfld && natt<nelem(attlist); i++){ attlist[natt] = estrdup(fld[i]); included[natt++] = (h == INCLUDE); } break; default: if(first){ delit = 1; for(i=0; i<nfld && nto<nelem(tolist); i++) tolist[nto++] = estrdup(fld[i]); }else /* ignore it */ delit = 0; break; } if(delit){ /* delete line from body */ memmove(to, s, n+1); }else to = s; free(copy); first = 0; } ofd = open(outgoing, OWRITE|OCEXEC); /* no error check necessary */ if(ofd > 0){ /* From dhog Fri Aug 24 22:13:00 EDT 2001 */ now = ctime(time(0)); seek(ofd, 0, 2); fprint(ofd, "From %s %s", user, now); fprint(ofd, "From: %s\n", user); fprint(ofd, "Date: %s", now); for(i=0; i<natt; i++) if(included[i]) fprint(ofd, "Include: %s\n", attlist[i]); else fprint(ofd, "Attach: %s\n", attlist[i]); /* needed because mail is by default Latin-1 */ fprint(ofd, "Content-Type: text/plain; charset=\"UTF-8\"\n"); fprint(ofd, "Content-Transfer-Encoding: 8bit\n"); } e = emalloc(sizeof(struct Exec)); if(pipe(p) < 0) error("can't create pipe: %r"); e->p[0] = p[0]; e->p[1] = p[1]; e->prog = unsharp("#9/bin/upas/marshal"); e->argv = emalloc((1+1+2+4*natt+1)*sizeof(char*)); e->argv[0] = estrdup("marshal"); e->argv[1] = estrdup("-8"); j = 2; if(m->replyname){ e->argv[j++] = estrdup("-R"); e->argv[j++] = estrstrdup(mbox.name, m->replyname); } for(i=0; i<natt; i++){ if(included[i]) e->argv[j++] = estrdup("-A"); else e->argv[j++] = estrdup("-a"); e->argv[j++] = estrdup(attlist[i]); } sync = chancreate(sizeof(int), 0); e->sync = sync; proccreate(execproc, e, EXECSTACK); recvul(sync); /* close(p[0]); */ /* using marshal -8, so generate rfc822 headers */ if(nto > 0){ print2(p[1], ofd, "To: "); for(i=0; i<nto-1; i++) print2(p[1], ofd, "%s, ", tolist[i]); print2(p[1], ofd, "%s\n", tolist[i]); } if(ncc > 0){ print2(p[1], ofd, "CC: "); for(i=0; i<ncc-1; i++) print2(p[1], ofd, "%s, ", cclist[i]); print2(p[1], ofd, "%s\n", cclist[i]); } if(nbcc > 0){ print2(p[1], ofd, "BCC: "); for(i=0; i<nbcc-1; i++) print2(p[1], ofd, "%s, ", bcclist[i]); print2(p[1], ofd, "%s\n", bcclist[i]); } i = strlen(body); if(i > 0) write2(p[1], ofd, body, i, 1); /* guarantee a blank line, to ensure attachments are separated from body */ if(i==0 || body[i-1]!='\n') write2(p[1], ofd, "\n\n", 2, 0); else if(i>1 && body[i-2]!='\n') write2(p[1], ofd, "\n", 1, 0); /* these look like pseudo-attachments in the "outgoing" box */ if(ofd>0 && natt>0){ for(i=0; i<natt; i++) if(included[i]) fprint(ofd, "=====> Include: %s\n", attlist[i]); else fprint(ofd, "=====> Attach: %s\n", attlist[i]); } if(ofd > 0) write(ofd, "\n", 1); for(i=0; i<natt; i++) free(attlist[i]); close(ofd); close(p[1]); free(body); if(m->replyname != nil) mesgmenumark(mbox.w, m->replyname, "\t[replied]"); if(m->name[0] == '/') s = estrdup(m->name); else s = estrstrdup(mbox.name, m->name); s = egrow(s, "-R", nil); winname(m->w, s); free(s); winclean(m->w); /* mark message unopened because it's no longer the original message */ m->opened = 0; }
void mainctl(void *v) { Window *w; Event *e, *e2, *eq, *ea; int na, nopen; char *s, *t, *buf; w = v; winincref(w); proccreate(wineventproc, w, STACK); for(;;){ e = recvp(w->cevent); 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 */ break; case 'F': /* generated by our actions; ignore */ break; case 'K': /* type away; we don't care */ break; case 'M': switch(e->c2){ case 'x': case 'X': ea = nil; e2 = nil; if(e->flag & 2) e2 = recvp(w->cevent); if(e->flag & 8){ ea = recvp(w->cevent); na = ea->nb; recvp(w->cevent); }else na = 0; s = e->b; /* if it's a known command, do it */ if((e->flag&2) && e->nb==0) s = e2->b; if(na){ t = emalloc(strlen(s)+1+na+1); sprint(t, "%s %s", s, ea->b); s = t; } /* if it's a long message, it can't be for us anyway */ if(!mboxcommand(w, s)) /* send it back */ winwriteevent(w, e); if(na) free(s); break; case 'l': case 'L': buf = nil; eq = e; if(e->flag & 2){ e2 = recvp(w->cevent); eq = e2; } s = eq->b; if(eq->q1>eq->q0 && eq->nb==0){ buf = emalloc((eq->q1-eq->q0)*UTFmax+1); winread(w, eq->q0, eq->q1, buf); s = buf; } nopen = 0; do{ /* skip 'deleted' string if present' */ if(strncmp(s, deleted, strlen(deleted)) == 0) s += strlen(deleted); /* skip mail box name if present */ if(strncmp(s, mbox.name, strlen(mbox.name)) == 0) s += strlen(mbox.name); nopen += mesgopen(&mbox, mbox.name, s, nil, 0, nil); while(*s!='\0' && *s++!='\n') ; }while(*s); if(nopen == 0) /* send it back */ winwriteevent(w, e); free(buf); break; case 'I': /* modify away; we don't care */ case 'D': case 'd': case 'i': break; default: goto Unknown; } } } }
void threadmain(int argc, char *argv[]) { Column *c; char buf[256]; int i, ncol; rfork(RFENVG|RFNAMEG); ncol = 1; ARGBEGIN{ case 'c': ncol = atoi(EARGF(usage())); if(ncol <= 0) usage(); break; case 'm': webmountpt = EARGF(usage()); break; case 'p': procstderr++; break; case 't': charset = EARGF(usage()); break; default: usage(); break; }ARGEND snprint(buf, sizeof(buf), "%s/ctl", webmountpt); webctlfd = open(buf, ORDWR); if(webctlfd < 0) sysfatal("can't initialize webfs: %r"); snarffd = open("/dev/snarf", OREAD|OCEXEC); if(initdraw(derror, fontnames[0], "abaco") < 0) sysfatal("can't open display: %r"); memimageinit(); iconinit(); timerinit(); initfontpaths(); cexit = chancreate(sizeof(int), 0); crefresh = chancreate(sizeof(Page *), 0); if(cexit==nil || crefresh==nil) sysfatal("can't create initial channels: %r"); mousectl = initmouse(nil, screen); if(mousectl == nil) sysfatal("can't initialize mouse: %r"); mouse = mousectl; keyboardctl = initkeyboard(nil); if(keyboardctl == nil) sysfatal("can't initialize keyboard: %r"); mainpid = getpid(); plumbwebfd = plumbopen("web", OREAD|OCEXEC); if(plumbwebfd >= 0){ cplumb = chancreate(sizeof(Plumbmsg*), 0); proccreate(plumbproc, nil, STACK); } plumbsendfd = plumbopen("send", OWRITE|OCEXEC); rowinit(&row, screen->clipr); for(i=0; i<ncol; i++){ c = rowadd(&row, nil, -1); if(c==nil && i==0) error("initializing columns"); } c = row.col[row.ncol-1]; for(i=0; i<argc; i++) if(i/WPERCOL >= row.ncol) readpage(c, argv[i]); else readpage(row.col[i/WPERCOL], argv[i]); flushimage(display, 1); threadcreate(keyboardthread, nil, STACK); threadcreate(mousethread, nil, STACK); threadnotify(shutdown, 1); recvul(cexit); threadexitsall(nil); }
void threadmain(int argc, char *argv[]) { int dofork; int rem; void (*fn)(void*); dofork = 1; rem = 0; ns = nil; srv = "plumb"; ARGBEGIN{ case 'd': debug = 1; break; case 'f': dofork = 0; break; case 'n': /* name of remote namespace */ ns = EARGF(usage()); break; case 'p': prog = EARGF(usage()); break; case 's': /* name of service */ srv = EARGF(usage()); break; case 'R': rem = 1; break; case 'x': export = 1; break; }ARGEND if(debug){ char *dbgfile; if(rem) dbgfile = smprint("/tmp/%s.export.debug", getuser()); else dbgfile = smprint("/tmp/%s.import.debug", getuser()); dfd = create(dbgfile, OWRITE, 0664); free(dbgfile); fmtinstall('F', fcallfmt); } if(rem){ netfd[0] = 0; netfd[1] = 1; write(1, "OK", 2); }else{ if(argc != 1) usage(); addr = argv[0]; /* connect to remote service */ netfd[0] = netfd[1] = call(addr, ns, srv); } fn = localside; if(rem+export == 1) fn = remoteside; if(rem || !dofork) fn(nil); else proccreate(fn, nil, Stack); }
void mainctl(void *v) { Window *w; Event *e; int delta, pendingS, pendingK; uint32_t hostpt, endpt; char tmp[32]; w = v; proccreate(wineventproc, w, STACK); hostpt = 0; endpt = 0; winsetaddr(w, "0", 0); pendingS = 0; pendingK = 0; for(;;){ if(debug) fprint(2, "input range %lud-%lud\n", hostpt, endpt); e = recvp(w->cevent); if(debug) fprint(2, "msg: %C %C %d %d %d %d %q\n", e->c1 ? e->c1 : ' ', e->c2 ? e->c2 : ' ', e->q0, e->q1, e->flag, e->nb, e->b); switch(e->c1){ default: Unknown: fprint(2, "unknown message %c%c\n", e->c1, e->c2); break; case 'C': /* input needed for /dev/cons */ if(pendingS) pendingK = 1; else hostpt += sendinput(w, hostpt, &endpt); break; case 'S': /* output to stdout */ sprint(tmp, "#%lud", hostpt); winsetaddr(w, tmp, 0); write(w->data, e->b, e->nb); pendingS += e->nr; break; case 'E': /* write to tag or body; body happens due to sendit */ delta = e->q1-e->q0; if(e->c2=='I'){ endpt += delta; if(e->q0 < hostpt) hostpt += delta; else hostpt += sendinput(w, hostpt, &endpt); break; } if(!islower(e->c2)) fprint(2, "win msg: %C %C %d %d %d %d %q\n", e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b); break; case 'F': /* generated by our actions (specifically case 'S' above) */ delta = e->q1-e->q0; if(e->c2=='D'){ /* we know about the delete by _sendinput */ break; } if(e->c2=='I'){ pendingS -= e->q1 - e->q0; if(pendingS < 0) fprint(2, "win: pendingS = %d\n", pendingS); if(e->q0 != hostpt) fprint(2, "win: insert at %d expected %lud\n", e->q0, hostpt); endpt += delta; hostpt += delta; sendp(writechan, nil); if(pendingS == 0 && pendingK){ pendingK = 0; hostpt += sendinput(w, hostpt, &endpt); } break; } if(!islower(e->c2)) fprint(2, "win msg: %C %C %d %d %d %d %q\n", e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b); break; case 'K': delta = e->q1-e->q0; switch(e->c2){ case 'D': endpt -= delta; if(e->q1 < hostpt) hostpt -= delta; else if(e->q0 < hostpt) hostpt = e->q0; break; case 'I': delta = e->q1 - e->q0; endpt += delta; if(endpt < e->q1) /* just in case */ endpt = e->q1; if(e->q0 < hostpt) hostpt += delta; if(e->nr>0 && e->r[e->nr-1]==0x7F){ write(notepg, "interrupt", 9); hostpt = endpt; break; } if(e->q0 >= hostpt && hasboundary(e->r, e->nr)){ /* * If we are between the S message (which * we processed by inserting text in the * window) and the F message notifying us * that the text has been inserted, then our * impression of the hostpt and acme's * may be different. This could be seen if you * hit enter a bunch of times in a con * session. To work around the unreliability, * only send input if we don't have an S pending. * The same race occurs between when a character * is typed and when we get notice of it, but * since characters tend to be typed at the end * of the buffer, we don't run into it. There's * no workaround possible for this typing race, * since we can't tell when the user has typed * something but we just haven't been notified. */ if(pendingS) pendingK = 1; else hostpt += sendinput(w, hostpt, &endpt); } break; } break; case 'M': /* mouse */ delta = e->q1-e->q0; switch(e->c2){ case 'x': case 'X': execevent(w, e, command); break; case 'l': /* reflect all searches back to acme */ case 'L': if(e->flag & 2) recvp(w->cevent); winwriteevent(w, e); break; case 'I': endpt += delta; if(e->q0 < hostpt) hostpt += delta; else hostpt += sendinput(w, hostpt, &endpt); break; case 'D': endpt -= delta; if(e->q1 < hostpt) hostpt -= delta; else if(e->q0 < hostpt) hostpt = e->q0; break; case 'd': /* modify away; we don't care */ case 'i': break; default: goto Unknown; } } } }
char* tcs(char *charset, char *s) { char *buf; int i, n, nbuf; int fd[3], p[2], pp[2]; uchar *us; char *t, *u; char *argv[4]; Rune r; Writeargs *w; if(s == nil || charset == nil || *s == 0) return s; if(cistrcmp(charset, "utf-8") == 0) return s; if(cistrcmp(charset, "iso-8859-1") == 0 || cistrcmp(charset, "us-ascii") == 0){ latin1: n = 0; for(us=(uchar*)s; *us; us++) n += runelen(*us); n++; t = emalloc(n); for(us=(uchar*)s, u=t; *us; us++){ r = *us; u += runetochar(u, &r); } *u = 0; free(s); return t; } for(i=0; i<nelem(tcstab); i++) if(cistrcmp(charset, tcstab[i].mime) == 0) goto tcs; goto latin1; tcs: argv[0] = "tcs"; argv[1] = "-f"; argv[2] = charset; argv[3] = nil; if(pipe(p) < 0 || pipe(pp) < 0) sysfatal("pipe: %r"); fd[0] = p[0]; fd[1] = pp[0]; fd[2] = dup(2, -1); if(threadspawnl(fd, "tcs", "tcs", "-f", tcstab[i].tcs, nil) < 0){ close(p[0]); close(p[1]); close(pp[0]); close(pp[1]); close(fd[2]); goto latin1; } close(p[0]); close(pp[0]); nbuf = UTFmax*strlen(s)+100; /* just a guess at worst case */ buf = emalloc(nbuf); w = emalloc(sizeof *w); w->fd = p[1]; w->s = estrdup(s); proccreate(twriter, w, STACK); n = readn(pp[1], buf, nbuf-1); close(pp[1]); if(n <= 0){ free(buf); goto latin1; } buf[n] = 0; free(s); s = estrdup(buf); free(buf); return s; }
void threadmain(int argc, char **argv) { char *p, *q; Dir *d; Window *w; ARGBEGIN{ case 'D': debug++; break; case 'd': dir = EARGF(usage()); break; default: usage(); break; }ARGEND if(argc != 1) usage(); from = findfrom(); group = estrdup(argv[0]); /* someone will be cute */ while(q=strchr(group, '/')) *q = '.'; p = estrdup(argv[0]); while(q=strchr(p, '.')) *q = '/'; p = estrstrstrdup(dir, "/", p); cleanname(p); if((d = dirstat(p)) == nil){ /* maybe it is a new group */ if((d = dirstat(dir)) == nil){ fprint(2, "dirstat(%s) fails: %r\n", dir); threadexitsall(nil); } if((d->mode&DMDIR)==0){ fprint(2, "%s not a directory\n", dir); threadexitsall(nil); } free(d); if((d = dirstat(p)) == nil){ fprint(2, "stat %s: %r\n", p); threadexitsall(nil); } } if((d->mode&DMDIR)==0){ fprint(2, "%s not a directory\n", dir); threadexitsall(nil); } free(d); dir = estrstrdup(p, "/"); q = estrstrdup(dir, "post"); canpost = access(q, AWRITE)==0; w = newwindow(); root = w; proccreate(wineventproc, w, STACK); proccreate(timerproc, w, STACK); winname(w, dir); if(canpost) wintagwrite(w, "Newpost ", 8); wintagwrite(w, "More ", 5); dirwindow(w); threadcreate(dirthread, w, STACK); threadexits(nil); }