Exemple #1
0
static void
xioproc(void *a)
{
	Channel *c;
	Ioproc *io;
	Iocall *r;

	c = a;
	if(io = mallocz(sizeof(*io), 1)){
		char buf[128];

		/*
		 * open might fail, ignore it for programs like factotum
		 * that don't use iointerrupt() anyway.
		 */
		snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
		io->ctl = open(buf, OWRITE);

		if((io->creply = chancreate(sizeof(void*), 0)) == nil){
			if(io->ctl >= 0)
				close(io->ctl);
			free(io);
			io = nil;
		} else
			io->c = c;
	}
	while(send(c, &io) < 0)
		;
	if(io == nil)
		return;

	for(;;){
		while(recv(io->c, &r) < 0)
			;
		if(r == 0)
			break;
		if(io->intr){
			r->ret = -1;
			strcpy(r->err, "interrupted");
		} else if((r->ret = r->op(&r->arg)) < 0)
			rerrstr(r->err, sizeof r->err);
		qlock(io);
		if(io->intr){
			io->intr = 0;
			if(io->ctl >= 0)
				write(io->ctl, "nointerrupt", 11);
		}
		while(send(io->creply, &r) < 0)
			;
		qunlock(io);
	}

	if(io->ctl >= 0)
		close(io->ctl);
	chanfree(io->c);
	chanfree(io->creply);
	free(io);
}
Exemple #2
0
void
convfree(Conv *c)
{
	freeattr(c->attr);
	free(c->sysuser);
	chanfree(c->rpcwait);
	chanfree(c->keywait);
	free(c);
}
Exemple #3
0
int
main(void)
{
	int i, nprocs, procn[Nproc];
	
	fail = 0;
	nprocs = 0;
	ch = chancreate(1000, sizeof(int));
	if(ch == nil){
		fail = 1;
		printf("chancreate failed\n");
	}
		
	for(i = 0; i < Nproc; ++i){
		procn[i] = i + 1;
		if(proccreate(f, &procn[i], 0) == nil){
			fail = 1;
			printf("proccreate failed\n");
		}else{
			nprocs++;
		}
	}
	
	for(i = 0; i < nprocs; ++i){
		int n;
		
		if(chanrecv(ch, &n) != 1){
			fail = 1;
			printf("recv error\n");
		}
	}
	chanfree(ch);
	return fail;
}
Exemple #4
0
int
sunsrvudp(SunSrv *srv, char *address)
{
	int fd;
	char adir[40];
	Arg *arg;

	fd = announce(address, adir);
	if(fd < 0)
		return -1;

	arg = emalloc(sizeof(Arg));
	arg->fd = fd;
	arg->srv = srv;
	arg->creply = chancreate(sizeof(SunMsg*), 10);
	arg->csync = chancreate(sizeof(void*), 10);

	proccreate(sunudpread, arg, SunStackSize);
	proccreate(sunudpwrite, arg, SunStackSize);
	recvp(arg->csync);
	recvp(arg->csync);
	chanfree(arg->csync);
	free(arg);

	return 0;
}
Exemple #5
0
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);
	}
}
Exemple #6
0
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;
}
Exemple #7
0
static void
etherfree(Ether *e)
{
	int i;
	Buf *bp;

	if(e->free != nil)
		e->free(e);
	closedev(e->epin);
	closedev(e->epout);
	if(e->rc == nil){	/* not really started */
		free(e);
		return;
	}
	for(i = 0; i < e->nconns; i++)
		if(e->conns[i] != nil){
			while((bp = nbrecvp(e->conns[i]->rc)) != nil)
				free(bp);
			chanfree(e->conns[i]->rc);
			free(e->conns[i]);
		}
	shutdownchan(e->bc);
	shutdownchan(e->rc);
	shutdownchan(e->wc);
	e->epin = e->epout = nil;
	devctl(e->dev, "detach");
	free(e);
}
Exemple #8
0
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;
}
Exemple #9
0
static void
shutdownchan(Channel *c)
{
    Packser *bp;

    while((bp=nbrecvp(c)) != nil)
        free(bp);
    chanfree(c);
}
Exemple #10
0
Waitmsg*
twaitfor(int pid)
{
	Waitreq r;
	Waitmsg *w;
	
	r.pid = pid;
	r.c = chancreate(sizeof(Waitmsg*), 1);
	send(twaitchan, &r);
	w = recvp(r.c);
	chanfree(r.c);
	return w;
}
Exemple #11
0
int
wctlmesg(Window *w, int m, Console *i)
{
	print_func_entry();
	switch(m){
	default:
		error("unknown control message");
		break;
	case Wakeup:
		break;
	case Rawon:
		break;
	case Rawoff:
		if(w->deleted)
			break;
		while(w->nraw > 0){
			//wkeyctl(w, w->raw[0]);
			--w->nraw;
			runemove(w->raw, w->raw+1, w->nraw);
		}
		break;
	case Holdon:
	case Holdoff:
		if(w->deleted)
			break;
		break;
	case Deleted:
		if(w->deleted)
			break;
		write(w->notefd, "hangup", 6);
		proccreate(deletetimeoutproc, estrdup(w->name), 4096);
		wclosewin(w);
		break;
	case Exited:
		close(w->notefd);
		chanfree(w->mc.c);
		chanfree(w->ck);
		chanfree(w->cctl);
		chanfree(w->conswrite);
		chanfree(w->consread);
		chanfree(w->mouseread);
		chanfree(w->wctlread);
		free(w->raw);
		free(w->run);
		free(w->dir);
		free(w->label);
		free(w);
		break;
	}
	print_func_exit();
	return m;
}
Exemple #12
0
void
closekeyboard(Keyboardctl *kc)
{
    Rune r;

    if(kc == nil)
        return;

    /*	postnote(PNPROC, kc->pid, "kill"); */

    do;
    while(nbrecv(kc->c, &r) > 0);
    chanfree(kc->c);
    free(kc);
}
Exemple #13
0
static void chan_release(struct kref *kref)
{
	struct chan *c = container_of(kref, struct chan, ref);
	ERRSTACK(1);
	/* this style discards the error from close().  picture it as
	 * if (waserror()) { } else { close(); } chanfree_no_matter_what();  */
	if (!waserror()) {
		printd("releasing chan %p, type %d\n", c, c->type);
		/* -1 means there is no dev yet.  wants a noop for close() */
		if (c->type != -1)
			devtab[c->type].close(c);
	}
	/* need to poperror regardless of whether we error'd or not */
	poperror();
	/* and chan free no matter what */
	chanfree(c);
}
Exemple #14
0
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;
}
Exemple #15
0
void
threadmain(int argc, char *argv[])
{
	char buf[512];
	int fd;
	Channel *c;

	progname = "plumber";

	ARGBEGIN{
	case 'p':
		plumbfile = ARGF();
		break;
	}ARGEND

	user = getenv("user");
	home = getenv("home");
	if(user==nil || home==nil)
		error("can't initialize $user or $home: %r");
	if(plumbfile == nil){
		sprint(buf, "%s/lib/plumbing", home);
		plumbfile = estrdup(buf);
	}

	fd = open(plumbfile, OREAD);
	if(fd < 0)
		error("can't open rules file %s: %r", plumbfile);
	if(setjmp(parsejmp))
		error("parse error");

	rules = readrules(plumbfile, fd);
	close(fd);

	/*
	 * Start all processes and threads from other proc
	 * so we (main pid) can return to user.
	 */
	c = chancreate(sizeof(void*), 0);
	proccreate(mainproc, c, 8192);
	recvp(c);
	chanfree(c);
	threadexits(nil);
}
Exemple #16
0
void
execproc(void *v)
{
	struct Exec *e;
	int p[2], q[2];
	char *prog;
	char *argv[NARGS+1], args[NARGCHAR];

	e = v;
	p[0] = e->p[0];
	p[1] = e->p[1];
	q[0] = e->q[0];
	q[1] = e->q[1];
	prog = e->prog;	/* known not to be malloc'ed */
	rfork(RFFDG);
	sendul(e->sync, 1);
	buildargv(e->argv, argv, args);
	free(e->argv);
	chanfree(e->sync);
	free(e);
	dup(p[0], 0);
	close(p[0]);
	close(p[1]);
	if(q[0]){
		dup(q[1], 1);
		close(q[0]);
		close(q[1]);
	}
	procexec(nil, prog, argv);
//fprint(2, "exec: %s", e->prog);
//{int i;
//for(i=0; argv[i]; i++) print(" '%s'", argv[i]);
//print("\n");
//}
//argv[0] = "cat";
//argv[1] = nil;
//procexec(nil, "/bin/cat", argv);
	fprint(2, "Mail: can't exec %s: %r\n", prog);
	threadexits("can't exec");
}
Exemple #17
0
void
ventiproc(void *dummy)
{
	int i;
	Block *db;
	u32int bno;
	u64int bsize;

	USED(dummy);

	proccreate(vtsendproc, z, STACK);
	proccreate(vtrecvproc, z, STACK);

	writechan = chancreate(sizeof(WriteReq), 0);
	for(i=0; i<nwritethread; i++)
		threadcreate(writethread, nil, STACK);
	vtcachesetwrite(zcache, myvtwrite);

	bsize = fsys->blocksize;
	vtfilelock(vfile, -1);
	while((db = qread(qventi, &bno)) != nil){
		if(nop){
			blockput(db);
			continue;
		}
		if(vtfilewrite(vfile, db->data, bsize, bno*bsize) != bsize)
			sysfatal("ventiproc vtfilewrite: %r");
		if(vtfileflushbefore(vfile, (bno+1)*bsize) < 0)
			sysfatal("ventiproc vtfileflushbefore: %r");
		blockput(db);
	}
	vtfileunlock(vfile);
	vtcachesetwrite(zcache, nil);
	for(i=0; i<nwritethread; i++)
		send(writechan, nil);
	chanfree(writechan);
	if(statustime)
		print("# %T venti proc exiting - nsend %d nrecv %d\n", nsend, nrecv);
	runlock(&endlk);
}
Exemple #18
0
/*
 *  create a pipe, no streams are created until an open
 */
