V9/netb/src/setup.c
/* the client set up end of the connection */
/* the first message is 16 bytes, (buf-len in 1024's, dev, prot, dbg, 13 unused)
* the second message is the client's passwd file (name uid '\n') and zeros
* the third message is client's gid's and zeros
* each of these is acked by a single byte of 1, 2, resp 3.
*/
#include "share.h"
#include "pwd.h"
#include "grp.h"
struct stat rootstat;
extern int errno;
extern char *sys_errlist[];
int dbgfd = 2, devnum;
/* setup host-name remote-server-to-execute mount-point protocol[dt] */
main(argc, argv)
char **argv;
{ int fd;
if(argc != 6 && argc != 7)
fatal("usage: setup host server mount protocol devnum [dbg]\n");
switch(argv[4][0]) {
default: /* cf /n/bowell/usr/jerq/src/sam/io.c */
fatal("weird net type %s\n", argv[4]);
case 'd': /* datakit */
#ifdef OLD
fd = tdkexec(argv[1], argv[2]);
#else
fd = ipcopen(ipcpath(argv[1], "dk", "fsb"), "heavy");
#endif
break;
case 't':
#ifdef OLD
fd = tcp_rcmd(argv[1], "shell", "pjw", "pjw", "share/zarf", 0);
#else
fd = ipcrexec(argv[1], "heavy", argv[2]);
#endif
break;
}
devnum = atoi(argv[5]);
errno = 0;
if(fd >= 0)
setup(fd, argv[3], argv[4], argc == 7? argv[6]: 0);
else
perror("couldn't call");
debug("setup(%s,%s,%s,%s) errno %d\n", argv[1], argv[2], argv[3], argv[4],
errno);
}
char msg[16];
setup(fd, dir, net, dbg)
char *dir, *net;
{ struct stat stb;
int i;
if(stat(dir, &rootstat) < 0)
fatal("setup: couldn't stat dir %d\n", dir);
msg[0] = 5; /* 5*1024 is the largest message i'll send */
/* that number is known in the kernel in netb.c */
msg[1] = devnum; /* client dev, when shifted left 8 */
msg[2] = net[0]; /* so server knows about messages */
msg[3] = dbg;
#if mc68000
msg[4] = 's';
#endif
#if vax
msg[4] = 'v';
#endif
#if cray
msg[4] = 'c';
#endif
/* the next 12 bytes could be used for authentication or something */
i = write(fd, msg, 16);
if(i != 16)
fatal("write on setup returned %d\n", i);
i = read(fd, msg, 16);
if(i != 1)
fatal("read on setup returned %d |%s|\n", i, msg);
if(msg[0] != 1)
fatal("setup read char %d\b", msg[0]);
/* whew, paranoia is costly, and they're still out there */
/* now send uid table */
senduid(fd);
/* now send gid table */
sendgid(fd);
i = fmount(4 /*fstyp*/, fd, dir, devnum<<8);
if(i < 0)
fatal("gmount returned %d, errno %d:%s\n", i, errno, sys_errlist[errno]);
/* and that's that */
}
char uidbuf[5*1024]; /* 1024*msg[0] */
senduid(cfd)
{ struct passwd *p;
char *s = uidbuf, *t;
int i;
while(p = getpwent()) {
for(t = p->pw_name; *t; t++)
*s++ = *t;
*s++ = ' ';
sprintf(s, "%d\n", p->pw_uid);
while(*s)
s++;
}
endpwent();
*s++ = 0;
if(s >= uidbuf + sizeof(uidbuf))
fatal("client password file too big\n");
/* send and ack */
i = write(cfd, uidbuf, sizeof(uidbuf)); /* write has known length */
if(i != sizeof(uidbuf))
fatal("write uid %d (%d)\n", i, errno);
i = read(cfd, uidbuf, 16);
if(i != 1)
fatal("senduid ack read %d (%d)\n", i, errno);
if(uidbuf[0] != 2)
fatal("send uid ack was %d not 2\n", uidbuf[0]);
}
sendgid(cfd)
{ struct group *p;
char *s = uidbuf, *t;
int i;
for(i = 0; i < sizeof(uidbuf); i++)
uidbuf[i] = 0;
while(p = getgrent()) {
for(t = p->gr_name; *t; t++)
*s++ = *t;
*s++ = ' ';
sprintf(s, "%d\n", p->gr_gid);
while(*s)
s++;
}
endgrent();
*s++ = 0;
if(s >= uidbuf + sizeof(uidbuf))
fatal("client group file too big\n");
/* send and ack */
i = write(cfd, uidbuf, sizeof(uidbuf));
if(i != sizeof(uidbuf))
fatal("write gid %d (%d)\n", i, errno);
i = read(cfd, uidbuf, 16);
if(i != 1)
fatal("sendgid ack read %d (%d)\n", i, errno);
if(uidbuf[0] != 3)
fatal("send gid ack was %d not 2\n", uidbuf[0]);
}
char msgbuf[1024];
/* VARARGS1 */
fatal(s, a, b, c, d, e, f)
char *s;
{
sprintf(msgbuf, s, a, b, c, d, e, f);
write(dbgfd, msgbuf, strlen(msgbuf));
exit(1);
}
/* VARARGS1 */
debug(s, a, b, c, d, e, f)
char *s;
{
sprintf(msgbuf, s, a, b, c, d, e, f);
write(dbgfd, msgbuf, strlen(msgbuf));
}