V10/netfs/libnetb/runfs.c

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

/*
 * 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]);
}