Example #1
0
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;
}
Example #2
0
File: ether.c Project: npe9/harvey
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;
}
Example #3
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);
}
Example #4
0
File: usbd.c Project: elbing/harvey
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);
}
Example #5
0
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;
			}
		}
	}
}
Example #6
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);
}
Example #7
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);
}
Example #8
0
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();
}
Example #9
0
File: gs.c Project: 00001/plan9port
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;
}
Example #10
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);
}
Example #11
0
void
hoststart(void)
{
	hostc = chancreate(sizeof(int), 0);
	proccreate(hostproc, hostc, 1024);
}
Example #12
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;
}
Example #13
0
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();
}
Example #14
0
int
vtproc(void (*fn)(void*), void *arg)
{
	proccreate(fn, arg, 256*1024);
	return 0;
}
Example #15
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;
}
Example #16
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;
			}
		}
	}
}
Example #17
0
File: main.c Project: 99years/plan9
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);
}
Example #18
0
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);
}
Example #19
0
File: main.c Project: npe9/harvey
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;
			}
		}
	}
}
Example #20
0
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;
}
Example #21
0
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);
}