static Chan*
pipeattach(char *spec)
{
	Pipe *p;
	Chan *c;

	c = devattach('|', spec);
	if(waserror()){
		chanfree(c);
		nexterror();
	}
	p = malloc(sizeof(Pipe));
	if(p == 0)
		exhausted("memory");
	p->ref = 1;

	p->q[0] = qopen(conf.pipeqsize, 0, 0, 0);
	if(p->q[0] == 0){
		free(p);
		exhausted("memory");
	}
	p->q[1] = qopen(conf.pipeqsize, 0, 0, 0);
	if(p->q[1] == 0){
		qfree(p->q[0]);
		free(p);
		exhausted("memory");
	}
	poperror();

	lock(&pipealloc);
	p->path = ++pipealloc.path;
	unlock(&pipealloc);
	p->perm = pipedir[Qdata0].perm;

	mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR);
	c->aux = p;
	c->dev = 0;
	return c;
}
Exemple #19
0
void
execproc(void *v)
{
	struct Exec *e;
	int p[2], q[2];
	char *prog;
	char *argv[NARGS+1], args[NARGCHAR];
	int fd[3];

	e = v;
	p[0] = e->p[0];
	p[1] = e->p[1];
	q[0] = e->q[0];
	q[1] = e->q[1];
	prog = e->prog;	/* known not to be malloc'ed */
	
	fd[0] = dup(p[0], -1);
	if(q[0])
		fd[1] = dup(q[1], -1);
	else
		fd[1] = dup(1, -1);
	fd[2] = dup(2, -2);
	sendul(e->sync, 1);
	buildargv(e->argv, argv, args);
	free(e->argv);
	chanfree(e->sync);
	free(e);
	
	threadexec(nil, fd, prog, argv);
	close(fd[0]);
	close(fd[1]);
	close(fd[2]);

	fprint(2, "Mail: can't exec %s: %r\n", prog);
	threadexits("can't exec");
}
Exemple #20
0
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;
}
Exemple #21
0
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;
}
Exemple #22
0
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;
}
Exemple #23
0
static void
openfdthread(void *v)
{
	Conn *c;
	Fid *fid;
	Msg *m;
	int n;
	vlong tot;
	Ioproc *io;
	char buf[1024];

	c = v;
	fid = c->fdfid;
	io = ioproc();
	threadsetname("openfd %s", c->fdfid);
	tot = 0;
	m = nil;
	if(c->fdmode == OREAD){
		for(;;){
			if(verbose) fprint(2, "%T tread...");
			m = msgnew(0);
			m->internal = 1;
			m->c = c;
			m->tx.type = Tread;
			m->tx.count = msize - IOHDRSZ;
			m->tx.fid = fid->fid;
			m->tx.tag = m->tag;
			m->tx.offset = tot;
			m->fid = fid;
			fid->ref++;
			msgincref(m);
			sendomsg(m);
			recvp(c->internal);
			if(m->rx.type == Rerror){
			/*	fprint(2, "%T read error: %s\n", m->rx.ename); */
				break;
			}
			if(m->rx.count == 0)
				break;
			tot += m->rx.count;
			if(iowrite(io, c->fd, m->rx.data, m->rx.count) != m->rx.count){
				/* fprint(2, "%T pipe write error: %r\n"); */
				break;
			}
			msgput(m);
			msgput(m);
			m = nil;
		}
	}else{
		for(;;){
			if(verbose) fprint(2, "%T twrite...");
			n = sizeof buf;
			if(n > msize)
				n = msize;
			if((n=ioread(io, c->fd, buf, n)) <= 0){
				if(n < 0)
					fprint(2, "%T pipe read error: %r\n");
				break;
			}
			m = msgnew(0);
			m->internal = 1;
			m->c = c;
			m->tx.type = Twrite;
			m->tx.fid = fid->fid;
			m->tx.data = buf;
			m->tx.count = n;
			m->tx.tag = m->tag;
			m->tx.offset = tot;
			m->fid = fid;
			fid->ref++;
			msgincref(m);
			sendomsg(m);
			recvp(c->internal);
			if(m->rx.type == Rerror){
			/*	fprint(2, "%T write error: %s\n", m->rx.ename); */
			}
			tot += n;
			msgput(m);
			msgput(m);
			m = nil;
		}
	}
	if(verbose) fprint(2, "%T eof on %d fid %d\n", c->fd, fid->fid);
	close(c->fd);
	closeioproc(io);
	if(m){
		msgput(m);
		msgput(m);
	}
	if(verbose) fprint(2, "%T eof on %d fid %d ref %d\n", c->fd, fid->fid, fid->ref);
	if(--fid->openfd == 0){
		m = msgnew(0);
		m->internal = 1;
		m->c = c;
		m->tx.type = Tclunk;
		m->tx.tag = m->tag;
		m->tx.fid = fid->fid;
		m->fid = fid;
		fid->ref++;
		msgincref(m);
		sendomsg(m);
		recvp(c->internal);
		msgput(m);
		msgput(m);
	}
	fidput(fid);
	c->fdfid = nil;
	chanfree(c->internal);
	c->internal = 0;
	free(c);
}			
Exemple #24
0
void
connthread(void *arg)
{
	int i, fd;
	Conn *c;
	Hash *h, *hnext;
	Msg *m, *om, *mm, sync;
	Fid *f;
	Ioproc *io;

	c = arg;
	threadsetname("conn %s", c->dir);
	io = ioproc();
	fd = ioaccept(io, c->fd, c->dir);
	if(fd < 0){
		if(verbose) fprint(2, "%T accept %s: %r\n", c->dir);
		goto out;
	}
	close(c->fd);
	c->fd = fd;
	threadcreate(connoutthread, c, STACK);
	while((m = mread9p(io, c->fd)) != nil){
		if(verbose > 1) fprint(2, "%T fd#%d -> %F\n", c->fd, &m->tx);
		m->c = c;
		m->ctag = m->tx.tag;
		c->nmsg++;
		if(verbose > 1) fprint(2, "%T fd#%d: new msg %p\n", c->fd, m);
		if(puthash(c->tag, m->tx.tag, m) < 0){
			err(m, "duplicate tag");
			continue;
		}
		msgincref(m);
		switch(m->tx.type){
		case Tversion:
			m->rx.tag = m->tx.tag;
			m->rx.msize = m->tx.msize;
			if(m->rx.msize > msize)
				m->rx.msize = msize;
			m->rx.version = "9P2000";
			m->rx.type = Rversion;
			send9pmsg(m);
			continue;
		case Tflush:
			if((m->oldm = gethash(c->tag, m->tx.oldtag)) == nil){
				m->rx.tag = m->tx.tag;
				m->rx.type = Rflush;
				send9pmsg(m);
				continue;
			}
			msgincref(m->oldm);
			break;
		case Tattach:
			m->afid = nil;
			if(m->tx.afid != NOFID
			&& (m->afid = gethash(c->fid, m->tx.afid)) == nil){
				err(m, "unknown fid");
				continue;
			}
			if(m->afid)
				m->afid->ref++;
			m->fid = fidnew(m->tx.fid);
			if(puthash(c->fid, m->tx.fid, m->fid) < 0){
				err(m, "duplicate fid");
				continue;
			}
			m->fid->ref++;
			if(attached && m->afid==nil){
				if(m->tx.aname[0] && strcmp(xaname, m->tx.aname) != 0){
					err(m, "invalid attach name");
					continue;
				}
				m->tx.afid = xafid;
				m->tx.aname = xaname;
				m->tx.uname = getuser();	/* what srv.c used */
				repack(&m->tx, &m->tpkt);
			}
			break;
		case Twalk:
			if((m->fid = gethash(c->fid, m->tx.fid)) == nil){
				err(m, "unknown fid");
				continue;
			}
			m->fid->ref++;
			if(m->tx.newfid == m->tx.fid){
				m->fid->ref++;
				m->newfid = m->fid;
			}else{
				m->newfid = fidnew(m->tx.newfid);
				if(puthash(c->fid, m->tx.newfid, m->newfid) < 0){
					err(m, "duplicate fid");
					continue;
				}
				m->newfid->ref++;
			}
			break;
		case Tauth:
			if(attached){
				err(m, "authentication not required");
				continue;
			}
			if(noauth){
				err(m, "authentication rejected");
				continue;
			}
			m->afid = fidnew(m->tx.afid);
			if(puthash(c->fid, m->tx.afid, m->afid) < 0){
				err(m, "duplicate fid");
				continue;
			}
			m->afid->ref++;
			break;
		case Tcreate:
			if(m->tx.perm&(DMSYMLINK|DMDEVICE|DMNAMEDPIPE|DMSOCKET)){
				err(m, "unsupported file type");
				continue;
			}
			goto caseTopen;
		case Topenfd:
			if(m->tx.mode&~(OTRUNC|3)){
				err(m, "bad openfd mode");
				continue;
			}
			m->isopenfd = 1;
			m->tx.type = Topen;
			m->tpkt[4] = Topen;
			/* fall through */
		caseTopen:
		case Topen:
		case Tclunk:
		case Tread:
		case Twrite:
		case Tremove:
		case Tstat:
		case Twstat:
			if((m->fid = gethash(c->fid, m->tx.fid)) == nil){
				err(m, "unknown fid");
				continue;
			}
			m->fid->ref++;
			break;
		}

		/* have everything - translate and send */
		m->c = c;
		m->ctag = m->tx.tag;
		m->tx.tag = m->tag;
		if(m->fid)
			m->tx.fid = m->fid->fid;
		if(m->newfid)
			m->tx.newfid = m->newfid->fid;
		if(m->afid)
			m->tx.afid = m->afid->fid;
		if(m->oldm)
			m->tx.oldtag = m->oldm->tag;
		/* reference passes to outq */
		sendq(outq, m);
		while(c->nmsg >= MAXMSG){
			c->inputstalled = 1;
			recvp(c->inc);
		}
	}

	if(verbose) fprint(2, "%T fd#%d eof; flushing conn\n", c->fd);

	/* flush all outstanding messages */
	for(i=0; i<NHASH; i++){
		while((h = c->tag[i]) != nil){
			om = h->v;
			msgincref(om); /* for us */
			m = msgnew(0);
			m->internal = 1;
			m->c = c;
			c->nmsg++;
			m->tx.type = Tflush;
			m->tx.tag = m->tag;
			m->tx.oldtag = om->tag;
			m->oldm = om;
			msgincref(om);
			msgincref(m);	/* for outq */
			sendomsg(m);
			mm = recvp(c->internal);
			assert(mm == m);
			msgput(m);	/* got from recvp */
			msgput(m);	/* got from msgnew */
			if(delhash(c->tag, om->ctag, om) == 0)
				msgput(om);	/* got from hash table */
			msgput(om);	/* got from msgincref */
		}
	}

	/*
	 * outputthread has written all its messages
	 * to the remote connection (because we've gotten all the replies!),
	 * but it might not have gotten a chance to msgput
	 * the very last one.  sync up to make sure.
	 */
	memset(&sync, 0, sizeof sync);
	sync.sync = 1;
	sync.c = c;
	sendq(outq, &sync);
	recvp(c->outqdead);

	/* everything is quiet; can close the local output queue. */
	sendq(c->outq, nil);
	recvp(c->outqdead);

	/* should be no messages left anywhere. */
	assert(c->nmsg == 0);

	/* clunk all outstanding fids */
	for(i=0; i<NHASH; i++){
		for(h=c->fid[i]; h; h=hnext){
			f = h->v;
			m = msgnew(0);
			m->internal = 1;
			m->c = c;
			c->nmsg++;
			m->tx.type = Tclunk;
			m->tx.tag = m->tag;
			m->tx.fid = f->fid;
			m->fid = f;
			f->ref++;
			msgincref(m);
			sendomsg(m);
			mm = recvp(c->internal);
			assert(mm == m);
			msgclear(m);
			msgput(m);	/* got from recvp */
			msgput(m);	/* got from msgnew */
			fidput(f);	/* got from hash table */
			hnext = h->next;
			free(h);
		}
	}

out:
	closeioproc(io);
	assert(c->nmsg == 0);
	assert(c->nfid == 0);
	close(c->fd);
	chanfree(c->internal);
	c->internal = 0;
	chanfree(c->inc);
	c->inc = 0;
	free(c->inq);
	c->inq = 0;
	free(c);
}
Exemple #25
0
void
winctl(void *arg)
{
	print_func_entry();
	Rune *rp, *bp, *kbdr;
	int nr, nb, c, wid, i, npart, lastb;
	char *s, *t, part[3];
	Window *w;
	Mousestate *mp, m;
	enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT };
	Alt alts[NWALT+1];
	int walt;
	Mousereadmesg mrm;
	Conswritemesg cwm;
	Consreadmesg crm;
	Consreadmesg cwrm;
	Stringpair pair;
	Wctlmesg wcm;
	char buf[4*12+1];
	w = arg;
	snprint(buf, sizeof buf, "winctl-id%d", w->id);
	threadsetname(buf);

	mrm.cm = chancreate(sizeof(Mouse), 0);
	cwm.cw = chancreate(sizeof(Stringpair), 0);
	crm.c1 = chancreate(sizeof(Stringpair), 0);
	crm.c2 = chancreate(sizeof(Stringpair), 0);
	cwrm.c1 = chancreate(sizeof(Stringpair), 0);
	cwrm.c2 = chancreate(sizeof(Stringpair), 0);


	alts[WKey].c = w->ck;
	alts[WKey].v = &kbdr;
	alts[WKey].op = CHANRCV;
	alts[WMouse].c = w->mc.c;
	alts[WMouse].v = &w->mc.Mouse;
	alts[WMouse].op = CHANNOP; // XXXCHANRCV;
	alts[WMouseread].c = w->mouseread;
	alts[WMouseread].v = &mrm;
	alts[WMouseread].op = CHANNOP; // XXXCHANSND;
	alts[WCtl].c = w->cctl;
	alts[WCtl].v = &wcm;
	alts[WCtl].op = CHANRCV;
	alts[WCwrite].c = w->conswrite;
	alts[WCwrite].v = &cwm;
	alts[WCwrite].op = CHANSND;
	alts[WCread].c = w->consread;
	alts[WCread].v = &crm;
	alts[WCread].op = CHANSND;
	alts[WWread].c = w->wctlread;
	alts[WWread].v = &cwrm;
	alts[WWread].op = CHANSND;
	alts[NWALT].op = CHANEND;

	npart = 0;
	lastb = -1;
	for(;;){
		// TODO: mouses
		if(0 && w->mouseopen && w->mouse.counter != w->mouse.lastcounter)
			alts[WMouseread].op = CHANSND;
		else
			alts[WMouseread].op = CHANNOP;
		if(w->deleted || !w->wctlready)
			alts[WWread].op = CHANNOP;
		else
			alts[WWread].op = CHANSND;
		/* this code depends on NL and EOT fitting in a single byte */
		/* kind of expensive for each loop; worth precomputing? */
		/*if(w->holding)
			alts[WCread].op = CHANNOP;
			else*/ if(npart || (w->rawing && w->nraw>0))
			alts[WCread].op = CHANSND;
		else
		{
			alts[WCread].op = CHANNOP;
			for(i=w->qh; i<w->nr; i++){
				c = w->run[i];
				if(c=='\n' || c=='\004'){
					alts[WCread].op = CHANSND;
					break;
				}
			}
		}

		walt = alt(alts);

		switch(walt){
		case WKey:
			for(i=0; kbdr[i]!=L'\0'; i++)
				wkeyctl(w, kbdr[i]);
			//wkeyctl(w, r);
///			while(nbrecv(w->ck, &r))
				//wkeyctl(w, r);
			break;
		case WMouse:
			if(w->mouseopen) {
				w->mouse.counter++;

				/* queue click events */
				if(!w->mouse.qfull && lastb != w->mc.buttons) {	/* add to ring */
					mp = &w->mouse.queue[w->mouse.wi];
					if(++w->mouse.wi == nelem(w->mouse.queue))
						w->mouse.wi = 0;
					if(w->mouse.wi == w->mouse.ri)
						w->mouse.qfull = TRUE;
					mp->Mouse = w->mc.Mouse;
					mp->counter = w->mouse.counter;
					lastb = w->mc.buttons;
				}
			} else
				fprint(2, "MOUSECTL\n"); //wmousectl(w);
			break;
		case WMouseread:
			/* send a queued event or, if the queue is empty, the current state */
			/* if the queue has filled, we discard all the events it contained. */
			/* the intent is to discard frantic clicking by the user during long latencies. */
			w->mouse.qfull = FALSE;
			if(w->mouse.wi != w->mouse.ri) {
				m = w->mouse.queue[w->mouse.ri];
				if(++w->mouse.ri == nelem(w->mouse.queue))
					w->mouse.ri = 0;
			} else
				m = (Mousestate){w->mc.Mouse, w->mouse.counter};

			w->mouse.lastcounter = m.counter;
			send(mrm.cm, &m.Mouse);
			continue;
		case WCtl:
			exits("WCtl can't do");
#if 0
			if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){
				chanfree(crm.c1);
				chanfree(crm.c2);
				chanfree(mrm.cm);
				chanfree(cwm.cw);
				chanfree(cwrm.c1);
				chanfree(cwrm.c2);
				threadexits(nil);
			}
			#endif
			continue;
		case WCwrite:
			recv(cwm.cw, &pair);
			rp = pair.s;
			nr = pair.ns;
			bp = rp;
			for(i=0; i<nr; i++) {
				// See rio for the run conversion crap. For now, I'm not going to
				// worry about it. This is designed to target Akaros too.
				fprint(/*w->Console->out*/1, "%c", *bp++);
			}
			free(rp);
			break;
		case WCread:
			recv(crm.c1, &pair);
			t = pair.s;
			nb = pair.ns;
			i = npart;
			npart = 0;
			if(i)
				memmove(t, part, i);
			while(i<nb && (w->qh<w->nr || w->nraw>0)){
				if(w->qh == w->nr){
					wid = runetochar(t+i, &w->raw[0]);
					w->nraw--;
					runemove(w->raw, w->raw+1, w->nraw);
				}else
					wid = runetochar(t+i, &w->run[w->qh++]);
				c = t[i];	/* knows break characters fit in a byte */
				i += wid;
				if(!w->rawing && (c == '\n' || c=='\004')){
					if(c == '\004')
						i--;
					break;
				}
			}
			if(i==nb && w->qh<w->nr && w->run[w->qh]=='\004')
				w->qh++;
			if(i > nb){
				npart = i-nb;
				memmove(part, t+nb, npart);
				i = nb;
			}
			pair.s = t;
			pair.ns = i;
			send(crm.c2, &pair);
			continue;
		case WWread:
			w->wctlready = 0;
			recv(cwrm.c1, &pair);
			if(w->deleted)
				pair.ns = sprint(pair.s, "");
			else{
				s = "visible";
				for(i=0; i<nhidden; i++)
					if(hidden[i] == w){
						s = "hidden";
						break;
					}
				t = "notcurrent";
				if(w == input)
					t = "current";
				pair.ns = snprint(pair.s, pair.ns, "%s %s ",t, s);
			}
			send(cwrm.c2, &pair);
			continue;
		}
	}
	print_func_exit();
}
Exemple #26
0
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);
}
Exemple #27
0
static Chan*
loopbackattach(char *spec)
{
	Loop *volatile lb;
	Queue *q;
	Chan *c;
	int chan;
	int dev;

	dev = 0;
	if(spec != nil){
		dev = atoi(spec);
		if(dev >= Nloopbacks)
			error(Ebadspec);
	}

	c = devattach('X', spec);
	if(waserror()){
		chanfree(c);
		nexterror();
	}

	lb = &loopbacks[dev];
	qlock(lb);
	if(waserror()){
		lb->ref--;
		qunlock(lb);
		nexterror();
	}

	lb->ref++;
	if(lb->ref == 1){
		for(chan = 0; chan < 2; chan++){
			lb->link[chan].ci.mode = Trelative;
			lb->link[chan].ci.a = &lb->link[chan];
			lb->link[chan].ci.f = linkintr;
			lb->link[chan].limit = Loopqlim;
			q = qopen(lb->link[chan].limit, 0, 0, 0);
			lb->link[chan].iq = q;
			if(q == nil){
				freelb(lb);
				exhausted("memory");
			}
			q = qopen(lb->link[chan].limit, 0, 0, 0);
			lb->link[chan].oq = q;
			if(q == nil){
				freelb(lb);
				exhausted("memory");
			}
			lb->link[chan].indrop = 1;

			lb->link[chan].delaynns = Delayn;
			lb->link[chan].delay0ns = Delay0;
		}
	}
	poperror();
	qunlock(lb);

	poperror();

	mkqid(&c->qid, QID(0, Qtopdir), 0, QTDIR);
	c->aux = lb;
	c->dev = dev;
	return c;
}
Exemple #28
0
int
mesgcommand(Message *m, char *cmd)
{
	char *s;
	char *args[10];
	int ok, ret, nargs;

	s = cmd;
	ret = 1;
	nargs = tokenize(s, args, nelem(args));
	if(nargs == 0)
		return 0;
	if(strcmp(args[0], "Post") == 0){
		mesgsend(m);
		goto Return;
	}
	if(strncmp(args[0], "Save", 4) == 0){
		if(m->isreply)
			goto Return;
		s = estrdup("\t[saved");
		if(nargs==1 || strcmp(args[1], "")==0){
			ok = mesgsave(m, "stored");
		}else{
			ok = mesgsave(m, args[1]);
			s = eappend(s, " ", args[1]);
		}
		if(ok){
			s = egrow(s, "]", nil);
			mesgmenumark(mbox.w, m->name, s);
		}
		free(s);
		goto Return;
	}
	if(strcmp(args[0], "Reply")==0){
		if(nargs>=2 && strcmp(args[1], "all")==0)
			mkreply(m, "Replyall", nil, nil, nil);
		else
			mkreply(m, "Reply", nil, nil, nil);
		goto Return;
	}
	if(strcmp(args[0], "Q") == 0){
		s = winselection(m->w);	/* will be freed by mkreply */
		if(nargs>=3 && strcmp(args[1], "Reply")==0 && strcmp(args[2], "all")==0)
			mkreply(m, "QReplyall", nil, nil, s);
		else
			mkreply(m, "QReply", nil, nil, s);
		goto Return;
	}
	if(strcmp(args[0], "Del") == 0){
		if(windel(m->w, 0)){
			chanfree(m->w->cevent);
			free(m->w);
			m->w = nil;
			if(m->isreply)
				delreply(m);
			else{
				m->opened = 0;
				m->tagposted = 0;
			}
			free(cmd);
			threadexits(nil);
		}
		goto Return;
	}
	if(strcmp(args[0], "Delmesg") == 0){
		if(!m->isreply){
			mesgmenumarkdel(wbox, &mbox, m, 1);
			free(cmd);	/* mesgcommand might not return */
			mesgcommand(m, estrdup("Del"));
			return 1;
		}
		goto Return;
	}
	if(strcmp(args[0], "UnDelmesg") == 0){
		if(!m->isreply && m->deleted)
			mesgmenumarkundel(wbox, &mbox, m);
		goto Return;
	}
//	if(strcmp(args[0], "Headers") == 0){
//		m->showheaders();
//		return True;
//	}

	ret = 0;

    Return:
	free(cmd);
	return ret;
}
Exemple #29
0
int
synckids(Syncpath *s)
{
	int i, ret, n;
	Channel *c;
	Kids *ak, *bk;

	c = chan(Kids*);
	ak = emalloc(sizeof(*ak));
	ak->repl = s->sync->ra;
	ak->p = s->p;
	ak->c = c;
	spawn(kidthread, ak);

	bk = emalloc(sizeof(*bk));
	bk->repl = s->sync->rb;
	bk->p = s->p;
	bk->c = c;
	spawn(kidthread, bk);

	threadstate("synckids wait %p", c);
	recvp(c);
	threadstate("synckids wait %p", c);
	recvp(c);
	chanfree(c);

	ret = -1;
	if(ak->err){
		s->err = ak->err;
		ak->err = 0;
		s->state = SyncError;
		goto End;
	}
	if(bk->err){
		s->err = bk->err;
		bk->err = 0;
		s->state = SyncError;
		goto End;
	}

	ret = 0;
	if(ak->nk)
		qsort(ak->k, ak->nk, sizeof(ak->k[0]), kidnamecmp);
	if(bk->nk)
		qsort(bk->k, bk->nk, sizeof(bk->k[0]), kidnamecmp);
	n = mergekids(s, ak->k, ak->nk, bk->k, bk->nk, 0);
	if(n == 0){
		s->state = SyncDone;
		syncfinish(s);
		goto End;
	}
	mergekids(s, ak->k, ak->nk, bk->k, bk->nk, n);
	s->npend = s->nkid;
	s->finishstate = SyncDone;
	for(i=0; i<n; i++){
		if(s->kid[i].a.s == nil)
			s->kid[i].a.s = mkemptystate(s->a.s->synctime);
		if(s->kid[i].b.s == nil)
			s->kid[i].b.s = mkemptystate(s->b.s->synctime);
		qsend(s->sync->syncq, &s->kid[i]);
	}

End:
	if(ak->err)
		free(ak->err);
	if(bk->err)
		free(bk->err);
	freekids(ak->k, ak->nk);
	freekids(bk->k, bk->nk);
	free(ak);
	free(bk);
	return ret;
}