Beispiel #1
0
void
main(int argc, char **argv)
{
	int stdio, srvfd, pipefd[2];

	rep = malloc(sizeof(Fcall));
	req = malloc(Reqsize);
	if(rep == nil || req == nil)
		panic("out of memory");
	stdio = 0;
	ARGBEGIN{
	case ':':
		trspaces = 1;
		break;
	case 'r':
		readonly = 1;
		break;
	case 'v':
		++chatty;
		break;
	case 'f':
		deffile = ARGF();
		break;
	case 's':
		stdio = 1;
		break;
	case 'p':
		doabort = 1;
		break;
	default:
		usage();
	}ARGEND

	if(argc == 0)
		strcpy(srvfile, "#s/dos");
	else if(argc == 1)
		snprint(srvfile, sizeof srvfile, "#s/%s", argv[0]);
	else
		usage();

	if(stdio){
		pipefd[0] = 0;
		pipefd[1] = 1;
	}else{
		close(0);
		close(1);
		open("/dev/null", OREAD);
		open("/dev/null", OWRITE);
		if(pipe(pipefd) < 0)
			panic("pipe");
		srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
		if(srvfd < 0)
			panic(srvfile);
		fprint(srvfd, "%d", pipefd[0]);
		close(pipefd[0]);
		atexit(rmservice);
		fprint(2, "%s: serving %s\n", argv0, srvfile);
	}
	srvfd = pipefd[1];

	switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC|RFNAMEG)){
	case -1:
		panic("fork");
	default:
		_exits(0);
	case 0:
		break;
	}

	iotrack_init();

	if(!chatty){
		close(2);
		open("#c/cons", OWRITE);
	}

	io(srvfd);
	exits(0);
}
Beispiel #2
0
static int32_t
cmdread(Chan *ch, void *a, int32_t n, int64_t offset)
{
	Proc *up = externup();
	Conv *c;
	Proc *p;
	char *s, *cmds;
	int fd;
	char buf[256];

	USED(offset);

	s = a;
	switch(TYPE(ch->qid)) {
	default:
		error(Eperm);
	case Qcmd:
	case Qtopdir:
	case Qconvdir:
		return devdirread(ch, a, n, 0, 0, cmdgen);
	case Qctl:
		sprint(up->genbuf, "%ld", CONV(ch->qid));
		return readstr(offset, s, n, up->genbuf);
	case Qalloc:
		c = cmd.conv[CONV(ch->qid)];
		p = c->p;
		snprint(buf, sizeof(buf), "%#p %#p %#p %#p %#p %#p %#p %#p",
			p->seg[TSEG]->base, p->seg[TSEG]->top,
			p->seg[DSEG]->base, p->seg[DSEG]->top,
			p->seg[BSEG]->base, p->seg[BSEG]->top,
			p->seg[SSEG]->base, p->seg[SSEG]->top);
		return readstr(offset, s, n, buf);
	case Qexec:
		c = cmd.conv[CONV(ch->qid)];
		snprint(up->genbuf, sizeof(up->genbuf), "%ld", c->esz);
		return readstr(offset, s, n, up->genbuf);
	case Qstatus:
		c = cmd.conv[CONV(ch->qid)];
		cmds = "";
		if(c->cmd != nil)
			cmds = c->cmd->f[1];
		snprint(up->genbuf, sizeof(up->genbuf), "cmd/%d %d %s %q %q\n",
			c->x, c->inuse, c->state, c->dir, cmds);
		return readstr(offset, s, n, up->genbuf);
	case Qdata:
	case Qstderr:
		fd = 1;
		if(TYPE(ch->qid) == Qstderr)
			fd = 2;
		c = cmd.conv[CONV(ch->qid)];
		qlock(&c->l);
		if(c->fd[fd] == -1){
			qunlock(&c->l);
			return 0;
		}
		qunlock(&c->l);
	//	osenter();
//		n = read(c->fd[fd], a, n);
//		osleave();
//		if(n < 0)
//			oserror();
		return n;
	case Qwait:
		c = cmd.conv[CONV(ch->qid)];
		return qread(c->waitq, a, n);
	}
}
Beispiel #3
0
static int
gzipf(char *file, int stdout)
{
	Dir *dir;
	char ofile[256], *f, *s;
	int ifd, ofd, ok;

	ifd = open(file, OREAD);
	if(ifd < 0){
		fprint(2, "gzip: can't open %s: %r\n", file);
		return 0;
	}
	dir = dirfstat(ifd);
	if(dir == nil){
		fprint(2, "gzip: can't stat %s: %r\n", file);
		close(ifd);
		return 0;
	}
	if(dir->mode & DMDIR){
		fprint(2, "gzip: can't compress a directory\n");
		close(ifd);
		free(dir);
		return 0;
	}

	if(stdout){
		ofd = 1;
		strcpy(ofile, "<stdout>");
	}else{
		f = strrchr(file, '/');
		if(f != nil)
			f++;
		else
			f = file;
		s = strrchr(f, '.');
		if(s != nil && s != ofile && strcmp(s, ".tar") == 0){
			*s = '\0';
			snprint(ofile, sizeof(ofile), "%s.tgz", f);
		}else
			snprint(ofile, sizeof(ofile), "%s.gz", f);
		ofd = create(ofile, OWRITE, 0666);
		if(ofd < 0){
			fprint(2, "gzip: can't open %s: %r\n", ofile);
			close(ifd);
			return 0;
		}
	}

	if(verbose)
		fprint(2, "compressing %s to %s\n", file, ofile);

	Binit(&bout, ofd, OWRITE);
	ok = gzip(file, dir->mtime, ifd, &bout);
	if(!ok || Bflush(&bout) < 0){
		fprint(2, "gzip: error writing %s: %r\n", ofile);
		if(!stdout)
			remove(ofile);
	}
	Bterm(&bout);
	free(dir);
	close(ifd);
	close(ofd);
	return ok;
}
Beispiel #4
0
static void
cmparena(char *name, vlong len)
{
	ArenaHead head;
	DigestState s;
	u64int n, e;
	u32int bs;
	int i, j;
	char buf[20];

	fprint(2, "cmp %s\n", name);

	memset(&s, 0, sizeof s);

	/*
	 * read a little bit, which will include the header
	 */
	if(readblock(fd, data, HeadSize) < 0){
		fprint(2, "%s: reading header: %r\n", name);
		return;
	}
	if(unpackarenahead(&head, data) < 0){
		fprint(2, "%s: corrupt arena header: %r\n", name);
		return;
	}
	if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
		fprint(2, "%s: warning: unknown arena version %d\n", name, head.version);
	if(len != 0 && len != head.size)
		fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len);
	if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
		fprint(2, "%s: warning: unexpected name %s\n", name, head.name);

	if(readblock(fd1, data1, HeadSize) < 0){
		fprint(2, "%s: reading header: %r\n", name);
		return;
	}
	if(unpackarenahead(&head, data) < 0){
		fprint(2, "%s: corrupt arena header: %r\n", name);
		return;
	}
	if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
		fprint(2, "%s: warning: unknown arena version %d\n", name, head.version);
	if(len != 0 && len != head.size)
		fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len);
	if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
		fprint(2, "%s: warning: unexpected name %s\n", name, head.name);

	seek(fd, -HeadSize, 1);
	seek(fd1, -HeadSize, 1);

	if(printheader(name, &head, fd) < 0)
		return;
	
	/*
	 * now we know how much to read
	 * read everything but the last block, which is special
	 */
	e = head.size;
	bs = blocksize;
	for(n = 0; n < e; n += bs){
		if(n + bs > e)
			bs = e - n;
		if(readblock(fd, data, bs) < 0){
			fprint(2, "%s: read data: %r\n", name);
			return;
		}
		if(readblock(fd1, data1, bs) < 0){
			fprint(2, "%s: read data: %r\n", name);
			return;
		}
		if(memcmp(data, data1, bs) != 0){
			print("mismatch at %llx\n", n);
			for(i=0; i<bs; i+=16){
				if(memcmp(data+i, data1+i, 16) != 0){
					snprint(buf, sizeof buf, "%llx", n+i);
					print("%s ", buf);
					for(j=0; j<16; j++){
						print(" %.2ux", data[i+j]);
						if(j == 7)
							print(" -");
					}
					print("\n");
					print("%*s ", (int)strlen(buf), "");
					for(j=0; j<16; j++){
						print(" %.2ux", data1[i+j]);
						if(j == 7)
							print(" -");
					}
					print("\n");
				}
			}
		}
	}
}
Beispiel #5
0
void
challengebox(Ticketreq *tr)
{
	long chal;
	char *key, *netkey;
	char kbuf[DESKEYLEN], nkbuf[DESKEYLEN], hkey[DESKEYLEN];
	char buf[NETCHLEN+1];
	char *err;

	key = findkey(KEYDB, tr->uid, kbuf);
	netkey = findkey(NETKEYDB, tr->uid, nkbuf);
	if(key == 0 && netkey == 0){
		/* make one up so caller doesn't know it was wrong */
		mkkey(nkbuf);
		netkey = nkbuf;
		if(debug)
			syslog(0, AUTHLOG, "cr-fail uid %s@%s", tr->uid, raddr);
	}
	if(findkey(KEYDB, tr->hostid, hkey) == 0){
		/* make one up so caller doesn't know it was wrong */
		mkkey(hkey);
		if(debug)
			syslog(0, AUTHLOG, "cr-fail hostid %s %s@%s", tr->hostid,
				tr->uid, raddr);
	}

	/*
	 * challenge-response
	 */
	memset(buf, 0, sizeof(buf));
	buf[0] = AuthOK;
	chal = lnrand(MAXNETCHAL);
	snprint(buf+1, sizeof buf - 1, "%lud", chal);
	if(write(1, buf, NETCHLEN+1) < 0)
		exits(0);
	if(readn(0, buf, NETCHLEN) < 0)
		exits(0);
	if(!(key && netcheck(key, chal, buf))
	&& !(netkey && netcheck(netkey, chal, buf))
	&& (err = secureidcheck(tr->uid, buf)) != nil){
		replyerror("cr-fail %s %s %s", err, tr->uid, raddr);
		logfail(tr->uid);
		if(debug)
			syslog(0, AUTHLOG, "cr-fail %s@%s(%s): bad resp",
				tr->uid, tr->hostid, raddr);
		return;
	}
	succeed(tr->uid);

	/*
	 *  reply with ticket & authenticator
	 */
	if(tickauthreply(tr, hkey) < 0){
		if(debug)
			syslog(0, AUTHLOG, "cr-fail %s@%s(%s): hangup",
				tr->uid, tr->hostid, raddr);
		exits(0);
	}

	if(debug)
		syslog(0, AUTHLOG, "cr-ok %s@%s(%s)",
			tr->uid, tr->hostid, raddr);
}
Beispiel #6
0
static int32_t
capwrite(Chan *c, void *va, int32_t n, int64_t m)
{
	Caphash *p;
	char *cp;
	uint8_t hash[Hashlen];
	char *key, *from, *to;
	char err[256];
	Proc *up = externup();

	switch((uint32_t)c->qid.path){
	case Qhash:
		if(!iseve())
			error(Eperm);
		if(n < Hashlen)
			error(Eshort);
		memmove(hash, va, Hashlen);
		addcap(hash);
		break;

	case Quse:
		/* copy key to avoid a fault in hmac_xx */
		cp = nil;
		if(waserror()){
			free(cp);
			nexterror();
		}
		cp = smalloc(n+1);
		memmove(cp, va, n);
		cp[n] = 0;

		from = cp;
		key = strrchr(cp, '@');
		if(key == nil)
			error(Eshort);
		*key++ = 0;
		hmac_sha1((uint8_t*)from, strlen(from), (uint8_t*)key, strlen(key), hash, nil);

		p = remcap(hash);
		if(p == nil){
			snprint(err, sizeof err, "invalid capability %s@%s", from, key);
			error(err);
		}

		/* if a from user is supplied, make sure it matches */
		to = strchr(from, '@');
		if(to == nil){
			to = from;
		} else {
			*to++ = 0;
			if(strcmp(from, up->user) != 0)
				error("capability must match user");
		}

		/* set user id */
		kstrdup(&up->user, to);
		up->basepri = PriNormal;

		free(p);
		free(cp);
		poperror();
		break;

	default:
		error(Eperm);
		break;
	}

	return n;
}
Beispiel #7
0
static int
progheap(Heapqry *hq, char *va, int count, ulong offset)
{
	WORD *w;
	void *p;
	List *hd;
	Array *a;
	char *fmt, *str;
	Module *m;
	Modlink *ml;
	Channel *c;
	ulong addr;
	String *ss;
	union { REAL r; LONG l; WORD w[2]; } rock;
	int i, s, n, len, signed_off;
	Type *t;

	n = 0;
	s = 0;
	signed_off = offset;
	addr = hq->addr;
	for(i = 0; i < hq->count; i++) {
		switch(hq->fmt) {
		case 'W':
			if(addr & 3)
				return -1;
			n += snprint(va+n, count-n, "%d\n", *(WORD*)addr);
			s = sizeof(WORD);
			break;
		case 'B':
			n += snprint(va+n, count-n, "%d\n", *(BYTE*)addr);
			s = sizeof(BYTE);
			break;
		case 'V':
			if(addr & 3)
				return -1;
			w = (WORD*)addr;
			rock.w[0] = w[0];
			rock.w[1] = w[1];
			n += snprint(va+n, count-n, "%lld\n", rock.l);
			s = sizeof(LONG);
			break;
		case 'R':
			if(addr & 3)
				return -1;
			w = (WORD*)addr;
			rock.w[0] = w[0];
			rock.w[1] = w[1];
			n += snprint(va+n, count-n, "%g\n", rock.r);
			s = sizeof(REAL);
			break;
		case 'I':
			if(addr & 3)
				return -1;
			for(m = modules; m != nil; m = m->link)
				if(m == (Module*)hq->module)
					break;
			if(m == nil)
				error(Ebadctl);
			addr = (ulong)(m->prog+addr);
			n += snprint(va+n, count-n, "%D\n", (Inst*)addr);
			s = sizeof(Inst);
			break;
		case 'P':
			if(addr & 3)
				return -1;
			p = *(void**)addr;
			fmt = "nil\n";
			if(p != H)
				fmt = "%lux\n";
			n += snprint(va+n, count-n, fmt, p);
			s = sizeof(WORD);
			break;
		case 'L':
			if(addr & 3)
				return -1;
			hd = *(List**)addr;
			if(hd == H || D2H(hd)->t != &Tlist)
				return -1;
			n += snprint(va+n, count-n, "%lux.%lux\n", (ulong)&hd->tail, (ulong)hd->data);
			s = sizeof(WORD);
			break;
		case 'A':
			if(addr & 3)
				return -1;
			a = *(Array**)addr;
			if(a == H)
				n += snprint(va+n, count-n, "nil\n");
			else {
				if(D2H(a)->t != &Tarray)
					return -1;
				n += snprint(va+n, count-n, "%d.%lux\n", a->len, (ulong)a->data);
			}
			s = sizeof(WORD);
			break;
		case 'C':
			if(addr & 3)
				return -1;
			ss = *(String**)addr;
			if(ss == H)
				ss = &snil;
			else
			if(D2H(ss)->t != &Tstring)
				return -1;
			n += snprint(va+n, count-n, "%d.", abs(ss->len));
			str = string2c(ss);
			len = strlen(str);
			if(count-n < len)
				len = count-n;
			if(len > 0) {
				memmove(va+n, str, len);
				n += len;
			}
			break;
		case 'M':
			if(addr & 3)
				return -1;
			ml = *(Modlink**)addr;
			fmt = ml == H ? "nil\n" : "%lux\n";
			n += snprint(va+n, count-n, fmt, ml->MP);
			s = sizeof(WORD);
			break;
		case 'c':
			if(addr & 3)
				return -1;
			c = *(Channel**)addr;
			if(c == H)
				n += snprint(va+n, count-n, "nil\n");
			else{
				t = D2H(c)->t;
				if(t != &Tchannel && t != Trdchan && t != Twrchan)
					return -1;
				if(c->buf == H)
					n += snprint(va+n, count-n, "0.%lux\n", (ulong)c);
				else
					n += snprint(va+n, count-n, "%d.%lux.%d.%d\n", c->buf->len, (ulong)c->buf->data, c->front, c->size);
			}
			break;
			
		}
		addr += s;
		if(signed_off > 0) {
			signed_off -= n;
			if(signed_off < 0) {
				memmove(va, va+n+signed_off, -signed_off);
				n = -signed_off;
			}
			else
				n = 0;
		}
	}
	return n;
}
Beispiel #8
0
/*
 *  lookup info about a client in the database.  Find an address on the
 *  same net as riip.
 */
