V9/netb/src/input.c

Compare this file to the similar file:
Show the results in this format:

#include "share.h"
#include "signal.h"
/* this is the main server routine.  All the real work is in work.c, but
 * the messages are built here, and converted from the client's types */

struct client client;
unsigned char *inbuf, *nmbuf;
int inlen, hisdev, proto, iamroot;
int clienttype;
extern char *cmdname[];

server(len)
{	int i, n;
	inbuf = (unsigned char *) malloc(inlen = len);
	nmbuf = (unsigned char *) malloc(inlen);
	error("max msg %d bytes\n", len);
	iamroot = getuid() == 0;
	getexcepts();	/* read the exception table */
	getuids();
	getgids();
	doneexcepts();
	/* put the root into files[] */
	addroot();
	signals();
loop:
	switch(proto) {
	default:
		fatal("unk protocol %d |%c|\n", proto, proto);
	case 'd':	/* datakit, so messages */
		n = read(cfd, inbuf, inlen);
		if(n < 16)	/* header is known to be 16 bytes long */
			fatal("server read %d (<16)\n", n);
		if(inbuf[0] != NETB)
			fatal("server wanted version %d, got %d\n", NETB, inbuf[0]);
		break;
	case 't':	/* tcp, wretched byte stream */
		n = tcpread();
		break;
	}
	/* now convert the damned structures */
	debug("server %d bytes for %s (%d)\n", n, cmdname[inbuf[1]], inbuf[1]);
	fromclient(n);
	goto loop;
}

gotsig(n)
{
	error("exiting on signal %d\n", n);
	abort();
	exit(1);
}

signals()
{	int i;
	for(i = 1; i < NSIG; i++)
		signal(i, gotsig);
}

tcpread()
{	unsigned char *p;
	int cnt, n, len;
	p = inbuf;
	/* first read a sendb struct, which is known to be 16 bytes long */
	cnt = 0;
moreheader:
	n = read(cfd, p, inlen);
	if(n < 0)
		fatal("tcpread -1 (%d)\n", errno);
	if(n == 0)
		fatal("tcp first read 0\n");
	p += n;
	cnt += n;
	if(cnt < 16)
	goto moreheader;
	/* the first byte must be NETB */
	if(inbuf[0] != NETB)
		fatal("tcp read version %d, not %d\n", inbuf[0], NETB);
	len = clientlong(inbuf + 8);	/* server knows where len is in header */
	if(cnt > len)
		fatal("tcp read %d (>%d)\n", cnt, len);
more:
	if(cnt >= len)
		return(cnt);
	n = read(cfd, p, len - cnt);
	if(n <= 0)
		fatal("tcp read loop %d after %d (%d)\n", n, cnt, errno);
	cnt += n;
	p += n;
	goto more;
}

