Ejemplo n.º 1
0
static Session *
createsession(int fd)
{
	Session *s;
	s = smbemalloc(sizeof(Session));
	s->fd = fd;
	s->state = Connected;
	qlock(&sessions);
	if (!(*tcp.accept)(s, &s->write)) {
		qunlock(&sessions);
		free(s);
		return nil;
	}
	s->thread = procrfork(tcpreader, s, 32768, RFNAMEG);
	if (s->thread < 0) {
		qunlock(&sessions);
		(*s->write)(s, nil, -1);
		free(s);
		return nil;
	}
	s->next = sessions.head;
	sessions.head = s;
	qunlock(&sessions);
	return s;
}
Ejemplo n.º 2
0
void
playinit(void)
{
	int i;

	full = chancreate(sizeof(Pacbuf*), 1);
	empty = chancreate(sizeof(Pacbuf*), NPacbuf);
	spare = chancreate(sizeof(Pacbuf*), NSparebuf);
	playout = chancreate(sizeof(Pacbuf*), NPacbuf+NSparebuf);
	for(i = 0; i < NPacbuf; i++)
		sendp(empty, malloc(sizeof(Pacbuf)));
	for(i = 0; i < NSparebuf; i++)
		sendp(spare, malloc(sizeof(Pacbuf)));

	playc = chancreate(sizeof(Pmsg), 1);
	procrfork(decproc, nil, 32*1024, RFFDG);
	procrfork(pcmproc, nil, 32*1024, RFFDG);
}
Ejemplo n.º 3
0
void
threadmain(int argc, char **argv)
{
	uintptr_t pid;
	char *cmd = nil;
	char **args = nil;

	/*
	 * don't bother with fancy arg processing, because it picks up options
	 * for the command you are starting.  Just check for -c as argv[1]
	 * and then take it from there.
	 */
	if (argc < 2)
		usage();
	while (argv[1][0] == '-') {
		switch(argv[1][1]) {
		case 'c':
			if (argc < 3)
				usage();
			cmd = strdup(argv[2]);
			args = &argv[2];
			break;
		case 'd':
			debug = 1;
			break;
		default:
			usage();
		}
		++argv;
		--argc;
	}

	/* run a command? */
	if(cmd) {
		pid = fork();
		if (pid < 0)
			sysfatal("fork failed: %r");
		if(pid == 0) {
			hang();
			exec(cmd, args);
			if(cmd[0] != '/')
				exec(smprint("/bin/%s", cmd), args);
			sysfatal("exec %s failed: %r", cmd);
		}
	} else {
		if(argc != 2)
			usage();
		pid = atoi(argv[1]);
	}

	out   = chancreate(sizeof(char*), 0);
	quit  = chancreate(sizeof(char*), 0);
	forkc = chancreate(sizeof(uint32_t *), 0);
	nread++;
	procrfork(writer, nil, Stacksize, 0);
	reader((void*)pid);
}
Ejemplo n.º 4
0
void
reader(void *v)
{
	int cfd, tfd, forking = 0, pid, newpid;
	char *ctl, *truss;
	Msg *s;

	pid = (int)(uintptr)v;
	ctl = smprint("/proc/%d/ctl", pid);
	if ((cfd = open(ctl, OWRITE)) < 0)
		die(smprint("%s: %r", ctl));
	truss = smprint("/proc/%d/syscall", pid);
	if ((tfd = open(truss, OREAD)) < 0)
		die(smprint("%s: %r", truss));

	cwrite(cfd, ctl, "stop", 4);
	cwrite(cfd, truss, "startsyscall", 12);

	s = mallocz(sizeof(Msg) + Bufsize, 1);
	s->pid = pid;
	s->buf = (char *)&s[1];
	while(pread(tfd, s->buf, Bufsize - 1, 0) > 0){
		if (forking && s->buf[1] == '=' && s->buf[3] != '-') {
			forking = 0;
			newpid = strtol(&s->buf[3], 0, 0);
			sendp(forkc, (void*)newpid);
			procrfork(reader, (void*)newpid, Stacksize, 0);
		}

		/*
		 * There are three tests here and they (I hope) guarantee
		 * no false positives.
		 */
		if (strstr(s->buf, " Rfork") != nil) {
			char *a[8];
			char *rf;

			rf = strdup(s->buf);
         		if (tokenize(rf, a, 8) == 5) {
				ulong flags;

				flags = strtoul(a[4], 0, 16);
				if (flags & RFPROC)
					forking = 1;
			}
			free(rf);
		}
		sendp(out, s);
		cwrite(cfd, truss, "startsyscall", 12);
		s = mallocz(sizeof(Msg) + Bufsize, 1);
		s->pid = pid;
		s->buf = (char *)&s[1];
	}
	sendp(quit, nil);
	threadexitsall(nil);
}
Ejemplo n.º 5
0
void
reader(void *v)
{
	char *ctl, *truss;
	int pid, newpid;
	int cfd, tfd;
	Str *s;
	int forking = 0;

	pid = (int)v;
	ctl = smprint("/proc/%d/ctl", pid);
	if ((cfd = open(ctl, OWRITE)) < 0)
		die(smprint("%s: %r", ctl));
	truss = smprint("/proc/%d/syscall", pid);
	if ((tfd = open(truss, OREAD)) < 0)
		die(smprint("%s: %r", truss));

	cwrite(cfd, ctl, "stop", 4);
	cwrite(cfd, truss, "startsyscall", 12);

	s = mallocz(sizeof(Str) + 8192, 1);
	s->buf = (char *)&s[1];
	/* 8191 is not a typo. It ensures a null-terminated string. The device currently limits to 4096 anyway */
	while((s->len = pread(tfd, s->buf, 8191, 0ULL)) > 0){
		if (forking && (s->buf[1] == '=') && (s->buf[3] != '-')) {
			forking = 0;
			newpid = strtol(&s->buf[3], 0, 0);
			sendp(forkc, (void*)newpid);
			procrfork(reader, (void*)newpid, 8192, 0);
		}

		/* There are three tests here and they (I hope) guarantee no false positives */
		if (strstr(s->buf, " Rfork") != nil) {
			char *a[8];
			char *rf;
			rf = strdup(s->buf);
         		if (tokenize(rf, a, 8) == 5) {
				unsigned long flags;
				flags = strtoul(a[4], 0, 16);
				if (flags & RFPROC)
					forking = 1;
			}
			free(rf);			
		}
		sendp(out, s);			
		cwrite(cfd, truss, "startsyscall", 12);
		s = mallocz(sizeof(Str) + 8192, 1);
		s->buf = (char *)&s[1];

	}
	sendp(quit, nil);
	threadexitsall(nil);
}
Ejemplo n.º 6
0
static NbSession *
createsession(int fd)
{
	Session *s;
	s = nbemalloc(sizeof(Session));
	s->fd = fd;
	s->state = NeedSessionRequest;
	qlock(&sessions);
	s->thread = procrfork(tcpreader, s, 32768, RFNAMEG);
	if (s->thread < 0) {
		qunlock(&sessions);
		free(s);
		return nil;
	}
	s->next = sessions.head;
	sessions.head = s;
	qunlock(&sessions);
	return s;
}
Ejemplo n.º 7
0
void
threadmain(int argc, char **argv)
{
	int pid;
	char *cmd = nil;
	char **args = nil;

	ARGBEGIN{
	case 'c':
		cmd = strdup(EARGF(usage()));
		args = argv;
		break;
	default:
		usage();
	}ARGEND;

	/* run a command? */
	if(cmd) {
		pid = fork();
		if (pid < 0) {
			fprint(2, "No fork: %r\n");
			exits("fork failed");
		}
		if(pid == 0) {
			hang(getpid());
			exec(cmd, args);
			fprint(2, "Bad exec: %s: %r\n", cmd);
			exits("Bad exec");
		}
	} else {
		if(argc != 1)
			sysfatal("usage");
		pid = atoi(argv[0]);
	}

	out = chancreate(sizeof(char*), 0);
	quit = chancreate(sizeof(char*), 0);
	forkc = chancreate(sizeof(ulong *), 0);
	nread++;
	procrfork(writer, nil, 8192, 0);
	reader((void*)pid);
}
Ejemplo n.º 8
0
static int
startplay(ushort n)
{
	int fd[2];
	Playfd *pfd;
	char *file;

	file = getplaylist(n);
	if(file == nil)
		return Undef;
	if (debug & DbgPlayer)
		fprint(2, "startplay: file is `%s'\n", file);
	if(pipe(fd) < 0)
		sysfatal("pipe: %r");
	pfd = malloc(sizeof(Playfd));
	pfd->filename = file;	/* mallocated already */
	pfd->fd = fd[1];
	pfd->cfd = fd[0];
	procrfork(decexec, pfd, 4096, RFFDG|RFENVG);
	close(fd[1]);	/* write fd, for pac4dec */
	return fd[0];	/* read fd */
}
Ejemplo n.º 9
0
int
proccreate(void (*f)(void*), void *arg, uint stacksize)
{
	return procrfork(f, arg, stacksize, 0);
}
Ejemplo n.º 10
0
void
reader(void *v)
{
	int cfd, tfd, exiting, pid;
	uintptr_t newpid;
	char *ctl, *truss;
	Str *s;
	static char waitstop[] = "waitstop";

	pid = (int)(uintptr)v;
	if (debug)
		fprint(outf, "DEBUG: -------------> reader starts with pid %d\n", pid);
	ctl = smprint("/proc/%d/ctl", pid);
	if ((cfd = open(ctl, OWRITE)) < 0)
		die(smprint("%s: %r", ctl));
	truss = smprint("/proc/%d/syscall", pid);
	if ((tfd = open(truss, OREAD)) < 0)
		die(smprint("%s: %r", truss));
	if (debug)
		fprint(outf, "DEBUG: Send %s to pid %d ...", waitstop, pid);
	/* child was stopped by hang msg earlier */
	cwrite(cfd, ctl, waitstop, sizeof waitstop - 1);
	if (debug)
		fprint(outf, "DEBUG: back for %d\n", pid);

	if (debug)
		fprint(outf, "DEBUG: Send %s to pid %d\n", "startsyscall", pid);
	cwrite(cfd, ctl, "startsyscall", 12);
	if (debug)
		fprint(outf, "DEBUG: back for %d\n", pid);
	s = newstr();
	exiting = 0;
	while((s->len = pread(tfd, s->buf, Bufsize - 1, 0)) >= 0){
		if (s->buf[0] == 'F') {
			char *val = strstr(s->buf, "= ");
			if (val) {
				newpid = strtol(&val[2], 0, 0);
				sendp(forkc, (void*)newpid);
				procrfork(reader, (void*)newpid, Stacksize, 0);
			}
		}

		if (strstr(s->buf, " Exits") != nil)
			exiting = 1;

		sendp(out, s);	/* print line from /proc/$child/syscall */
		if (exiting) {
			s = newstr();
			strcpy(s->buf, "\n");
			sendp(out, s);
			break;
		}

		/* flush syscall trace buffer */
		if (debug)
			fprint(outf, "DEBUG: Send %s to pid %d\n", "startsyscall", pid);
		cwrite(cfd, ctl, "startsyscall", 12);
		if (debug)
			fprint(outf, "DEBUG: back for %d\n", pid);
		s = newstr();
	}

	sendp(quit, nil);
	threadexitsall(nil);
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
Archivo: main.c Proyecto: 99years/plan9
void
threadmain(int argc, char *argv[])
{
	char *srvfile;
	char *srvpost;
	char *mntpt;
	int i;

	mntpt = "/mnt";
	srvpost = nil;

	rfork(RFNOTEG);

	ARGBEGIN{
	case 'a':
		aflag = 1;
		break;
	case 'm':
		mntpt = ARGF();
		break;
	case 'd':
		debug = strtoul(ARGF(), nil, 0);
		break;
	case 's':
		srvpost = ARGF();
		break;
	default:
		usage();
	}ARGEND

	user = strdup(getuser());

	quotefmtinstall();

	if(debug)
		fmtinstall('F', fcallfmt);

	volumechan = chancreate(sizeof(volume), 1);
	playchan = chancreate(sizeof(Wmsg), 1);
	playlistreq = chancreate(sizeof(Wmsg), 0);	/* No storage! requires rendez-vous */
	workers = chancreate(sizeof(Worker*), 256);
	for(i = 1; i < Nqid; i++)
		files[i].workers = chancreate(sizeof(Worker*), 256);

	if(pipe(srvfd) < 0)
		sysfatal("pipe failed: %r");
	procrfork(srv, nil, STACKSIZE, RFFDG);
	close(srvfd[0]);	/* don't deadlock if child fails */

	procrfork(volumeproc, nil, STACKSIZE, RFFDG);
	playinit();

	if(srvpost){
		srvfile = smprint("/srv/playlist.%s", srvpost);
		remove(srvfile);
		post(srvfile, srvfd[1]);
		free(srvfile);
	}
	if(mount(srvfd[1], -1, mntpt, MBEFORE, "") < 0)
		sysfatal("mount failed: %r");
	threadexits(nil);
}
Ejemplo n.º 13
0
Archivo: vacfs.c Proyecto: npe9/harvey
void
threadmain(int argc, char *argv[])
{
	char *defsrv, *srvname;
	int p[2], fd;
	int stdio;
	char *host = nil;
	long ncache;

	stdio = 0;
	ncache = 256;
	fmtinstall('H', encodefmt);
	fmtinstall('V', vtscorefmt);
	fmtinstall('F', vtfcallfmt);
	
	defmnt = nil;
	defsrv = nil;
	ARGBEGIN{
	case 'd':
		fmtinstall('F', fcallfmt);
		dflag = 1;
		break;
	case 'c':
		ncache = atoi(EARGF(usage()));
		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':
		defmnt = EARGF(usage());
		break;
	case 'p':
		noperm = 1;
		break;
	case 'V':
		chattyventi = 1;
		break;
	default:
		usage();
	}ARGEND

	if(argc != 1)
		usage();

	if(defsrv == nil && defmnt == nil && !stdio)
		defmnt = "/n/vac";
	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, ncache);
	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];
		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);
		}
	}

	procrfork(srv, 0, Stacksize, RFFDG|RFNAMEG|RFNOTEG);

	if(!stdio){
		close(p[0]);
		if(defmnt){
			if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0)
				sysfatal("mount %s: %r", defmnt);
		}
	}
	threadexits(0);
}
Ejemplo n.º 14
0
void
lockscreen(void)
{
	enum { Nfld = 5, Fldlen = 12, Cursorlen = 2*4 + 2*2*16, };
	char *s;
	char buf[Nfld*Fldlen], *flds[Nfld], newcmd[128], cbuf[Cursorlen];
	int fd, dx, dy;
	Image *i;
	Point p;
	Rectangle r;
	Tm *tm;

	fd = open("/dev/screen", OREAD);
	if(fd < 0)
		error("can't open /dev/screen: %r");
	if(read(fd, buf, Nfld*Fldlen) != Nfld*Fldlen)
		error("can't read /dev/screen: %r");
	close(fd);
	buf[sizeof buf-1] = 0;
	if(tokenize(buf, flds, Nfld) != Nfld)
		error("can't tokenize /dev/screen header");
	snprint(newcmd, sizeof newcmd, "-r %s %s %d %d",
		flds[1], flds[2], atoi(flds[3]) - 1, atoi(flds[4]) - 1);
	newwindow(newcmd);
	if (initdraw(nil, nil, "screenlock") < 0)
		sysfatal("initdraw failed");
	if(display == nil)
		error("no display");

	/* screen is now open and covered.  grab mouse and hold on tight */
	procrfork(grabmouse, nil, 4096, RFFDG);
	procrfork(blanker, nil, 4096, RFFDG);
	fd = open(pic, OREAD);
	if(fd > 0){
		i = readimage(display, fd, 0);
		if(i){
 			r = screen->r;
			p = Pt(r.max.x / 2, r.max.y * 2 / 3); 
			dx = (Dx(screen->r) - Dx(i->r)) / 2;
			r.min.x += dx;
			r.max.x -= dx;
			dy = (Dy(screen->r) - Dy(i->r)) / 2;
			r.min.y += dy;
			r.max.y -= dy;
			draw(screen, screen->r, display->black, nil, ZP);
			draw(screen, r, i, nil, i->r.min);
			flushimage(display, 1);
		}
		close(fd);

		/* identify the user on screen, centered */
		tm = localtime(time(0));
		s = smprint("user %s at %d:%02.2d", getuser(), tm->hour, tm->min);
		p = subpt(p, Pt(stringwidth(font, "m") * strlen(s) / 2, 0));
		screenstring(p, s);
	}

	/* clear the cursor */
	fd = open("/dev/cursor", OWRITE);
	if(fd > 0){
		memset(cbuf, 0, sizeof cbuf);
		write(fd, cbuf, sizeof cbuf);
		/* leave it open */
	}
}
Ejemplo n.º 15
0
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);
}
Ejemplo n.º 16
0
void
threadmain(int argc, char *argv[]) {
	char *q;
	char *srvname;
	char *mntpt;
	int list;

	mntpt = "/mnt";
	user = strdup(getuser());
	srvname = nil;
	list = 0;

	// mainmem->flags |= POOL_NOREUSE;

	ARGBEGIN{
	case 'l':
		list = 1;
		break;
	case 'm':
		mntpt = ARGF();
		break;
	case 'd':
		debug = strtoul(ARGF(), nil, 0);
		break;
	case 's':
		srvname = ARGF();
		break;
	case 'f':
		fflag = 1;
		break;
	default:
		fprint(2, usage, argv0);
		exits("usage");
	}ARGEND

	switch (argc) {
	default:
		fprint(2, usage, argv0);
		exits("usage");
	case 0:
		mapname = DEFAULTMAP;
		break;
	case 1:
		mapname = argv[0];
		break;
	}

	quotefmtinstall();

	if((f = Bopen(mapname, OREAD)) == nil)
		sysfatal("%s: %r", mapname);
	free(file);
	file = strdup(mapname);
	free(startdir);
	startdir = strdup(mapname);
	if ((q = strrchr(startdir, '/')))
		*q = '\0';
	else
		startdir[0] = '\0';
	inittokenlist();
	getobject(Root, nil);
	Bterm(f);
	f = nil;
	root->parent = root;

	if(list){
		listfiles(root);
		threadexits(nil);
	}

	if(pipe(p) < 0)
		sysfatal("pipe failed: %r");
	mfd[0] = p[0];
	mfd[1] = p[0];

	threadnotify(robusthandler, 1);
	user = strdup(getuser());

	if(debug)
		fmtinstall('F', fcallfmt);

	procrfork(io, nil, STACKSIZE, RFFDG);	//RFNOTEG?

	close(p[0]);	/* don't deadlock if child fails */

	if(srvname){
		srvname = smprint("/srv/jukefs.%s", srvname);
		remove(srvname);
		post(srvname, "jukefs", p[1]);
	}
	if(mount(p[1], -1, mntpt, MBEFORE, "") < 0)
		sysfatal("mount failed: %r");
	threadexits(nil);
}