int
lookup(Bootp *bp, Info *iip, Info *riip)
{
	Ndbtuple *t, *nt;
	Ndbs s;
	char *hwattr;
	char *hwval, hwbuf[33];
	uchar ciaddr[IPaddrlen];

	if(opendb() == nil){
		warning(1, "can't open db");
		return -1;
	}

	memset(iip, 0, sizeof(*iip));

	/* client knows its address? */
	v4tov6(ciaddr, bp->ciaddr);
	if(validip(ciaddr)){
		if(lookupip(ciaddr, iip, 0) < 0) {
			if (debug)
				warning(0, "don't know %I", ciaddr);
			return -1;	/* don't know anything about it */
		}
		if(!samenet(riip->ipaddr, iip)){
			warning(0, "%I not on %I", ciaddr, riip->ipnet);
			return -1;
		}

		/*
		 *  see if this is a masquerade, i.e., if the ether
		 *  address doesn't match what we expected it to be.
		 */
		if(memcmp(iip->etheraddr, zeroes, 6) != 0)
		if(memcmp(bp->chaddr, iip->etheraddr, 6) != 0)
			warning(0, "ciaddr %I rcvd from %E instead of %E",
				ciaddr, bp->chaddr, iip->etheraddr);

		return 0;
	}

	if(bp->hlen > Maxhwlen)
		return -1;
	switch(bp->htype){
	case 1:
		hwattr = "ether";
		hwval = hwbuf;
		snprint(hwbuf, sizeof(hwbuf), "%E", bp->chaddr);
		break;
	default:
		syslog(0, blog, "not ethernet %E, htype %d, hlen %d",
			bp->chaddr, bp->htype, bp->hlen);
		return -1;
	}

	/*
	 *  use hardware address to find an ip address on
	 *  same net as riip
	 */
	t = ndbsearch(db, &s, hwattr, hwval);
	while(t){
		for(nt = t; nt; nt = nt->entry){
			if(strcmp(nt->attr, "ip") != 0)
				continue;
			parseip(ciaddr, nt->val);
			if(lookupip(ciaddr, iip, 0) < 0)
				continue;
			if(samenet(riip->ipaddr, iip)){
				ndbfree(t);
				return 0;
			}
		}
		ndbfree(t);
		t = ndbsnext(&s, hwattr, hwval);
	}
	return -1;
}
Beispiel #9
0
/*
 *  do an ipinfo with defaults
 */
