2.9BSD/usr/net/src/netser/efs/efsd.c
#ifndef lint
static char sccsid[] = "@(#)efsd.c 4.2 10/10/82";
#endif
#include <stdio.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <net/in.h>
#include <errno.h>
#include <pwd.h>
#include <wait.h>
#include <signal.h>
#include <sgtty.h>
#include <stdio.h>
#include <sys/efs.h>
#define EXIT (1)
#define NO_EXIT (2)
#define dprintf if(debug) printf2("efsd: "); \
if(debug) printf2
#define efserror(f, exit) {efssenderror(f, exit); break;}
extern errno;
char *raddr();
int options = SO_ACCEPTCONN|SO_KEEPALIVE|SO_DONTLINGER;
struct sockaddr_in sin = { AF_INET, IPPORT_EFSSERVER };
int debug = 0;
main(argc, argv)
int argc;
char **argv;
{
union wait status;
int f;
struct sockaddr_in from;
#ifndef DEBUG
if (fork())
exit(0);
for (f = 0; f < 10; f++)
(void) close(f);
(void) open("/", 0);
(void) dup2(0, 1);
(void) dup2(0, 2);
{ int tt = open("/dev/tty", 2);
if (tt > 0) {
ioctl(tt, TIOCNOTTY, 0);
close(tt);
}
}
#endif
#if vax
sin.sin_port = htons(sin.sin_port);
#endif
argc--, argv++;
if (argc > 0 && !strcmp(argv[0], "-d")) {
options |= SO_DEBUG;
debug = 1;
}
nice(-4); /* give it some help */
for (;;) {
f = socket(SOCK_STREAM, 0, &sin, options);
if (f < 0) {
perror("socket");
sleep(5);
continue;
}
if (accept(f, &from) < 0) {
perror("accept");
if(close(f) < 0)
perror("close");
sleep(1);
continue;
}
if (fork() == 0)
doit(f, &from);
if(close(f) < 0)
perror("close");
while (wait3(status, WNOHANG, 0) > 0)
continue;
}
}
char bigbuffer[32*1024]; /* is this big enough? */
extern errno;
struct efs_controlblock cb, retcb;
char *getpath();
doit(f, fromp)
int f;
struct sockaddr_in *fromp;
{
char *rhost;
short int mode, uid, gid, cmask;
short int owner, group;
register int i;
long int offset, count, size, len;
char *path;
int fd;
struct stat statb;
#if vax
fromp->sin_port = htons(fromp->sin_port);
#endif
rhost = raddr(fromp->sin_addr.s_addr);
if (fromp->sin_family != AF_INET ||
/* fromp->sin_port >= IPPORT_RESERVED || NOT FOR NOW */
rhost == 0)
abort("connection invalid");
for(;;) {
if(read(f, &cb, sizeof cb) != sizeof cb)
abort("efsd: read1");
dprintf("\ncmd: %d\n", cb.efs_cmd);
switch(cb.efs_cmd) {
case EFS_OPEN:
case EFS_CREAT:
mode = ntohs(cb.efs_mode);
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
cmask = ntohs(cb.efs_cmask);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
dprintf("O/C mode=%o,uid=%d,gid=%d,cmask=%o,path=%s\n",
mode, uid, gid, cmask, path);
umask(cmask);
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if(cb.efs_cmd == EFS_OPEN) {
if((fd = open(path, mode)) < 0)
efserror(f, EXIT);
} else if((fd = creat(path, mode)) < 0)
efserror(f, EXIT);
size = lseek(fd, 0L, 2); /* pass size back */
dprintf("O/C succeeded. size=%d\n", size);
retcb.efs_size = htonl(size);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
break;
case EFS_CLOSE:
if(close(fd) < 0) {
efserror(f, NO_EXIT);
} else {
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
}
exit(0);
case EFS_READ:
offset = ntohl(cb.efs_offset);
count = ntohl(cb.efs_count);
if(count > sizeof bigbuffer)
abort("EFS_READ: buffer too small");
if(lseek(fd, offset, 0) < 0) {
dprintf("efs_read, lseek to %d failed\n", offset);
efserror(f, NO_EXIT);
}
if((len = read(fd, bigbuffer, count)) < 0) {
dprintf("efs_read, read %d failed\n", count);
efserror(f, NO_EXIT);
}
dprintf("read returns %d\n", len);
retcb.efs_size = htonl(len);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
efswrite(f, bigbuffer, len);
break;
case EFS_WRITE:
offset = ntohl(cb.efs_offset);
count = ntohl(cb.efs_count);
if(count > sizeof bigbuffer)
abort("EFS_WRITE: buffer too small");
if(lseek(fd, offset, 0) < 0)
efserror(f, NO_EXIT);
if(read(f, bigbuffer, count) != count)
abort("efsd: read2");
if((len = write(fd, bigbuffer, count)) < 0)
efserror(f, NO_EXIT);
retcb.efs_cmd = EFS_OK;
retcb.efs_size = htonl(len);
efswrite(f, &retcb, sizeof retcb);
break;
case EFS_IOCTL:
if(ioctl(fd, FIONREAD, &size) < 0)
efserror(f, NO_EXIT);
retcb.efs_cmd = EFS_OK;
retcb.efs_size = htonl(size);
efswrite(f, &retcb, sizeof retcb);
break;
case EFS_FSTAT:
if(fstat(fd, &statb) < 0)
efserror(f, NO_EXIT);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
/* THIS IS NOT PORTABLE -- SHOULD htonl EACH FIELD */
efswrite(f, &statb, sizeof statb);
break;
case EFS_STAT:
case EFS_LSTAT:
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if(cb.efs_cmd == EFS_STAT) {
if(stat(path, &statb) < 0)
efserror(f, EXIT);
} else if(lstat(path, &statb) < 0)
efserror(f, EXIT);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
/* THIS IS NOT PORTABLE -- SHOULD htonl EACH FIELD */
efswrite(f, &statb, sizeof statb);
exit(0); /* once only function */
case EFS_UNLINK:
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if(unlink(path) < 0)
efserror(f, EXIT);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
exit(0); /* once only function */
case EFS_READLINK:
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if((len = readlink(path, bigbuffer,
sizeof bigbuffer)) < 0)
efserror(f, EXIT);
retcb.efs_cmd = EFS_OK;
retcb.efs_size = htonl(len);
efswrite(f, &retcb, sizeof retcb);
efswrite(f, bigbuffer, len);
exit(0); /* once only function */
case EFS_CHMOD:
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
mode = ntohs(cb.efs_mode);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if(chmod(path, mode) < 0)
efserror(f, EXIT);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
exit(0); /* once only function */
case EFS_CHOWN:
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
owner = ntohs(cb.efs_owner);
group = ntohs(cb.efs_group);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if(chown(path, owner, group) < 0)
efserror(f, EXIT);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
exit(0); /* once only function */
case EFS_ACCESS:
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
mode = ntohs(cb.efs_mode);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if(access(path, mode) < 0)
efserror(f, EXIT);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
exit(0); /* once only function */
case EFS_UTIME:
uid = ntohs(cb.efs_uid);
gid = ntohs(cb.efs_gid);
for(i = 0; i < (sizeof cb.efs_grps)/(sizeof(int)); i++)
cb.efs_grps[i] = ntohl(cb.efs_grps);
cb.efs_time[0] = ntohl(cb.efs_time[0]);
cb.efs_time[1] = ntohl(cb.efs_time[1]);
path = getpath(f);
if(path == NULL || strlen(path) <= 0) {
errno = ENOENT;
efserror(f, EXIT);
}
setgid(gid);
setgrp(cb.efs_grps, 0);
setuid(uid);
if(utime(path, cb.efs_time) < 0)
efserror(f, EXIT);
retcb.efs_cmd = EFS_OK;
efswrite(f, &retcb, sizeof retcb);
exit(0); /* once only function */
}
}
}
char pathbuf[MAXPATHLEN];
char *getpath(f)
int f;
{
register char *cp;
char c;
for(cp = pathbuf; cp < &pathbuf[MAXPATHLEN]; cp++) {
if(read(f, &c, 1) < 0)
abort("getpath: read1");
*cp = c;
if(c == '\0')
return(pathbuf);
}
abort("getpath: file name too long");
}
efswrite(f, addr, size)
int f;
char *addr;
int size;
{
dprintf("efswrite: size=%d\n", size);
if(write(f, addr, size) != size)
abort("efswrite");
dprintf("\twrite done\n");
}
efssenderror(f, exitflag)
int f, exitflag;
{
dprintf("efssenderror: errno=%d\n", errno);
retcb.efs_cmd = EFS_ERROR;
retcb.efs_error = errno;
efswrite(f, &retcb, sizeof retcb);
if(exitflag == EXIT)
exit(0);
}
abort(str)
char *str;
{
perror(str);
exit(1);
}
printf2(s, a, b, c, d, e, f, g, h)
char *s;
{
fprintf(stderr, s, a, b, c, d, e, f, g, h);
}