static Xfid* fsysclunk(Xfid *x, Fid *f) { fsysdelid(f->mntdir); sendp(x->c, xfidclose); return nil; }
/* * Called only in exec.c:/^run(), from a different FD group */ Mntdir* fsysmount(Rune *dir, int ndir, Rune **incl, int nincl) { char buf[256]; Mntdir *m; /* close server side so don't hang if acme is half-exited */ close(sfd); m = fsysaddid(dir, ndir, incl, nincl); sprint(buf, "%d", m->id); if(mount(cfd, -1, "/mnt/acme", MREPL, buf) < 0) { fsysdelid(m); return nil; } close(cfd); bind("/mnt/acme", "/mnt/wsys", MREPL); if(bind("/mnt/acme", "/dev", MBEFORE) < 0) { fsysdelid(m); return nil; } return m; }
/* called while row is locked */ void flushwarnings(void) { Warning *warn, *next; Window *w; Text *t; int owner, nr, q0, n; Rune *r; for(warn=warnings; warn; warn=next) { w = errorwin(warn->md, 'E'); t = &w->body; owner = w->owner; if(owner == 0) w->owner = 'E'; wincommit(w, t); /* * Most commands don't generate much output. For instance, * Edit ,>cat goes through /dev/cons and is already in blocks * because of the i/o system, but a few can. Edit ,p will * put the entire result into a single hunk. So it's worth doing * this in blocks (and putting the text in a buffer in the first * place), to avoid a big memory footprint. */ r = fbufalloc(); q0 = t->file->nc; for(n = 0; n < warn->buf.nc; n += nr){ nr = warn->buf.nc - n; if(nr > RBUFSIZE) nr = RBUFSIZE; bufread(&warn->buf, n, r, nr); textbsinsert(t, t->file->nc, r, nr, TRUE, &nr); } textshow(t, q0, t->file->nc, 1); free(r); winsettag(t->w); textscrdraw(t); w->owner = owner; w->dirty = FALSE; winunlock(w); bufclose(&warn->buf); next = warn->next; if(warn->md) fsysdelid(warn->md); free(warn); } warnings = nil; }
static Xfid* fsyswalk(Xfid *x, Fid *f) { Fcall t; int c, i, j, id; Qid q; uint8_t type; uint32_t path; Fid *nf; Dirtab *d, *dir; Window *w; char *err; nf = nil; w = nil; if(f->open) return respond(x, &t, "walk of open file"); if(x->fid != x->newfid) { nf = newfid(x->newfid); if(nf->busy) return respond(x, &t, "newfid already in use"); nf->busy = TRUE; nf->open = FALSE; nf->mntdir = f->mntdir; if(f->mntdir) f->mntdir->ref++; nf->dir = f->dir; nf->qid = f->qid; nf->w = f->w; nf->nrpart = 0; /* not open, so must be zero */ if(nf->w) incref(nf->w); f = nf; /* walk f */ } t.nwqid = 0; err = nil; dir = nil; id = WIN(f->qid); q = f->qid; if(x->nwname > 0) { for(i=0; i<x->nwname; i++) { if((q.type & QTDIR) == 0) { err = Enotdir; break; } if(strcmp(x->wname[i], "..") == 0) { type = QTDIR; path = Qdir; id = 0; if(w) { winclose(w); w = nil; } Accept: if(i == MAXWELEM) { err = "name too long"; break; } q.type = type; q.vers = 0; q.path = QID(id, path); t.wqid[t.nwqid++] = q; continue; } /* is it a numeric name? */ for(j=0; (c=x->wname[i][j]); j++) if(c<'0' || '9'<c) goto Regular; /* yes: it's a directory */ if(w) /* name has form 27/23; get out before losing w */ break; id = atoi(x->wname[i]); qlock(&row); w = lookid(id, FALSE); if(w == nil) { qunlock(&row); break; } incref(w); /* we'll drop reference at end if there's an error */ path = Qdir; type = QTDIR; qunlock(&row); dir = dirtabw; goto Accept; Regular: // if(FILE(f->qid) == Qacme) /* empty directory */ // break; if(strcmp(x->wname[i], "new") == 0) { if(w) error("w set in walk to new"); sendp(cnewwindow, nil); /* signal newwindowthread */ w = recvp(cnewwindow); /* receive new window */ incref(w); type = QTDIR; path = QID(w->id, Qdir); id = w->id; dir = dirtabw; goto Accept; } if(id == 0) d = dirtab; else d = dirtabw; d++; /* skip '.' */ for(; d->name; d++) if(strcmp(x->wname[i], d->name) == 0) { path = d->qid; type = d->type; dir = d; goto Accept; } break; /* file not found */ } if(i==0 && err == nil) err = Eexist; } if(err!=nil || t.nwqid<x->nwname) { if(nf) { nf->busy = FALSE; fsysdelid(nf->mntdir); } } else if(t.nwqid == x->nwname) { if(w) { f->w = w; w = nil; /* don't drop the reference */ } if(dir) f->dir = dir; f->qid = q; } if(w != nil) winclose(w); return respond(x, &t, err); }
void waitthread(void *v) { Waitmsg *w; Command *c, *lc; uint pid; int found, ncmd; Rune *cmd; char *err; Text *t; Pid *pids, *p, *lastp; enum { WErr, WKill, WWait, WCmd, NWALT }; Alt alts[NWALT+1]; USED(v); threadsetname("waitthread"); pids = nil; alts[WErr].c = cerr; alts[WErr].v = &err; alts[WErr].op = CHANRCV; alts[WKill].c = ckill; alts[WKill].v = &cmd; alts[WKill].op = CHANRCV; alts[WWait].c = cwait; alts[WWait].v = &w; alts[WWait].op = CHANRCV; alts[WCmd].c = ccommand; alts[WCmd].v = &c; alts[WCmd].op = CHANRCV; alts[NWALT].op = CHANEND; command = nil; for(;;){ switch(alt(alts)){ case WErr: qlock(&row.lk); warning(nil, "%s", err); free(err); flushimage(display, 1); qunlock(&row.lk); break; case WKill: found = FALSE; ncmd = runestrlen(cmd); for(c=command; c; c=c->next){ /* -1 for blank */ if(runeeq(c->name, c->nname-1, cmd, ncmd) == TRUE){ if(postnote(PNGROUP, c->pid, "kill") < 0) warning(nil, "kill %S: %r\n", cmd); found = TRUE; } } if(!found) warning(nil, "Kill: no process %S\n", cmd); free(cmd); break; case WWait: pid = w->pid; lc = nil; for(c=command; c; c=c->next){ if(c->pid == pid){ if(lc) lc->next = c->next; else command = c->next; break; } lc = c; } qlock(&row.lk); t = &row.tag; textcommit(t, TRUE); if(c == nil){ /* helper processes use this exit status */ if(strncmp(w->msg, "libthread", 9) != 0){ p = emalloc(sizeof(Pid)); p->pid = pid; strncpy(p->msg, w->msg, sizeof(p->msg)); p->next = pids; pids = p; } }else{ if(search(t, c->name, c->nname)){ textdelete(t, t->q0, t->q1, TRUE); textsetselect(t, 0, 0); } if(w->msg[0]) warning(c->md, "%.*S: exit %s\n", c->nname-1, c->name, w->msg); flushimage(display, 1); } qunlock(&row.lk); free(w); Freecmd: if(c){ if(c->iseditcmd) sendul(cedit, 0); free(c->text); free(c->name); fsysdelid(c->md); free(c); } break; case WCmd: /* has this command already exited? */ lastp = nil; for(p=pids; p!=nil; p=p->next){ if(p->pid == c->pid){ if(p->msg[0]) warning(c->md, "%s\n", p->msg); if(lastp == nil) pids = p->next; else lastp->next = p->next; free(p); goto Freecmd; } lastp = p; } c->next = command; command = c; qlock(&row.lk); t = &row.tag; textcommit(t, TRUE); textinsert(t, 0, c->name, c->nname, TRUE); textsetselect(t, 0, 0); flushimage(display, 1); qunlock(&row.lk); break; } } }