int
lookupip(uchar *ipaddr, Info *iip, int gate)
{
	char ip[32];
	Ndbtuple *t, *nt;
	char *attrs[32], **p;

	if(opendb() == nil){
		warning(1, "can't open db");
		return -1;
	}

	p = attrs;
	*p++ = "ip";
	*p++ = "ipmask";
	*p++ = "@ipgw";
	if(!gate){
		*p++ = "bootf";
		*p++ = "bootf2";
		*p++ = "@tftp";
		*p++ = "@tftp2";
		*p++ = "rootpath";
		*p++ = "dhcp";
		*p++ = "vendorclass";
		*p++ = "ether";
		*p++ = "dom";
		*p++ = "@fs";
		*p++ = "@auth";
	}
	*p = 0;

	memset(iip, 0, sizeof(*iip));
	snprint(ip, sizeof(ip), "%I", ipaddr);
	t = ndbipinfo(db, "ip", ip, attrs, p - attrs);
	if(t == nil)
		return -1;
	
	for(nt = t; nt != nil; nt = nt->entry){
		if(strcmp(nt->attr, "ip") == 0)
			setipaddr(iip->ipaddr, nt->val);
		else
		if(strcmp(nt->attr, "ipmask") == 0)
			setipmask(iip->ipmask, nt->val);
		else
		if(strcmp(nt->attr, "fs") == 0)
			setipaddr(iip->fsip, nt->val);
		else
		if(strcmp(nt->attr, "auth") == 0)
			setipaddr(iip->auip, nt->val);
		else
		if(strcmp(nt->attr, "tftp") == 0)
			setipaddr(iip->tftp, nt->val);
		else
		if(strcmp(nt->attr, "tftp2") == 0)
			setipaddr(iip->tftp2, nt->val);
		else
		if(strcmp(nt->attr, "ipgw") == 0)
			setipaddr(iip->gwip, nt->val);
		else
		if(strcmp(nt->attr, "ether") == 0){
			/*
			 * this is probably wrong for machines with multiple
			 * ethers.  bootp or dhcp requests could come from any
			 * of the ethers listed in the ndb entry.
			 */
			if(memcmp(iip->etheraddr, noetheraddr, 6) == 0)
				parseether(iip->etheraddr, nt->val);
			iip->indb = 1;
		}
		else
		if(strcmp(nt->attr, "dhcp") == 0){
			if(iip->dhcpgroup[0] == 0)
				strcpy(iip->dhcpgroup, nt->val);
		}
		else
		if(strcmp(nt->attr, "bootf") == 0){
			if(iip->bootf[0] == 0)
				strcpy(iip->bootf, nt->val);
		}
		else
		if(strcmp(nt->attr, "bootf2") == 0){
			if(iip->bootf2[0] == 0)
				strcpy(iip->bootf2, nt->val);
		}
		else
		if(strcmp(nt->attr, "vendor") == 0){
			if(iip->vendor[0] == 0)
				strcpy(iip->vendor, nt->val);
		}
		else
		if(strcmp(nt->attr, "dom") == 0){
			if(iip->domain[0] == 0)
				strcpy(iip->domain, nt->val);
		}
		else
		if(strcmp(nt->attr, "rootpath") == 0){
			if(iip->rootpath[0] == 0)
				strcpy(iip->rootpath, nt->val);
		}
	}
	ndbfree(t);
	maskip(iip->ipaddr, iip->ipmask, iip->ipnet);
	return 0;
}
Beispiel #10
0
/*
 *  attach a device (or pkt driver) to the interface.
 *  called with c locked
 */
