|
|
researchv10 Norman
/*
* run and mount a netb file server,
* including the uid-login name handshake protocol
*/
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h> /* for makedev */
#define NBFS 4 /* for fmount */
/*
* setup handshake parameters
*/
#define MAXMSG 5 /* largest message 5*MSGBLOCK -- known to kernel too */
#define MSGBLOCK 1024
int debug; /* debug level, for server */
char *estr();
main(argc, argv)
int argc;
char **argv;
{
int pfd[2];
int pid;
int sts;
while (--argc > 0 && **++argv == '-') {
switch (argv[0][1]) {
case 'd':
debug = atoi(&argv[0][2]);
break;
default:
fprintf(stderr, "unknown flag %s ignored\n", argv[0]);
break;
}
}
if (argc < 2) {
fprintf(stderr, "usage: runfs [-dlevel] mpoint server arg ...\n");
exit(1);
}
if (pipe(pfd) < 0) {
perror("pipe");
exit(1);
}
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}
/*
* child: run setup handshake, mount filesystem
*/
if (pid == 0) {
close(pfd[1]); /* for clean error */
sts = setup(pfd[0], argv[0]);
exit(sts);
}
/*
* parent: exec server
*/
close(pfd[0]);
dup2(pfd[1], 0);
dup2(pfd[1], 1);
close(pfd[1]);
execv(argv[1], &argv[1]);
fprintf(stderr, "exec %s: %s\n", argv[1], estr());
exit(1);
}
/*
* initial protocol with server:
* client sends 16 bytes:
* max buffer size in 1024-byte units
* device number in use
* protocol letter
* debugging flag
* 12 unused
* server sends one byte: 1
* client sends a list of userids: maxsize bytes
* if list won't fit in one buffer, last username is `:'
* server acks with one byte 012; client sends more
* server sends one byte: 2
* client sends a list of groupids: maxsize bytes
* if list won't fit in one buffer, last groupname is `:'
* server acks with one byte 013; client sends more
* server sends one byte: 3
* then we mount it, and further messages come from the kernel
*/
#define M1LEN 16
setup(fd, mpoint)
int fd;
char *mpoint;
{
char m[M1LEN];
register int n;
signal(SIGPIPE, SIG_DFL);
memset(m, 0, M1LEN);
m[0] = MAXMSG;
/* m[1] = fp->devnum;. */
m[1] = 0; /* will this work? */
m[2] = 'd'; /* ignored by server? */
m[3] = debug;
alarm(600);
if ((n = write(fd, m, M1LEN)) != M1LEN) {
fprintf(stderr, "setup 1: write returned %d; %s\n", n, estr());
alarm(0);
return (-1);
}
if (getresp(fd, 1, mpoint) == 0)
return (-1);
alarm(600);
if (senduid(fd, mpoint) < 0) {
alarm(0);
return (-1);
}
alarm(600);
if (sendgid(fd, mpoint) < 0) {
alarm(0);
return (-1);
}
alarm(60);
alarm(60);
funmount(mpoint); /* bad -- might unmount wrong fs */
if (trymount(fd, mpoint) < 0) {
fprintf(stderr, "fmount: %s: %s\n", mpoint, estr());
alarm(0);
return (-1);
}
alarm(0);
return (0);
}
/*
* fmount, but try to guess unique device number
*/
int
trymount(fd, mpoint)
int fd;
char *mpoint;
{
register int dev;
for (dev = 200; dev >= 100; --dev) {
if (fmount(NBFS, fd, mpoint, makedev(dev, 0)) >= 0)
return (0);
if (errno != EBUSY)
return (-1);
}
return (-1);
}
getresp(fd, id, mpoint)
int fd, id;
{
register int n;
char m;
alarm(600);
n = read(fd, &m, 1);
alarm(0); /* assume errno untouched */
if (n != 1) {
fprintf(stderr, "setup %d: %s: read returned %d: %s\n", id, mpoint, n, estr());
return (0);
}
if (m != id) {
fprintf(stderr, "setup %d: %s: received %d (%c)\n", id, mpoint, (unsigned char)m, m);
return (0);
}
return (1);
}
#define SLOP 50
senduid(fd, mpoint)
int fd;
char *mpoint;
{
char idbuf[MAXMSG*MSGBLOCK+SLOP];
char onebuf[SLOP];
register char *p;
register struct passwd *pw;
register int n, wn;
setpwent();
p = idbuf;
while ((pw = getpwent()) != NULL) {
sprintf(onebuf, "%s %d\n", pw->pw_name, pw->pw_uid);
n = strlen(onebuf);
if (n > &idbuf[MAXMSG*MSGBLOCK] - p - 4) { /* room for ": 1\n" */
strcpy(p, ": 1\n"); /* `more coming' */
if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
fprintf(stderr, "%s: write uid: %d; %s\n", mpoint, wn, estr());
return (-1);
}
if (getresp(fd, 012, mpoint) == 0)
return (-1);
p = idbuf;
}
strcpy(p, onebuf);
p += n;
}
endpwent();
if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
fprintf(stderr, "%s: write uid: %d; %s\n", mpoint, wn, estr());
return (-1);
}
if (getresp(fd, 2, mpoint) == 0)
return (-1);
return (0);
}
sendgid(fd, mpoint)
int fd;
char *mpoint;
{
char idbuf[MAXMSG*MSGBLOCK+SLOP];
char onebuf[SLOP];
register char *p;
register struct group *gr;
register int n, wn;
setgrent();
p = idbuf;
while ((gr = getgrent()) != NULL) {
sprintf(onebuf, "%s %d\n", gr->gr_name, gr->gr_gid);
n = strlen(onebuf);
if (n > &idbuf[MAXMSG*MSGBLOCK] - p - 4) { /* room for ": 1\n" */
strcpy(p, ": 1\n"); /* `more coming' */
if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
fprintf(stderr, "%s: write gid: %d; %s\n", mpoint, wn, estr());
return (-1);
}
if (getresp(fd, 013, mpoint) == 0)
return (-1);
p = idbuf;
}
strcpy(p, onebuf);
p += n;
}
endgrent();
if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
fprintf(stderr, "%s: write gid: %d; %s\n", mpoint, wn, estr());
return (-1);
}
if (getresp(fd, 3, mpoint) == 0)
return (-1);
return (0);
}
char *
estr()
{
static char buf[] = "Error -2147483648";
if (errno < 0 || errno >= sys_nerr) {
sprintf(buf, "Error %d", errno);
return (buf);
}
return (sys_errlist[errno]);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.