File:  [Research Unix] / researchv9 / ipc / src / mgrs / svcmgr / service.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#include "mgr.h"
#include <sys/types.h>
#include <errno.h>
#include <ctype.h>

fd_set	listenset;	/* set of fd's on which we are listening */
Service *svchead;	/* head of services */
Service *nsvchead;	/* new head of services */

/*
 *  Parse a service definition line.  The line is of the form:
 *  `service action+action+action+...'
 */
Service *
newservice(cp)
	char *cp;
{
#	define MAXACTS 32
	char *arg;
	char *acts[MAXACTS];
	Service *sp=(Service *)malloc(sizeof(Service));
	int i, n;
	Action *lap;

	if(sp==NULL) {
		logevent("out of memory parsing service\n");
		return NULL;
	}
	sp->ap = NULL;
	sp->listen = -1;
	sp->name = NULL;
	sp->next = (Service *)NULL;
	sp->accept = 0;
	sp->lasttime = 1;

	/* find service name */
	for(; isspace(*cp); cp++)
		;
	for(arg=cp; *arg && !isspace(*arg); arg++)
		;
	if(isspace(*arg))
		*arg++ = '\0';
	sp->name = strdup(cp);

	/* separate actions */
	for(; isspace(*arg); arg++)
		;
	for(n=0; n<MAXACTS; n++) {
		if(*arg=='\0')
			break;
		acts[n] = arg;
		for(;;arg++)
			if(*arg=='\\' && *(arg+1)=='+') {
				arg++;
			} else if(*arg=='+') {
				*arg++ = '\0';
				break;
			} else if(*arg=='\0')
				break;
		for(; isspace(*arg)||*arg=='+'; arg++)
			;
	}
	if (n <= 0) {
		logevent("service with no action `%s'\n", cp);
		freeservice(sp);
		return NULL;
	}

	/* parse actions */
	for(lap=NULL, i=0; i<n; i++) {
		if (lap==NULL)
			sp->ap = lap = newaction(acts[i]);
		else
			lap = lap->next = newaction(acts[i]);
		if (lap==NULL) {
			freeservice(sp);
			return NULL;
		}
		lap->next = NULL;
		sp->accept |= lap->accept;
	}
	logevent("newservice(%s)\n", sp->name);
	return sp;
}

freeservice(sp)
	Service *sp;
{
	if(sp==NULL)
		return;
	if(sp->listen>=0) {
		logevent("denouncing %s\n", sp->name);
		close(sp->listen);
		FD_CLR(sp->listen, listenset);
	}
	if(sp->name!=NULL)
		free(sp->name);
	for(; sp->ap!=NULL; sp->ap=sp->ap->next)
		freeaction(sp->ap);
	free((char *)sp);
}

/*
 *  Add a service to the ones for which we are listening
 */
addservice(sp)
	Service *sp;
{
	Service *p;

	/* look for an announced version of the service */
	for(p=svchead; p; p=p->next)
		if (strcmp(sp->name, p->name)==0)
			break;

	/* inherit fd from old service */
	if (p) {
		sp->listen = p->listen;
		p->listen = -1;
	}

	/* add the new service */
	sp->next = nsvchead;
	nsvchead = sp;
	return 0;
}

/*
 *  Start the listening process on any services not already listening.
 */
startsvcs()
{
	Service *p, *np;

	/* denounce old services */
	for(p=svchead; p; p=np) {
		np = p->next;
		freeservice(p);
	}

	/* install new services */
	svchead = nsvchead;
	nsvchead = (Service *)NULL;

	announcesvcs();
}

/*
 *  Announce any services not already listening
 */
announcesvcs()
{
	Service *p;

	/* announce new services */
	for(p=svchead; p; p=p->next) {
		if (p->listen>=0)
			continue;
		logevent("announcing %s\n", p->name);
		p->listen = ipccreat(p->name, "light");
		if (p->listen<0) {
			logevent("failed\n");
			continue;
		}
		chmod(p->name, 0666);
		FD_SET(p->listen, listenset);
	}
}

/*
 *  Reset all services
 */
resetsvcs()
{
	Service *p, *np;

	/* shut down all listeners */
	logevent("resetsrvcs()\n");
	for(p=svchead; p; p=np) {
		logevent("retracting %s\n", p->name);
		np = p->next;
		freeservice(p);
	}
	svchead = (Service *)NULL;
	readfiles();
}

/*
 *  Get a request and vector to the appropriate service
 */
Request *
listen()
{
	fd_set readset;
	Service *sp;
	static Request rp;
	ipcinfo *ip;
	int n;

	for(;;) {
		readset = listenset;
		if((n=select(NOFILE, &readset, (fd_set *)NULL, 30*1000))<0) {
			if (errno!=EINTR) {
				logevent("select failed: %d\n", errno);
				resetsvcs();
			}
			continue;
		}
		if(checkfiles())
			readfiles();
		announcesvcs();
		if(n==0)
			continue;
		for(sp=svchead; sp; sp=sp->next)
			if (FD_ISSET(sp->listen, readset))
				break;
		if (!sp) {
			logevent("listen on bad fd\n");
			resetsvcs();
			continue;
		}
		if ((ip = ipclisten(sp->listen)) == NULL) {
			logevent("bad listen: fd %d\n", sp->listen);
			close(sp->listen);
			FD_CLR(sp->listen, listenset);
			sp->listen = -1;
			continue;
		}
		logevent("call for %s\n", ip->name);
		if (ip->machine==NULL || ip->user==NULL) {
			logevent("null machine/user called %s!\n", sp->name);
			ipcreject(ip, EACCES, "no machine or user name");
			continue;
		}
		logevent("call from %s!%s\n", ip->machine, ip->user);
		if ((!sp->accept) && ipcaccept(ip)<0) {
			logevent("can't accept %s from %s!%s\n", sp->name, ip->machine, ip->user);
			continue;
		}
		logevent("accept %s from %s %s\n", sp->name, ip->machine, ip->user);
		return(newrequest(ip, sp));
	}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.