static char*
ipifcbind(Conv *c, char **argv, int argc)
{
	Mach *m = machp();
	Ipifc *ifc;
	Medium *medium;

	if(argc < 2)
		return Ebadarg;

	ifc = (Ipifc*)c->ptcl;

	/* bind the device to the interface */
	medium = ipfindmedium(argv[1]);
	if(medium == nil)
		return "unknown interface type";

	wlock(ifc);
	if(ifc->medium != nil){
		wunlock(ifc);
		return "interface already bound";
	}
	if(waserror()){
		wunlock(ifc);
		nexterror();
	}

	/* do medium specific binding */
	(*medium->bind)(ifc, argc, argv);

	/* set the bound device name */
	if(argc > 2)
		strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
	else
		snprint(ifc->dev, sizeof ifc->dev, "%s%d", medium->name, c->x);
	ifc->dev[sizeof(ifc->dev)-1] = 0;

	/* set up parameters */
	ifc->medium = medium;
	ifc->mintu = ifc->medium->mintu;
	ifc->maxtu = ifc->medium->maxtu;
	if(ifc->medium->unbindonclose == 0)
		ifc->conv->inuse++;
	ifc->rp.mflag = 0;		/* default not managed */
	ifc->rp.oflag = 0;
	ifc->rp.maxraint = 600000;	/* millisecs */
	ifc->rp.minraint = 200000;
	ifc->rp.linkmtu = 0;		/* no mtu sent */
	ifc->rp.reachtime = 0;
	ifc->rp.rxmitra = 0;
	ifc->rp.ttl = MAXTTL;
	ifc->rp.routerlt = 3 * ifc->rp.maxraint;

	/* any ancillary structures (like routes) no int32_ter pertain */
	ifc->ifcid++;

	/* reopen all the queues closed by a previous unbind */
	qreopen(c->rq);
	qreopen(c->eq);
	qreopen(c->sq);

	wunlock(ifc);
	poperror();

	return nil;
}
Beispiel #11
0
char*
ipifcadd6(Ipifc *ifc, char**argv, int argc)
{
	int plen = 64;
	int32_t origint = NOW / 1000, preflt = ~0L, validlt = ~0L;
	char addr[Maxv6repr], preflen[6];
	char *params[3];
	uint8_t autoflag = 1, onlink = 1;
	uint8_t prefix[IPaddrlen];
	Iplifc *lifc;

	switch(argc) {
	case 7:
		preflt = atoi(argv[6]);
		/* fall through */
	case 6:
		validlt = atoi(argv[5]);
		/* fall through */
	case 5:
		autoflag = atoi(argv[4]);
		/* fall through */
	case 4:
		onlink = atoi(argv[3]);
		/* fall through */
	case 3:
		plen = atoi(argv[2]);
		/* fall through */
	case 2:
		break;
	default:
		return Ebadarg;
	}

	if (parseip(prefix, argv[1]) != 6)
		return "bad ipv6 address";
	if (validlt < preflt)
		return "valid ipv6 lifetime less than preferred lifetime";
	if (plen < 0)
		return "negative ipv6 prefix length";
	/* i think that this length limit is bogus - geoff */
//	if (plen > 64)
//		return "ipv6 prefix length greater than 64;
	if (islinklocal(prefix))
		return "ipv6 prefix is link-local";

	lifc = smalloc(sizeof(Iplifc));
	lifc->onlink = (onlink != 0);
	lifc->autoflag = (autoflag != 0);
	lifc->validlt = validlt;
	lifc->preflt = preflt;
	lifc->origint = origint;

	/* issue "add" ctl msg for v6 link-local addr and prefix len */
	if(!ifc->medium->pref2addr)
		return "no pref2addr on interface";
	ifc->medium->pref2addr(prefix, ifc->mac);	/* mac → v6 link-local addr */
	snprint(addr, sizeof addr, "%I", prefix);
	snprint(preflen, sizeof preflen, "/%d", plen);
	params[0] = "add";
	params[1] = addr;
	params[2] = preflen;

	return ipifcadd(ifc, params, 3, 0, lifc);
}
Beispiel #12
0
int
main(int argc, char **argv)
{
	int isnew;
	char *id, buf[Maxmsg], home[Maxmsg], prompt[100], *hexHi;
	char *pass, *passck;
	long expsecs;
	mpint *H = mpnew(0), *Hi = mpnew(0);
	PW *pw;
	Tm *tm;

	SECSTORE_DIR = unsharp("#9/secstore");

	ARGBEGIN{
	case 'v':
		verbose++;
		break;
	}ARGEND;
	if(argc!=1){
		print("usage: secuser [-v] <user>\n");
		exits("usage");
	}

	ensure_exists(SECSTORE_DIR, DMDIR|0755L);
	snprint(home, sizeof(home), "%s/who", SECSTORE_DIR);
	ensure_exists(home, DMDIR|0755L);
	snprint(home, sizeof(home), "%s/store", SECSTORE_DIR);
	ensure_exists(home, DMDIR|0700L);

	id = argv[0];
	if(verbose)
		fprint(2,"secuser %s\n", id);
	if((pw = getPW(id,1)) == nil){
		isnew = 1;
		print("new account (because %s/%s %r)\n", SECSTORE_DIR, id);
		pw = emalloc(sizeof(*pw));
		pw->id = estrdup(id);
		snprint(home, sizeof(home), "%s/store/%s", SECSTORE_DIR, id);
		if(access(home, AEXIST) == 0){
			print("new user, but directory %s already exists\n", home);
			exits(home);
		}
	}else{
		isnew = 0;
	}

	/* get main password for id */
	for(;;){
		if(isnew)
			snprint(prompt, sizeof(prompt), "%s password", id);
		else
			snprint(prompt, sizeof(prompt), "%s password [default = don't change]", id);
		pass = readcons(prompt, nil, 1);
		if(pass == nil){
			print("getpass failed\n");
			exits("getpass failed");
		}
		if(verbose)
			print("%ld characters\n", strlen(pass));
		if(pass[0] == '\0' && isnew == 0)
			break;
		if(strlen(pass) >= 7)
			break;
		print("password must be at least 7 characters\n");
	}

	if(pass[0] != '\0'){
		snprint(prompt, sizeof(prompt), "retype password");
		if(verbose)
			print("confirming...\n");
		passck = readcons(prompt, nil, 1);
		if(passck == nil){
			print("getpass failed\n");
			exits("getpass failed");
		}
		if(strcmp(pass, passck) != 0){
			print("passwords didn't match\n");
			exits("no match");
		}
		memset(passck, 0, strlen(passck));
		free(passck);
		hexHi = PAK_Hi(id, pass, H, Hi);
		memset(pass, 0, strlen(pass));
		free(pass);
		free(hexHi);
		mpfree(H);
		pw->Hi = Hi;
	}

	/* get expiration time (midnight of date specified) */
	if(isnew)
		expsecs = time(0) + 365*24*60*60;
	else
		expsecs = pw->expire;

	for(;;){
		tm = localtime(expsecs);
		print("expires [DDMMYYYY, default = %2.2d%2.2d%4.4d]: ",
				tm->mday, tm->mon, tm->year+1900);
		userinput(buf, sizeof(buf));
		if(strlen(buf) == 0)
			break;
		if(strlen(buf) != 8){
			print("!bad date format: %s\n", buf);
			continue;
		}
		tm->mday = (buf[0]-'0')*10 + (buf[1]-'0');
		if(tm->mday > 31 || tm->mday < 1){
			print("!bad day of month: %d\n", tm->mday);
			continue;
		}
		tm->mon = (buf[2]-'0')*10 + (buf[3]-'0') - 1;
		if(tm->mon > 11 || tm->mday < 0){
			print("!bad month: %d\n", tm->mon + 1);
			continue;
		}
		tm->year = atoi(buf+4) - 1900;
		if(tm->year < 70){
			print("!bad year: %d\n", tm->year + 1900);
			continue;
		}
		tm->sec = 59;
		tm->min = 59;
		tm->hour = 23;
		tm->yday = 0;
		expsecs = tm2sec(tm);
		break;
	}
	pw->expire = expsecs;

	/* failed logins */
	if(pw->failed != 0 )
		print("clearing %d failed login attempts\n", pw->failed);
	pw->failed = 0;

	/* status bits */
	if(isnew)
		pw->status = Enabled;
	for(;;){
		print("Enabled or Disabled [default %s]: ",
			(pw->status & Enabled) ? "Enabled" : "Disabled" );
		userinput(buf, sizeof(buf));
		if(strlen(buf) == 0)
			break;
		if(buf[0]=='E' || buf[0]=='e'){
			pw->status |= Enabled;
			break;
		}
		if(buf[0]=='D' || buf[0]=='d'){
			pw->status = pw->status & ~Enabled;
			break;
		}
	}
	for(;;){
		print("require STA? [default %s]: ",
			(pw->status & STA) ? "yes" : "no" );
		userinput(buf, sizeof(buf));
		if(strlen(buf) == 0)
			break;
		if(buf[0]=='Y' || buf[0]=='y'){
			pw->status |= STA;
			break;
		}
		if(buf[0]=='N' || buf[0]=='n'){
			pw->status = pw->status & ~STA;
			break;
		}
	}

	/* free form field */
	if(isnew)
		pw->other = nil;
	print("comments [default = %s]: ", (pw->other == nil) ? "" : pw->other);
	userinput(buf, 72);  /* 72 comes from password.h */
	if(buf[0])
		if((pw->other = strdup(buf)) == nil)
			sysfatal("strdup");

	syslog(0, LOG, "CHANGELOGIN for '%s'", pw->id);
	if(putPW(pw) < 0){
		print("error writing entry: %r\n");
		exits("can't write password file");
	}else{
		print("change written\n");
		if(isnew && create(home, OREAD, DMDIR | 0775L) < 0){
			print("unable to create %s: %r\n", home);
			exits(home);
		}
	}

	exits("");
	return 1;  /* keep  other compilers happy */
}
Beispiel #13
0
void
vnc(Ticketreq *tr)
{
	uchar chal[VNCchallen+6];
	uchar reply[VNCchallen];
	char *secret, *hkey;
	char sbuf[SECRETLEN], hbuf[DESKEYLEN];
	DESstate s;
	int i;

	/*
	 *  Create a challenge and send it.
	 */
	randombytes(chal+6, VNCchallen);
	chal[0] = AuthOKvar;
	snprint((char*)chal+1, sizeof chal - 1, "%-5d", VNCchallen);
	if(write(1, chal, sizeof(chal)) != sizeof(chal))
		return;

	/*
	 *  lookup keys (and swizzle bits)
	 */
	memset(sbuf, 0, sizeof(sbuf));
	secret = findsecret(KEYDB, tr->uid, sbuf);
	if(secret == 0){
		randombytes((uchar*)sbuf, sizeof(sbuf));
		secret = sbuf;
	}
	for(i = 0; i < 8; i++)
		secret[i] = swizzletab[(uchar)secret[i]];

	hkey = findkey(KEYDB, tr->hostid, hbuf);
	if(hkey == 0){
		randombytes((uchar*)hbuf, sizeof(hbuf));
		hkey = hbuf;
	}

	/*
	 *  get response
	 */
	if(readn(0, reply, sizeof(reply)) != sizeof(reply))
		return;

	/*
	 *  decrypt response and compare
	 */
	setupDESstate(&s, (uchar*)secret, nil);
	desECBdecrypt(reply, sizeof(reply), &s);
	if(memcmp(reply, chal+6, VNCchallen) != 0){
		replyerror("vnc-fail bad response %s", raddr);
		logfail(tr->uid);
		return;
	}
	succeed(tr->uid);

	/*
	 *  reply with ticket & authenticator
	 */
	if(tickauthreply(tr, hkey) < 0)
		exits(0);

	if(debug)
		syslog(0, AUTHLOG, "vnc-ok %s %s", tr->uid, raddr);
}
Beispiel #14
0
void
apop(Ticketreq *tr, int type)
{
	int challen, i, tries;
	char *secret, *hkey, *p;
	Ticketreq treq;
	DigestState *s;
	char sbuf[SECRETLEN], hbuf[DESKEYLEN];
	char tbuf[TICKREQLEN];
	char buf[MD5dlen*2];
	uchar digest[MD5dlen], resp[MD5dlen];
	ulong rb[4];
	char chal[256];

	USED(tr);

	/*
	 *  Create a challenge and send it.
	 */
	randombytes((uchar*)rb, sizeof(rb));
	p = chal;
	p += snprint(p, sizeof(chal), "<%lux%lux.%lux%lux@%s>",
		rb[0], rb[1], rb[2], rb[3], domainname());
	challen = p - chal;
	print("%c%-5d%s", AuthOKvar, challen, chal);

	/* give user a few attempts */
	for(tries = 0; ; tries++) {
		/*
		 *  get ticket request
		 */
		if(readn(0, tbuf, TICKREQLEN) < 0)
			exits(0);
		convM2TR(tbuf, &treq);
		tr = &treq;
		if(tr->type != type)
			exits(0);

		/*
		 * read response
		 */
		if(readn(0, buf, MD5dlen*2) < 0)
			exits(0);
		for(i = 0; i < MD5dlen; i++)
			resp[i] = (h2b(buf[2*i])<<4)|h2b(buf[2*i+1]);

		/*
		 * lookup
		 */
		secret = findsecret(KEYDB, tr->uid, sbuf);
		hkey = findkey(KEYDB, tr->hostid, hbuf);
		if(hkey == 0 || secret == 0){
			replyerror("apop-fail bad response %s", raddr);
			logfail(tr->uid);
			if(tries > 5)
				return;
			continue;
		}

		/*
		 *  check for match
		 */
		if(type == AuthCram){
			hmac_md5((uchar*)chal, challen,
				(uchar*)secret, strlen(secret),
				digest, nil);
		} else {
			s = md5((uchar*)chal, challen, 0, 0);
			md5((uchar*)secret, strlen(secret), digest, s);
		}
		if(memcmp(digest, resp, MD5dlen) != 0){
			replyerror("apop-fail bad response %s", raddr);
			logfail(tr->uid);
			if(tries > 5)
				return;
			continue;
		}
		break;
	}

	succeed(tr->uid);

	/*
	 *  reply with ticket & authenticator
	 */
	if(tickauthreply(tr, hkey) < 0)
		exits(0);

	if(debug){
		if(type == AuthCram)
			syslog(0, AUTHLOG, "cram-ok %s %s", tr->uid, raddr);
		else
			syslog(0, AUTHLOG, "apop-ok %s %s", tr->uid, raddr);
	}
}
Beispiel #15
0
//
//  read in the mailbox and parse into messages.
//
static char*
_readmbox(Mailbox *mb, int doplumb, Mlock *lk)
{
	int fd, n;
	String *tmp;
	Dir *d;
	static char err[Errlen];
	Message *m, **l;
	Inbuf *inb;
	char *x;

	l = &mb->root->part;

	/*
	 *  open the mailbox.  If it doesn't exist, try the temporary one.
	 */
	n = 0;
retry:
	fd = open(mb->path, OREAD);
	if(fd < 0){
		rerrstr(err, sizeof(err));
		if(strstr(err, "exclusive lock") != 0 && n++ < 20){
			sleep(500);	/* wait for lock to go away */
			goto retry;
		}
		if(strstr(err, "exist") != 0){
			tmp = s_copy(mb->path);
			s_append(tmp, ".tmp");
			if(sysrename(s_to_c(tmp), mb->path) == 0){
				s_free(tmp);
				goto retry;
			}
			s_free(tmp);
		}
		return err;
	}

	/*
	 *  a new qid.path means reread the mailbox, while
	 *  a new qid.vers means read any new messages
	 */
	d = dirfstat(fd);
	if(d == nil){
		close(fd);
		errstr(err, sizeof(err));
		return err;
	}
	if(mb->d != nil){
		if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){
			close(fd);
			free(d);
			return nil;
		}
		if(d->qid.path == mb->d->qid.path){
			while(*l != nil)
				l = &(*l)->next;
			seek(fd, mb->d->length, 0);
		}
		free(mb->d);
	}
	mb->d = d;
	mb->vers++;
	henter(PATH(0, Qtop), mb->name,
		(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);

	inb = emalloc(sizeof(Inbuf));
	inb->rptr = inb->wptr = inb->data;
	inb->fd = fd;

	//  read new messages
	snprint(err, sizeof err, "reading '%s'", mb->path);
	logmsg(err, nil);
	for(;;){
		if(lk != nil)
			syslockrefresh(lk);
		m = newmessage(mb->root);
		m->mallocd = 1;
		m->inmbox = 1;
		if(readmessage(m, inb) < 0){
			delmessage(mb, m);
			mb->root->subname--;
			break;
		}

		// merge mailbox versions
		while(*l != nil){
			if(memcmp((*l)->digest, m->digest, SHA1dlen) == 0){
				// matches mail we already read, discard
				logmsg("duplicate", *l);
				delmessage(mb, m);
				mb->root->subname--;
				m = nil;
				l = &(*l)->next;
				break;
			} else {
				// old mail no longer in box, mark deleted
				logmsg("disappeared", *l);
				if(doplumb)
					mailplumb(mb, *l, 1);
				(*l)->inmbox = 0;
				(*l)->deleted = 1;
				l = &(*l)->next;
			}
		}
		if(m == nil)
			continue;

		x = strchr(m->start, '\n');
		if(x == nil)
			m->header = m->end;
		else
			m->header = x + 1;
		m->mheader = m->mhend = m->header;
		parseunix(m);
		parse(m, 0, mb, 0);
		logmsg("new", m);

		/* chain in */
		*l = m;
		l = &m->next;
		if(doplumb)
			mailplumb(mb, m, 0);

	}
	logmsg("mbox read", nil);

	// whatever is left has been removed from the mbox, mark deleted
	while(*l != nil){
		if(doplumb)
			mailplumb(mb, *l, 1);
		(*l)->inmbox = 0;
		(*l)->deleted = 1;
		l = &(*l)->next;
	}

	close(fd);
	free(inb);
	return nil;
}
Beispiel #16
0
void
main(int argc, char **argv)
{
	int conn, ctlfd, fd, n;
	char buf[128], *base, *mtpt, *post, *url;

	mtpt = "/mnt/web";
	post = nil;
	base = nil;
	ARGBEGIN{
	default:
		usage();
	case 'b':
		base = EARGF(usage());
		break;
	case 'm':
		mtpt = EARGF(usage());
		break;
	case 'p':
		post = EARGF(usage());
		break;
	}ARGEND;

	if (argc != 1) 
		usage();

	url = argv[0];
 
	snprint(buf, sizeof buf, "%s/clone", mtpt);
	if((ctlfd = open(buf, ORDWR)) < 0)
		sysfatal("couldn't open %s: %r", buf);
	if((n = read(ctlfd, buf, sizeof buf-1)) < 0)
		sysfatal("reading clone: %r");
	if(n == 0)
		sysfatal("short read on clone");
	buf[n] = '\0';
	conn = atoi(buf);

	if(base)
		if(fprint(ctlfd, "baseurl %s", base) < 0)
			sysfatal("baseurl ctl write: %r");

	if(fprint(ctlfd, "url %s", url) <= 0)
		sysfatal("get ctl write: %r");

	if(post){
		snprint(buf, sizeof buf, "%s/%d/postbody", mtpt, conn);
		if((fd = open(buf, OWRITE)) < 0)
			sysfatal("open %s: %r", buf);
		if(write(fd, post, strlen(post)) < 0)
			sysfatal("post write failed: %r");
		close(fd);
	}

	snprint(buf, sizeof buf, "%s/%d/body", mtpt, conn);
	if((fd = open(buf, OREAD)) < 0)
		sysfatal("open %s: %r", buf);

	xfer(fd, 1);
	exits(nil);
}
Beispiel #17
0
void
main(int argc, char *argv[])
{
	int i, c;
	char *a;
	char name[LIBNAMELEN];

	Binit(&bso, 1, OWRITE);
	cout = -1;
	listinit();
	memset(debug, 0, sizeof(debug));
	nerrors = 0;
	outfile = "6.out";
	HEADTYPE = -1;
	INITTEXT = -1;
	INITTEXTP = -1;
	INITDAT = -1;
	INITRND = -1;
	INITENTRY = 0;
	ARGBEGIN {
	default:
		c = ARGC();
		if(c >= 0 && c < sizeof(debug))
			debug[c]++;
		break;
	case 'o': /* output to (next arg) */
		outfile = ARGF();
		break;
	case 'E':
		a = ARGF();
		if(a)
			INITENTRY = a;
		break;
	case 'H':
		a = ARGF();
		if(a)
			HEADTYPE = atolwhex(a);
		break;
	case 'L':
		addlibpath(EARGF(usage()));
		break;
	case 'T':
		a = ARGF();
		if(a)
			INITTEXT = atolwhex(a);
		break;
	case 'P':
		a = ARGF();
		if(a)
			INITTEXTP = atolwhex(a);
		break;
	case 'D':
		a = ARGF();
		if(a)
			INITDAT = atolwhex(a);
		break;
	case 'R':
		a = ARGF();
		if(a)
			INITRND = atolwhex(a);
		break;
	case 'x':	/* produce export table */
		doexp = 1;
		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
			readundefs(ARGF(), SEXPORT);
		break;
	case 'u':	/* produce dynamically loadable module */
		dlm = 1;
		debug['l']++;
		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
			readundefs(ARGF(), SIMPORT);
		break;
	} ARGEND
	USED(argc);
	if(*argv == 0)
		usage();
	if(!debug['9'] && !debug['U'] && !debug['B'])
		debug[DEFAULT] = 1;
	a = getenv("ccroot");
	if(a != nil && *a != '\0') {
		if(!fileexists(a)) {
			diag("nonexistent $ccroot: %s", a);
			errorexit();
		}
	}else
		a = "";
	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
	addlibpath(name);
	if(HEADTYPE == -1) {
		if(debug['B'])
			HEADTYPE = 2;
		if(debug['9'])
			HEADTYPE = 2;
	}
	switch(HEADTYPE) {
	default:
		diag("unknown -H option");
		errorexit();
	case 2:	/* plan 9 */
		HEADR = 32L+8L;
		if(INITTEXT == -1)
			INITTEXT = 0x200000+HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 0x200000;
		break;
	case 5:	/* elf32 executable */
		HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);
		if(INITTEXT == -1)
			INITTEXT = 0xf0110000L;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4096;
		break;
	case 6:	/* ELF64 executable */
		HEADR = rnd(Ehdr64sz+3*Phdr64sz, 16);
		if(INITTEXT == -1)
			INITTEXT = 0x200000+HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 0x200000;
		break;
	}
	if (INITTEXTP == -1)
		INITTEXTP = INITTEXT;
	if(INITDAT != 0 && INITRND != 0)
		print("warning: -D0x%llux is ignored because of -R0x%lux\n",
			INITDAT, INITRND);
	if(debug['v'])
		Bprint(&bso, "HEADER = -H%ld -T0x%llux -D0x%llux -R0x%lux\n",
			HEADTYPE, INITTEXT, INITDAT, INITRND);
	Bflush(&bso);
	for(i=1; optab[i].as; i++) {
		c = optab[i].as;
		if(opindex[c] != nil) {
			diag("phase error in optab: %d (%A)", i, c);
			errorexit();
		}
		opindex[c] = &optab[i];
	}

	for(i=0; i<Ymax; i++)
		ycover[i*Ymax + i] = 1;

	ycover[Yi0*Ymax + Yi8] = 1;
	ycover[Yi1*Ymax + Yi8] = 1;

	ycover[Yi0*Ymax + Ys32] = 1;
	ycover[Yi1*Ymax + Ys32] = 1;
	ycover[Yi8*Ymax + Ys32] = 1;

	ycover[Yi0*Ymax + Yi32] = 1;
	ycover[Yi1*Ymax + Yi32] = 1;
	ycover[Yi8*Ymax + Yi32] = 1;
	ycover[Ys32*Ymax + Yi32] = 1;

	ycover[Yi0*Ymax + Yi64] = 1;
	ycover[Yi1*Ymax + Yi64] = 1;
	ycover[Yi8*Ymax + Yi64] = 1;
	ycover[Ys32*Ymax + Yi64] = 1;
	ycover[Yi32*Ymax + Yi64] = 1;

	ycover[Yal*Ymax + Yrb] = 1;
	ycover[Ycl*Ymax + Yrb] = 1;
	ycover[Yax*Ymax + Yrb] = 1;
	ycover[Ycx*Ymax + Yrb] = 1;
	ycover[Yrx*Ymax + Yrb] = 1;
	ycover[Yrl*Ymax + Yrb] = 1;

	ycover[Ycl*Ymax + Ycx] = 1;

	ycover[Yax*Ymax + Yrx] = 1;
	ycover[Ycx*Ymax + Yrx] = 1;

	ycover[Yax*Ymax + Yrl] = 1;
	ycover[Ycx*Ymax + Yrl] = 1;
	ycover[Yrx*Ymax + Yrl] = 1;

	ycover[Yf0*Ymax + Yrf] = 1;

	ycover[Yal*Ymax + Ymb] = 1;
	ycover[Ycl*Ymax + Ymb] = 1;
	ycover[Yax*Ymax + Ymb] = 1;
	ycover[Ycx*Ymax + Ymb] = 1;
	ycover[Yrx*Ymax + Ymb] = 1;
	ycover[Yrb*Ymax + Ymb] = 1;
	ycover[Yrl*Ymax + Ymb] = 1;
	ycover[Ym*Ymax + Ymb] = 1;

	ycover[Yax*Ymax + Yml] = 1;
	ycover[Ycx*Ymax + Yml] = 1;
	ycover[Yrx*Ymax + Yml] = 1;
	ycover[Yrl*Ymax + Yml] = 1;
	ycover[Ym*Ymax + Yml] = 1;

	ycover[Yax*Ymax + Ymm] = 1;
	ycover[Ycx*Ymax + Ymm] = 1;
	ycover[Yrx*Ymax + Ymm] = 1;
	ycover[Yrl*Ymax + Ymm] = 1;
	ycover[Ym*Ymax + Ymm] = 1;
	ycover[Ymr*Ymax + Ymm] = 1;

	ycover[Yax*Ymax + Yxm] = 1;
	ycover[Ycx*Ymax + Yxm] = 1;
	ycover[Yrx*Ymax + Yxm] = 1;
	ycover[Yrl*Ymax + Yxm] = 1;
	ycover[Ym*Ymax + Yxm] = 1;
	ycover[Yxr*Ymax + Yxm] = 1;

	for(i=0; i<D_NONE; i++) {
		reg[i] = -1;
		if(i >= D_AL && i <= D_R15B) {
			reg[i] = (i-D_AL) & 7;
			if(i >= D_SPB && i <= D_DIB)
				regrex[i] = 0x40;
			if(i >= D_R8B && i <= D_R15B)
				regrex[i] = Rxr | Rxx | Rxb;
		}
		if(i >= D_AH && i<= D_BH)
			reg[i] = 4 + ((i-D_AH) & 7);
		if(i >= D_AX && i <= D_R15) {
			reg[i] = (i-D_AX) & 7;
			if(i >= D_R8)
				regrex[i] = Rxr | Rxx | Rxb;
		}
		if(i >= D_F0 && i <= D_F0+7)
			reg[i] = (i-D_F0) & 7;
		if(i >= D_M0 && i <= D_M0+7)
			reg[i] = (i-D_M0) & 7;
		if(i >= D_X0 && i <= D_X0+15) {
			reg[i] = (i-D_X0) & 7;
			if(i >= D_X0+8)
				regrex[i] = Rxr | Rxx | Rxb;
		}
		if(i >= D_CR+8 && i <= D_CR+15) 
			regrex[i] = Rxr;
	}

	zprg.link = P;
	zprg.pcond = P;
	zprg.back = 2;
	zprg.as = AGOK;
	zprg.from.type = D_NONE;
	zprg.from.index = D_NONE;
	zprg.from.scale = 1;
	zprg.to = zprg.from;
	zprg.mode = 64;

	pcstr = "%.6llux ";
	nuxiinit();
	histgen = 0;
	textp = P;
	datap = P;
	edatap = P;
	pc = 0;
	dtype = 4;
	cout = create(outfile, 1, 0775);
	if(cout < 0) {
		diag("cannot create %s: %r", outfile);
		errorexit();
	}
	version = 0;
	cbp = buf.cbuf;
	cbc = sizeof(buf.cbuf);
	firstp = prg();
	lastp = firstp;

	if(INITENTRY == 0) {
		INITENTRY = "_main";
		if(debug['p'])
			INITENTRY = "_mainp";
		if(!debug['l'])
			lookup(INITENTRY, 0)->type = SXREF;
	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
		lookup(INITENTRY, 0)->type = SXREF;

	while(*argv)
		objfile(*argv++);
	if(!debug['l'])
		loadlib();
	firstp = firstp->link;
	if(firstp == P)
		errorexit();
	if(doexp || dlm){
		EXPTAB = "_exporttab";
		zerosig(EXPTAB);
		zerosig("etext");
		zerosig("edata");
		zerosig("end");
		if(dlm){
			import();
			HEADTYPE = 2;
			INITTEXT = 0;
			INITDAT = 0;
			INITRND = 8;
			INITENTRY = EXPTAB;
		}
		export();
Beispiel #18
0
static long
consread(Chan *c, void *va, long n, vlong offset)
{
	int send;
	char *p, buf[64], ch;
	FILE * battery;
	FILE * brightness;
	int size;

	if(c->qid.type & QTDIR)
		return devdirread(c, va, n, contab, nelem(contab), devgen);

	switch((ulong)c->qid.path) {
	default:
		error(Egreg);

	case Qsysctl:
		return readstr(offset, va, n, VERSION);

	case Qsysname:
		if(ossysname == nil)
			return 0;
		return readstr(offset, va, n, ossysname);

	case Qrandom:
		return randomread(va, n);

	case Qnotquiterandom:
		genrandom(va, n);
		return n;

	case Qhostowner:
		return readstr(offset, va, n, eve);

	case Qhoststdin:
		return read(0, va, n);	/* should be pread */

	case Quser:
		return readstr(offset, va, n, up->env->user);

	case Qjit:
		snprint(buf, sizeof(buf), "%d", cflag);
		return readstr(offset, va, n, buf);

	case Qtime:
		snprint(buf, sizeof(buf), "%.lld", timeoffset + osusectime());
		return readstr(offset, va, n, buf);

	case Qdrivers:
		return devtabread(c, va, n, offset);

	case Qmemory:
		return poolread(va, n, offset);

	case Qnull:
		return 0;

	case Qmsec:
		return readnum(offset, va, n, osmillisec(), NUMSIZE);

	case Qcons:
		qlock(&kbd.q);
		if(waserror()){
			qunlock(&kbd.q);
			nexterror();
		}

		if(dflag)
			error(Enonexist);

		while(!qcanread(lineq)) {
			if(qread(kbdq, &ch, 1) == 0)
				continue;
			send = 0;
			if(ch == 0){
				/* flush output on rawoff -> rawon */
				if(kbd.x > 0)
					send = !qcanread(kbdq);
			}else if(kbd.raw){
				kbd.line[kbd.x++] = ch;
				send = !qcanread(kbdq);
			}else{
				switch(ch){
				case '\b':
					if(kbd.x)
						kbd.x--;
					break;
				case 0x15:
					kbd.x = 0;
					break;
				case 0x04:
					send = 1;
					break;
				case '\n':
					send = 1;
				default:
					kbd.line[kbd.x++] = ch;
					break;
				}
			}
			if(send || kbd.x == sizeof kbd.line){
				qwrite(lineq, kbd.line, kbd.x);
				kbd.x = 0;
			}
		}
		n = qread(lineq, va, n);
		qunlock(&kbd.q);
		poperror();
		return n;

	case Qscancode:
		if(offset == 0)
			return readstr(0, va, n, gkscanid);
		return qread(gkscanq, va, n);

	case Qkeyboard:
		return qread(gkbdq, va, n);

	case Qevents:
		return qread(c->aux, va, n);

	case Qkprint:
		rlock(&kprintq.l);
		if(waserror()){
			runlock(&kprintq.l);
			nexterror();
		}
		n = qread(kprintq.q, va, n);
		poperror();
		runlock(&kprintq.l);
		return n;
	case Qbattery:
		if(type == 's')
			battery = fopen("/sys/class/power_supply/battery/capacity", "r");
		else if(type == 'c')
			battery = fopen("/sys/class/power_supply/max17042-0/capacity", "r");
		else
			battery = fopen("/sys/class/power_supply/battery/capacity", "r");
		size = fread(buf, 1, sizeof(buf), battery);
		fclose(battery);
		buf[size - 1] = '\0';
		return readstr(offset, va, n, buf);
	case Qtype:
		if(type == 's')
			strncpy(buf, "nexus s", sizeof(buf));
		else if(type == 'c')
			strncpy(buf, "nook color", sizeof(buf));
		else if(type == 'e')
			strncpy(buf, "emulator", sizeof(buf));
		else
			strncpy(buf, "nexus s", sizeof(buf));
		return readstr(offset, va, n, buf);
	case Qbrightness:
		if(type == 'c')
			brightness = fopen("/sys/devices/platform/omap_pwm_led/leds/lcd-backlight/brightness", "r");
		else if(type == 'e')
			return;
		else
			brightness = fopen("/sys/class/backlight/s5p_bl/brightness", "r");
		size = fread(buf, 1, sizeof(buf), brightness);
		fclose(brightness);
		buf[size - 1] = '\0';
		return readstr(offset, va, n, buf);
	}
}
Beispiel #19
0
void
dbgxec(Prog *p)
{
	Bpt *b;
	Prog *kid;
	Osenv *env;
	Progctl *ctl;
	int op, pc, n;
	char buf[ERRMAX+10];
	extern void (*dec[])(void);

	env = p->osenv;
	ctl = env->debug;
	ctl->ref++;
	if(waserror()){
		closedbgctl(ctl, p);
		nexterror();
	}

	R = p->R;
	R.MP = R.M->MP;

	R.IC = p->quanta;
	if((ulong)R.IC > ctl->step)
		R.IC = ctl->step;
	if(ctl->stop)
		R.IC = 0;


	buf[0] = '\0';

	if(R.IC != 0 && R.M->compiled) {
		comvec();
		if(p != currun())
			dbgblock(p);
		goto save;
	}

	while(R.IC != 0) {
		if(0)
			print("step: %lux: %s %4ld %D\n",
				(ulong)p, R.M->m->name, R.PC-R.M->prog, R.PC);

		dec[R.PC->add]();
		op = R.PC->op;
		R.PC++;
		optab[op]();

		/*
		 * check notification about new progs
		 */
		if(op == ISPAWN || op == IMSPAWN) {
			/* pick up the kid from the end of the run queue */
			kid = delruntail(Pdebug);
			n = snprint(buf, sizeof buf, "new %d", kid->pid);
			qproduce(ctl->q, buf, n);
			buf[0] = '\0';
		}
		if(op == ILOAD) {
			n = snprint(buf, sizeof buf, "load %s", string2c(*(String**)R.s));
			qproduce(ctl->q, buf, n);
			buf[0] = '\0';
		}

		/*
		 * check for returns at big steps
		 */
		if(op == IRET)
			R.IC = 1;

		/*
		 * check for blocked progs
		 */
		if(R.IC == 1 && p != currun())
			dbgblock(p);
		if(ctl->stop)
			R.IC = 1;
		R.IC--;

		if(ctl->bpts == nil)
			continue;

		pc = R.PC - R.M->prog;
		for(b = ctl->bpts; b != nil; b = b->next) {
			if(pc == b->pc &&
			  (strcmp(R.M->m->path, b->path) == 0 ||
			   strcmp(R.M->m->path, b->file) == 0)) {
				strcpy(buf, "breakpoint");
				goto save;
			}
		}
	}
save:
	if(ctl->stop)
		strcpy(buf, "stopped");

	p->R = R;

	if(env->debug == nil) {
		poperror();
		return;
	}

	if(p == currun())
		delrun(Pdebug);

	telldbg(env->debug, buf);
	poperror();
	closedbgctl(env->debug, p);
}
Beispiel #20
0
/*
 * Print
 *  sysname: time: mesg
 * on /sys/log/logname.
 * If cons or log file can't be opened, print on the system console, too.
 */
void
syslog(int cons, char *logname, char *fmt, ...)
{
	char buf[1024];
	char *ctim, *p;
	va_list arg;
	int n;
	Dir *d;
	char err[ERRMAX];

	err[0] = '\0';
	errstr(err, sizeof err);
	lock(&sl);

	/*
	 *  paranoia makes us stat to make sure a fork+close
	 *  hasn't broken our fd's
	 */
	d = dirfstat(sl.fd);
	if(sl.fd < 0 || sl.name == nil || strcmp(sl.name, logname) != 0 ||
	   !eqdirdev(d, sl.d)){
		free(sl.name);
		sl.name = strdup(logname);
		if(sl.name == nil)
			cons = 1;
		else{
			free(sl.d);
			sl.d = nil;
			_syslogopen();
			if(sl.fd < 0)
				cons = 1;
			else
				sl.d = dirfstat(sl.fd);
		}
	}
	free(d);
	if(cons){
		d = dirfstat(sl.consfd);
		if(sl.consfd < 0 || !eqdirdev(d, sl.consd)){
			free(sl.consd);
			sl.consd = nil;
			sl.consfd = open("#c/cons", OWRITE|OCEXEC);
			if(sl.consfd >= 0)
				sl.consd = dirfstat(sl.consfd);
		}
		free(d);
	}

	if(fmt == nil){
		unlock(&sl);
		return;
	}

	ctim = ctime(time(0));
	p = buf + snprint(buf, sizeof(buf)-1, "%s ", sysname());
	strncpy(p, ctim+4, 15);
	p += 15;
	*p++ = ' ';
	errstr(err, sizeof err);
	va_start(arg, fmt);
	p = vseprint(p, buf+sizeof(buf)-1, fmt, arg);
	va_end(arg);
	*p++ = '\n';
	n = p - buf;

	if(sl.fd >= 0){
		seek(sl.fd, 0, 2);
		write(sl.fd, buf, n);
	}

	if(cons && sl.consfd >=0)
		write(sl.consfd, buf, n);

	unlock(&sl);
}
Beispiel #21
0
static long
progread(Chan *c, void *va, long n, vlong offset)
{
	int i;
	Prog *p;
	Osenv *o;
	Mntwalk *mw;
	ulong grpid;
	char *a = va;
	Progctl *ctl;
	char mbuf[64], timebuf[12];
	char flag[10];

	if(c->qid.type & QTDIR)
		return devdirread(c, a, n, 0, 0, proggen);

	switch(QID(c->qid)){
	case Qdbgctl:
		ctl = c->aux;
		return qread(ctl->q, va, n);
	case Qstatus:
		acquire();
		p = progpid(PID(c->qid));
		if(p == nil || p->state == Pexiting || p->R.M == H) {
			release();
			snprint(up->genbuf, sizeof(up->genbuf), "%8lud %8d %10s %s %10s %5dK %s",
				PID(c->qid),
				0,
				eve,
				progtime(0, timebuf, timebuf+sizeof(timebuf)),
				progstate[Pexiting],
				0,
				"[$Sys]");
			return readstr(offset, va, n, up->genbuf);
		}
		modstatus(&p->R, mbuf, sizeof(mbuf));
		o = p->osenv;
		snprint(up->genbuf, sizeof(up->genbuf), "%8d %8d %10s %s %10s %5dK %s",
			p->pid,
			p->group!=nil? p->group->id: 0,
			o->user,
			progtime(p->ticks, timebuf, timebuf+sizeof(timebuf)),
			progstate[p->state],
			progsize(p),
			mbuf);
		release();
		return readstr(offset, va, n, up->genbuf);
	case Qwait:
		return qread(c->aux, va, n);
	case Qns:
		acquire();
		if(waserror()){
			release();
			nexterror();
		}
		p = progpid(PID(c->qid));
		if(p == nil)
			error(Ethread);
		mw = c->aux;
		if(mw->cddone){
			poperror();
			release();
			return 0;
		}
		o = p->osenv;
		mntscan(mw, o->pgrp);
		if(mw->mh == 0) {
			mw->cddone = 1;
			i = snprint(a, n, "cd %s\n", o->pgrp->dot->name->s);
			poperror();
			release();
			return i;
		}
		int2flag(mw->cm->mflag, flag);
		if(strcmp(mw->cm->to->name->s, "#M") == 0){
			i = snprint(a, n, "mount %s %s %s %s\n", flag,
				mw->cm->to->mchan->name->s,
				mw->mh->from->name->s, mw->cm->spec? mw->cm->spec : "");
		}else
			i = snprint(a, n, "bind %s %s %s\n", flag,
				mw->cm->to->name->s, mw->mh->from->name->s);
		poperror();
		release();
		return i;
	case Qnsgrp:
		acquire();
		p = progpid(PID(c->qid));
		if(p == nil) {
			release();
			error(Ethread);
		}
		grpid = ((Osenv *)p->osenv)->pgrp->pgrpid;
		release();
		return readnum(offset, va, n, grpid, NUMSIZE);
	case Qpgrp:
		acquire();
		p = progpid(PID(c->qid));
		if(p == nil) {
			release();
			error(Ethread);
		}
		grpid = p->group!=nil? p->group->id: 0;
		release();
		return readnum(offset, va, n, grpid, NUMSIZE);
	case Qstack:
		acquire();
		p = progpid(PID(c->qid));
		if(p == nil || p->state == Pexiting) {
			release();
			error(Ethread);
		}
		if(p->state == Pready) {
			release();
			error(Estopped);
		}
		n = progstack(&p->R, p->state, va, n, offset);
		release();
		return n;
	case Qheap:
		acquire();
		if(waserror()){
			release();
			nexterror();
		}
		n = progheap(c->aux, va, n, offset);
		if(n == -1)
			error(Emisalign);
		poperror();
		release();
		return n;
	case Qfd:
		acquire();
		if(waserror()) {
			release();
			nexterror();
		}
		p = progpid(PID(c->qid));
		if(p == nil)
			error(Ethread);
		o = p->osenv;
		n = progfds(o, va, n, offset);
		poperror();
		release();
		return n;
	case Qexception:
		acquire();
		p = progpid(PID(c->qid));
		if(p == nil) {
			release();
			error(Ethread);
		}
		if(p->exstr == nil)
			up->genbuf[0] = 0;
		else
			snprint(up->genbuf, sizeof(up->genbuf), p->exstr);
		release();
		return readstr(offset, va, n, up->genbuf);
	}
	error(Egreg);
	return 0;
}
Beispiel #22
0
static long
consread(Chan *c, void *va, long n, vlong offset)
{
	ulong l;
	int i, send;
	char *p, buf[64], ch;

	if(c->qid.type & QTDIR)
		return devdirread(c, va, n, contab, nelem(contab), devgen);

	switch((ulong)c->qid.path) {
	default:
		error(Egreg);

	case Qsysctl:
		return readstr(offset, va, n, VERSION);

	case Qsysname:
		if(ossysname == nil)
			return 0;
		return readstr(offset, va, n, ossysname);

	case Qrandom:
		return randomread(va, n);

	case Qnotquiterandom:
		genrandom(va, n);
		return n;

	case Qpin:
		p = "pin set";
		if(up->env->pgrp->pin == Nopin)
			p = "no pin";
		return readstr(offset, va, n, p);

	case Qhostowner:
		return readstr(offset, va, n, eve);

	case Qhoststdin:
		return read(0, va, n);	/* should be pread */

	case Quser:
		return readstr(offset, va, n, up->env->user);

	case Qjit:
		snprint(buf, sizeof(buf), "%d", cflag);
		return readstr(offset, va, n, buf);

	case Qtime:
		snprint(buf, sizeof(buf), "%.lld", timeoffset + osusectime());
		return readstr(offset, va, n, buf);

	case Qdrivers:
		p = malloc(READSTR);
		if(p == nil)
			error(Enomem);
		l = 0;
		for(i = 0; devtab[i] != nil; i++)
			l += snprint(p+l, READSTR-l, "#%C %s\n", devtab[i]->dc,  devtab[i]->name);
		if(waserror()){
			free(p);
			nexterror();
		}
		n = readstr(offset, va, n, p);
		poperror();
		free(p);
		return n;

	case Qmemory:
		return poolread(va, n, offset);

	case Qnull:
		return 0;

	case Qmsec:
		return readnum(offset, va, n, osmillisec(), NUMSIZE);

	case Qcons:
		qlock(&kbd.q);
		if(waserror()){
			qunlock(&kbd.q);
			nexterror();
		}

		if(dflag)
			error(Enonexist);

		while(!qcanread(lineq)) {
			if(qread(kbdq, &ch, 1) == 0)
				continue;
			send = 0;
			if(ch == 0){
				/* flush output on rawoff -> rawon */
				if(kbd.x > 0)
					send = !qcanread(kbdq);
			}else if(kbd.raw){
				kbd.line[kbd.x++] = ch;
				send = !qcanread(kbdq);
			}else{
				switch(ch){
				case '\b':
					if(kbd.x)
						kbd.x--;
					break;
				case 0x15:
					kbd.x = 0;
					break;
				case 0x04:
					send = 1;
					break;
				case '\n':
					send = 1;
				default:
					kbd.line[kbd.x++] = ch;
					break;
				}
			}
			if(send || kbd.x == sizeof kbd.line){
				qwrite(lineq, kbd.line, kbd.x);
				kbd.x = 0;
			}
		}
		n = qread(lineq, va, n);
		qunlock(&kbd.q);
		poperror();
		return n;

	case Qscancode:
		if(offset == 0)
			return readstr(0, va, n, gkscanid);
		return qread(gkscanq, va, n);

	case Qkeyboard:
		return qread(gkbdq, va, n);

	case Qkprint:
		rlock(&kprintq.l);
		if(waserror()){
			runlock(&kprintq.l);
			nexterror();
		}
		n = qread(kprintq.q, va, n);
		poperror();
		runlock(&kprintq.l);
		return n;
	}
}
Beispiel #23
0
void
pexit(char *exitstr, int freemem)
{
	Proc *p;
	Segment **s, **es;
	long utime, stime;
	Waitq *wq, *f, *next;
	Fgrp *fgrp;
	Egrp *egrp;
	Rgrp *rgrp;
	Pgrp *pgrp;
	Chan *dot;
	void (*pt)(Proc*, int, vlong);

	if(up->syscalltrace)
		free(up->syscalltrace);
	up->alarm = 0;
	if (up->tt)
		timerdel(up);
	pt = proctrace;
	if(pt)
		pt(up, SDead, 0);

	/* nil out all the resources under lock (free later) */
	qlock(&up->debug);
	fgrp = up->fgrp;
	up->fgrp = nil;
	egrp = up->egrp;
	up->egrp = nil;
	rgrp = up->rgrp;
	up->rgrp = nil;
	pgrp = up->pgrp;
	up->pgrp = nil;
	dot = up->dot;
	up->dot = nil;
	qunlock(&up->debug);

	if(fgrp)
		closefgrp(fgrp);
	if(egrp)
		closeegrp(egrp);
	if(rgrp)
		closergrp(rgrp);
	if(dot)
		cclose(dot);
	if(pgrp)
		closepgrp(pgrp);

	/*
	 * if not a kernel process and have a parent,
	 * do some housekeeping.
	 */
	if(up->kp == 0) {
		p = up->parent;
		if(p == 0) {
			if(exitstr == 0)
				exitstr = "unknown";
			panic("boot process died: %s", exitstr);
		}

		while(waserror())
			;

		wq = smalloc(sizeof(Waitq));
		poperror();

		wq->w.pid = up->pid;
		utime = up->time[TUser] + up->time[TCUser];
		stime = up->time[TSys] + up->time[TCSys];
		wq->w.time[TUser] = tk2ms(utime);
		wq->w.time[TSys] = tk2ms(stime);
		wq->w.time[TReal] = tk2ms(MACHP(0)->ticks - up->time[TReal]);
		if(exitstr && exitstr[0])
			snprint(wq->w.msg, sizeof(wq->w.msg), "%s %lud: %s", up->text, up->pid, exitstr);
		else
			wq->w.msg[0] = '\0';

		lock(&p->exl);
		/*
		 * Check that parent is still alive.
		 */
		if(p->pid == up->parentpid && p->state != Broken) {
			p->nchild--;
			p->time[TCUser] += utime;
			p->time[TCSys] += stime;
			/*
			 * If there would be more than 128 wait records
			 * processes for my parent, then don't leave a wait
			 * record behind.  This helps prevent badly written
			 * daemon processes from accumulating lots of wait
			 * records.
		 	 */
			if(p->nwait < 128) {
				wq->next = p->waitq;
				p->waitq = wq;
				p->nwait++;
				wq = nil;
				wakeup(&p->waitr);
			}
		}
		unlock(&p->exl);
		if(wq)
			free(wq);
	}

	if(!freemem)
		addbroken(up);

	qlock(&up->seglock);
	es = &up->seg[NSEG];
	for(s = up->seg; s < es; s++) {
		if(*s) {
			putseg(*s);
			*s = 0;
		}
	}
	qunlock(&up->seglock);

	lock(&up->exl);		/* Prevent my children from leaving waits */
	pidunhash(up);
	up->pid = 0;
	wakeup(&up->waitr);
	unlock(&up->exl);

	for(f = up->waitq; f; f = next) {
		next = f->next;
		free(f);
	}

	/* release debuggers */
	qlock(&up->debug);
	if(up->pdbg) {
		wakeup(&up->pdbg->sleep);
		up->pdbg = 0;
	}
	qunlock(&up->debug);

	/* Sched must not loop for these locks */
	lock(&procalloc);
	lock(&palloc);

	edfstop(up);
	up->state = Moribund;
	sched();
	panic("pexit");
}
Beispiel #24
0
static char *
doauth(char *methods)
{
	char *buf, *base64;
	int n;
	DS ds;
	UserPasswd *p;

	dial_string_parse(ddomain, &ds);

	if(user != nil)
		p = auth_getuserpasswd(nil,
	  	  "proto=pass service=smtp server=%q user=%q", ds.host, user);
	else
		p = auth_getuserpasswd(nil,
	  	  "proto=pass service=smtp server=%q", ds.host);
	if (p == nil)
		return Giveup;

	if (strstr(methods, "LOGIN")){
		dBprint("AUTH LOGIN\r\n");
		if (getreply() != 3)
			return Retry;

		n = strlen(p->user);
		base64 = malloc(2*n);
		if (base64 == nil)
			return Retry;	/* Out of memory */
		enc64(base64, 2*n, (uchar *)p->user, n);
		dBprint("%s\r\n", base64);
		if (getreply() != 3)
			return Retry;

		n = strlen(p->passwd);
		base64 = malloc(2*n);
		if (base64 == nil)
			return Retry;	/* Out of memory */
		enc64(base64, 2*n, (uchar *)p->passwd, n);
		dBprint("%s\r\n", base64);
		if (getreply() != 2)
			return Retry;

		free(base64);
	}
	else
	if (strstr(methods, "PLAIN")){
		n = strlen(p->user) + strlen(p->passwd) + 3;
		buf = malloc(n);
		base64 = malloc(2 * n);
		if (buf == nil || base64 == nil) {
			free(buf);
			return Retry;	/* Out of memory */
		}
		snprint(buf, n, "%c%s%c%s", 0, p->user, 0, p->passwd);
		enc64(base64, 2 * n, (uchar *)buf, n - 1);
		free(buf);
		dBprint("AUTH PLAIN %s\r\n", base64);
		free(base64);
		if (getreply() != 2)
			return Retry;
	}
	else
		return "No supported AUTH method";
	return(0);
}