static void icachewritecoord(void *v) { int i, err; Index *ix; AState as; USED(v); threadsetname("icachewritecoord"); ix = mainindex; iwrite.as = icachestate(); for(;;){ trace(TraceProc, "icachewritecoord sleep"); waitforkick(&iwrite.round); trace(TraceWork, "start"); as = icachestate(); if(as.arena==iwrite.as.arena && as.aa==iwrite.as.aa){ /* will not be able to do anything more than last flush - kick disk */ trace(TraceProc, "icachewritecoord kick dcache"); kickdcache(); trace(TraceProc, "icachewritecoord kicked dcache"); goto SkipWork; /* won't do anything; don't bother rewriting bloom filter */ } iwrite.as = as; trace(TraceProc, "icachewritecoord start flush"); if(iwrite.as.arena){ for(i=0; i<ix->nsects; i++) send(ix->sects[i]->writechan, 0); if(ix->bloom) send(ix->bloom->writechan, 0); err = 0; for(i=0; i<ix->nsects; i++) err |= recvul(ix->sects[i]->writedonechan); if(ix->bloom) err |= recvul(ix->bloom->writedonechan); trace(TraceProc, "icachewritecoord donewrite err=%d", err); if(err == 0){ setatailstate(&iwrite.as); } } SkipWork: icacheclean(nil); /* wake up anyone waiting */ trace(TraceWork, "finish"); addstat(StatIcacheFlush, 1); } }
static int wait4data(Serialport *p, uchar *data, int count) { int d; Serial *ser; ser = p->s; qunlock(ser); d = sendul(p->w4data, 1); qlock(ser); if(d <= 0) return -1; if(p->ndata >= count) p->ndata -= count; else { count = p->ndata; p->ndata = 0; } memmove(data, p->data, count); if(p->ndata != 0) memmove(p->data, p->data+count, p->ndata); recvul(p->gotdata); return count; }
/* * Receives message string from the network and * returns the appropriate numeric token. If error * occurs -1 is returned. */ int recvmstr(int sock,char **s) { char buf[MAX_MSGSTR + 1]; unsigned long ultmp; int i; size_t len; DLOG_MSG(("recvmstr() : recvul(%d)",sock)); if (!recvul(sock,&ultmp)) return -1; len = (size_t)ultmp; if (len == 0 || len > MAX_MSGSTR) { errlog(LOG_ERR,"recvmstr() : len=%lu",(unsigned long)len); return -1; } DLOG_MSG(("recvmstr() : x_recv(%d)",sock)); if (!x_recv(sock,buf,len)) { DLOG_ERROR(("recvstr()")); return -1; } buf[len] = '\0'; DLOG_MSG(("recvstr() : buf=%s",buf)); for (i = 0; s[i]; i++) if (streql(s[i],buf)) return i; errlog(LOG_ERR,"recvmstr() : unknown message (%s)",buf); return -1; }
static void execthread(void *a) { Client *c; int p; char tmp[32]; c = a; snprint(tmp, sizeof tmp, "exec%d", c->num); threadsetname(tmp); c->execpid = chancreate(sizeof(ulong), 0); proccreate(execproc, c, STACK); p = recvul(c->execpid); chanfree(c->execpid); c->execpid = nil; close(c->fd[1]); c->fd[1] = c->fd[0]; if(p != -1){ c->pid = p; c->activethread = 2; threadcreate(readthread, c, STACK); threadcreate(writethread, c, STACK); if(c->execreq) respond(c->execreq, nil); }else{ if(c->execreq) respond(c->execreq, c->err); } }
int pipeline(int fd, char *cmd, ...) { Exec *e; va_list a; e = emalloc(sizeof(Exec)); if(pipe(e->p)<0 || pipe(e->q)<0) error("can't create pipe"); close(e->p[0]); e->p[0] = fd; va_start(a, cmd); e->cmd = vsmprint(cmd, a); va_end(a); e->sync = chancreate(sizeof(ulong), 0); if(e->sync == nil) error("can't create channel"); proccreate(execproc, e, STACK); recvul(e->sync); chanfree(e->sync); free(e->cmd); close(e->p[0]); close(e->p[1]); close(e->q[1]); fd = e->q[0]; free(e); return fd; }
static Cimage * loadimg(Rune *src, int x , int y) { Channel *sync; Cimage *ci; Runestr rs; Exec *e; char *filter; int fd, p[2], q[2]; ci = emalloc(sizeof(Cimage)); rs. r = src; rs.nr = runestrlen(rs.r); ci->url = urlalloc(&rs, nil, HGet); fd = urlopen(ci->url); if(fd < 0){ Err1: return ci; } filter = getfilter(ci->url->ctype.r, x, y); if(filter == nil){ werrstr("%S unsupported: %S", ci->url->ctype.r, ci->url->act.r); Err2: close(fd); goto Err1; } if(pipe(p)<0 || pipe(q)<0) error("can't create pipe"); close(p[0]); p[0] = fd; sync = chancreate(sizeof(ulong), 0); if(sync == nil) error("can't create channel"); 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 = filter; e->sync = sync; proccreate(execproc, e, STACK); recvul(sync); chanfree(sync); close(p[0]); close(p[1]); close(q[1]); ci->mi = readmemimage(q[0]); close(q[0]); if(ci->mi == nil){ werrstr("can't read image"); goto Err2; } free(filter); return ci; }
int confirmkey(Conv *c, Key *k) { int ret; if(*confirminuse == 0) return -1; lbappend(&confbuf, "confirm tag=%lud %A %N", c->tag, k->attr, k->privattr); flog("confirm %A %N", k->attr, k->privattr); c->state = "keyconfirm"; ret = recvul(c->keywait); flog("confirm=%d %A %N", ret, k->attr, k->privattr); return ret; }
int threadspawn(int fd[3], char *cmd, char *argv[]) { int pid; Execjob e; e.fd = fd; e.cmd = cmd; e.argv = argv; e.c = chancreate(sizeof(void*), 0); proccreate(execproc, &e, 65536); close(fd[0]); close(fd[1]); close(fd[2]); pid = recvul(e.c); chanfree(e.c); return pid; }
static void statusreader(void *u) { Areader *a; Channel *c; Packser *pk; Serialport *p; Serial *ser; int cl; p = u; ser = p->s; threadsetname("statusreader thread"); /* big buffering, fewer bytes lost */ c = chancreate(sizeof(Packser *), 128); a = emallocz(sizeof(Areader), 1); a->p = p; a->c = c; incref(ser->dev); proccreate(epreader, a, 16*1024); while((pk = recvp(c)) != nil){ memmove(p->data, pk->b, pk->nb); p->ndata = pk->nb; free(pk); dsprint(2, "serial %p: status reader %d \n", p, p->ndata); /* consume it all */ while(p->ndata != 0){ dsprint(2, "serial %p: status reader to consume: %d\n", p, p->ndata); cl = recvul(p->w4data); if(cl < 0) break; cl = sendul(p->gotdata, 1); if(cl < 0) break; } } shutdownchan(c); devctl(ser->dev, "detach"); closedev(ser->dev); usbfsdel(&p->fs); }
void startcmd(char *argv[], int *notepg) { struct Exec *e; Channel *cpid; char buf[64]; int pid; e = emalloc(sizeof(struct Exec)); e->argv = argv; cpid = chancreate(sizeof(uint32_t), 0); e->cpid = cpid; sprint(buf, "/mnt/wsys/%d", win->id); bind(buf, "/dev/acme", MREPL); proccreate(execproc, e, EXECSTACK); do pid = recvul(cpid); while(pid == -1); sprint(buf, "/proc/%d/notepg", pid); *notepg = open(buf, OWRITE); }
/* * Receives string from network (length info comes first) and * returns an allocated buffer containing the string and its length * (len will be in the same form as when returned by strlen(), i.e., * excluding the null terminator). If len is zero, the string * was empty in which case strorage will not be allocated * and the actual x_recv() for the string is not performed. * If the string buffer passed to recvstr() was not empty (i.e., * the pointer to it was not null) it is freed first. */ int recvstr(int sock,char **s,size_t *len) { unsigned long ultmp; DLOG_MSG(("recvstr() : recvul(%d)",sock)); if (!recvul(sock,&ultmp)) return 0; *len = (size_t)ultmp; if (*s) x_free(*s); if (*len > 0) { DLOG_MSG(("recvstr() : x_recv(%d)",sock)); *s = (char *)x_malloc(*len + 1); if (!x_recv(sock,*s,*len)) { DLOG_ERROR(("recvstr()")); return 0; } DLOG_MSG(("recvstr() : *s=%s",*s)); } else *s = (char *)0; return 1; }
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; }
int startdev(Port *pp) { Dev *d; Usbdev *ud; Devtab *dt; Sarg *sa; Channel *rc; d = pp->dev; assert(d); ud = d->usb; assert(ud != nil); writeinfo(d); if(ud->class == Clhub){ /* * Hubs are handled directly by this process avoiding * concurrent operation so that at most one device * has the config address in use. * We cancel kernel debug for these eps. too chatty. */ pp->hub = newhub(d->dir, d); if(pp->hub == nil) fprint(2, "%s: %s: %r\n", argv0, d->dir); else fprint(2, "usb/hub... "); if(usbdebug > 1) devctl(d, "debug 0"); /* polled hubs are chatty */ return pp->hub == nil ? -1 : 0; } for(dt = devtab; dt->name != nil; dt++) if(devmatch(dt, ud)) break; /* * From here on the device is for the driver. * When we return pp->dev contains a Dev just for us * with only the ctl open. Both devs are released on the last closedev: * driver's upon I/O errors and ours upon port dettach. */ if(dt->name == nil){ dprint(2, "%s: no configured entry for %s (csp %#08lx)\n", argv0, d->dir, ud->csp); close(d->dfd); d->dfd = -1; return 0; } sa = emallocz(sizeof(Sarg), 1); sa->pp = pp; sa->dt = dt; rc = sa->rc = chancreate(sizeof(uint32_t), 1); procrfork(startdevproc, sa, Stack, RFNOTEG); if(recvul(rc) != 0) free(sa); chanfree(rc); fprint(2, "usb/%s... ", dt->name); sleep(Spawndelay); /* in case we re-spawn too fast */ 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 threadmain(int argc, char *argv[]) { int i; char *p, *loadfile; Column *c; int ncol; Display *d; rfork(RFENVG|RFNAMEG); ncol = -1; loadfile = nil; ARGBEGIN{ case 'D': {extern int _threaddebuglevel; _threaddebuglevel = ~0; } break; 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; case 'm': mtpt = ARGF(); if(mtpt == nil) goto Usage; break; case 'r': swapscrollbuttons = TRUE; break; case 'W': winsize = ARGF(); if(winsize == nil) goto Usage; break; default: Usage: fprint(2, "usage: acme -a -c ncol -f fontname -F fixedwidthfontname -l loadfile -W winsize\n"); threadexitsall("usage"); }ARGEND fontnames[0] = estrdup(fontnames[0]); fontnames[1] = estrdup(fontnames[1]); quotefmtinstall(); fmtinstall('t', timefmt); cputype = getenv("cputype"); objtype = getenv("objtype"); home = getenv("HOME"); acmeshell = getenv("acmeshell"); if(acmeshell && *acmeshell == '\0') acmeshell = nil; 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"); threadexitsall("geninitdraw"); } */ if(initdraw(derror, fontnames[0], "acme") < 0){ fprint(2, "acme: can't open display: %r\n"); threadexitsall("initdraw"); } d = display; font = d->defaultfont; /*assert(font); */ reffont.f = font; reffonts[0] = &reffont; incref(&reffont.ref); /* one to hold up 'font' variable */ incref(&reffont.ref); /* 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"); } chansetname(ccommand, "ccommand"); chansetname(ckill, "ckill"); chansetname(cxfidalloc, "cxfidalloc"); chansetname(cxfidfree, "cxfidfree"); chansetname(cnewwindow, "cnewwindow"); chansetname(cerr, "cerr"); chansetname(cedit, "cedit"); chansetname(cexit, "cexit"); chansetname(cwarn, "cwarn"); mousectl = initmouse(nil, screen); if(mousectl == nil){ fprint(2, "acme: can't initialize mouse: %r\n"); threadexitsall("mouse"); } mouse = &mousectl->m; keyboardctl = initkeyboard(nil); if(keyboardctl == nil){ fprint(2, "acme: can't initialize keyboard: %r\n"); threadexitsall("keyboard"); } mainpid = getpid(); startplumbing(); /* plumbeditfd = plumbopen("edit", OREAD|OCEXEC); if(plumbeditfd < 0) fprint(2, "acme: can't initialize plumber: %r\n"); else{ cplumb = chancreate(sizeof(Plumbmsg*), 0); threadcreate(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); /* threadcreate(shutdownthread, nil, STACK); */ threadnotify(shutdown, 1); recvul(cexit); killprocs(); threadexitsall(nil); }
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 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); }