V9/netb/src/input.c
#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);
}