struct client nilclient;
/* knows what clients send.  when they're not all vaxes, change this */
fromclient(len)
{	unsigned char *p = inbuf;
	client = nilclient;	/* can you remember who sets what? */
	/* first the struct sendb */
	p++;	/* skip version */
	client.cmd = *p++;
	client.flags = *p++;
	p++;	/* skip */
	client.trannum = clientlong(p);
	p += 4;
	client.len = clientlong(p);
	p += 4;
	client.tag = clientlong(p);
	p += 4;
	if(client.len != len)
		fatal("client sent %d, claimed len was %d\n", len, client.len);
	if(client.tag == 0) {
		error("client sent tag 0 (cmd %d)\n", client.cmd);
		client.errno = ENOENT;
		goto respond;
	}
	/* now per individual requirement */
	switch(client.cmd) {
	default:
		fatal("client send unknown command %d %d\n", client.cmd, inbuf[1]);
	case NBPUT:
		if(len != p - inbuf)
			fatal("client put size, %d (!= %d)\n", len, p - inbuf);
		doput();
		break;
	case NBUPD:
		p += 4;	/* skip */
		client.uid = clientshort(p);
		p += 2;
		client.gid = clientshort(p);
		p += 2;
		client.mode = clientshort(p);
		p += 2;
		client.dev = clientshort(p);
		p += 2;
		p += 4;	/* skip */
		client.ta = clientlong(p);
		p += 4;
		client.tm = clientlong(p);
		p += 4;
		if(len != p - inbuf)
			fatal("client upd size, %d (!= %d)\n", len, p - inbuf);
		doupdate();
		break;
	case NBREAD:
		client.count = clientlong(p);	/* sanity check in doread() */
		p += 4;
		client.offset = clientlong(p);
		p += 4;
		if(len != p - inbuf)
			fatal("client read size, %d (!= %d)\n", len, p - inbuf);
		doread();
		break;
	case NBWRT:
		client.count = clientlong(p);	/* sanity check in dowrite() */
		p += 4;
		client.offset = clientlong(p);
		p += 4;
		if(len != p - inbuf + client.count)
			fatal("client write size, %d (!= %d)\n", len, p - inbuf + client.count);
		dowrite(p);
		break;
	case NBNAMI:
		p += 4;	/* skip */
		client.uid = clientshort(p);
		p += 2;
		client.gid = clientshort(p);
		p += 2;
		client.mode = clientshort(p);
		p += 2;
		client.dev = clientshort(p);
		p += 2;
		client.ino = clientlong(p);
		p += 4;
		donami(p, len - (p - inbuf));
		break;
	case NBSTAT:
		client.ta = clientlong(p);
		p += 4;
		p += 4;	/* skip */
		if(len != p - inbuf)
			fatal("client stat too long, %d (> %d)\n", len, p - inbuf);
		dostat();
		break;
	case NBTRNC:
		if(len != p - inbuf)
			fatal("client trunc too long, %d (> %d)\n", len, p - inbuf);
		dotrunc();
		break;
	}
respond:	
	responce(client.cmd);
}
#ifdef ns32000
#define vax 1
#endif
#if vax == 1
/* clients to vax */
clientlong(p)
unsigned char *p;
{
	switch (clienttype) {
		case 'v':
			return(*(long *)p);
		case 's':
			return(rev4(p));
	}
}

clientshort(p)
unsigned char *p;
{
	switch (clienttype) {
		case 'v':
			return(*(short *)p);
		case 's':
			return(rev2(p));
	}
}
#endif
#if cray == 1
/* client to cray */
clientlong(p)
unsigned char *p;
{	union {
		int x;
		unsigned char b[8];
	} u;
	int i;
	u.x = 0;
	switch (clienttype) {
		case 'v':
			for(i = 0; i < 4; i++)
				u.b[7-i] = *p++;
			return(u.x);
		case 's':
			for(i = 0; i < 4; i++)
				u.b[4+i] = *p++;
			return(u.x);
	}
}
clientshort(p)
unsigned char *p;
{	union {
		int x;
		unsigned char b[8];
	} u;
	int i;
	u.x = 0;
	switch (clienttype) {
		case 'v':
			for(i = 0; i < 2; i++)
				u.b[7-i] = *p++;
			return(u.x);
		case 's':
			for(i = 0; i < 2; i++)
				u.b[6+i] = *p++;
			return(u.x);
	}
}
#endif
#if sun == 1
/* client to sun */
clientlong(p)
unsigned char *p;
{
	switch (clienttype) {
		case 'v':
			return(rev4(p));
		case 's':
			return(*(long *)p);
	}
}

clientshort(p)
unsigned char *p;
{
	switch (clienttype) {
		case 'v':
			return(rev2(p));
		case 's':
			return(*(short *)p);
	}
}
#endif

rev4(p)
unsigned char *p;
{	union {
		long x;
		unsigned char b[4];
	} u;
	int i;
	for(i = 0; i < 4; i++)
		u.b[3-i] = *p++;
	return(u.x);
}
rev2(p)
unsigned char *p;
{	union {	/* this better work! */
		short x;
		unsigned char b[2];
	} u;
	int i;
	u.x = 0;
	for(i = 0; i < 2; i++)
		u.b[1-i] = *p++;
	return(u.x);
}