4.3BSD-UWisc/src/usr.etc/ypserv/ypserv.c

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

#ifndef lint
/* @(#)ypserv.c	2.1 86/04/16 NFSSRC */
static  char sccsid[] = "@(#)ypserv.c 1.1 86/02/05 Copyr 1985 Sun Micro";
#endif

/*
 * This contains the mainline code for the yellowpages server.  Data
 * structures which are process-global are also in this module.  
 */

#include "ypsym.h"
#include <sys/ioctl.h>
#include <sys/file.h>

static char create_failed[] = "ypserv:  Unable to create server for ";
static char register_failed[] = "ypserv:  Unable to register service for ";
char ypdbpath[] = __YP_PATH_PREFIX;
char order_key[] = ORDER_KEY;
char master_key[] = MASTER_KEY;
struct timeval ypintertry = {		/* udp secs betw tries in peer comm */
	YPINTERTRY_TIME,		/* Seconds */
	0				/* uSecs */
};
struct timeval yptimeout = {		/* udp total timeout for peer comm */
	YPTOTAL_TIME,			/* Seconds */
	0				/* uSecs */
};
char myhostname[MAX_MASTER_NAME + 1];
SVCXPRT *udphandle;
SVCXPRT *tcphandle;
bool silent = TRUE;
char logfile[] = "/etc/yp/ypserv.log";

void ypexit();
void ypinit();
void ypdispatch();
void ypolddispatch();
void ypget_command_line_args();
void dezombie();
void logprintf();

/*
 * External refs to functions named only by the dispatchers.
 */
extern void ypdomain();
extern void ypmatch();
extern void ypfirst();
extern void ypnext();
extern void ypxfr();
extern void ypall();
extern void ypmaster();
extern void yporder();
extern void ypoldmatch();
extern void ypoldfirst();
extern void ypoldnext();
extern void ypoldpoll();
extern void yppush();
extern void yppull();
extern void ypget();
extern void ypmaplist();

/*
 * This is the main line code for the yp server.
 */
main(argc, argv)
	int argc;
	char **argv;
{
	int readfds;
	struct timer_action *palarm_action;

 	ypinit(argc, argv); 			/* Set up shop */

	for (;;) {

		readfds = svc_fds;
		errno = 0;

		switch ( (int) select(32, &readfds, (int *) NULL,
		    (int *) NULL, (struct timeval *) NULL) ) {

		case -1:  {
		
			if (errno != EINTR) {
			    logprintf(
			   "ypserv:  bad fds bits in main loop select mask.\n");
			}

			break;
		}

		case 0:  {
			logprintf(
			    "ypserv:  invalid timeout in main loop select.\n");
			break;
		}

		default:  {
			svc_getreq (readfds);
			break;
		}
		
		}

	}

}

/*
 * Does startup processing for the yp server.
 */
void
ypinit(argc, argv)
	int argc;
	char **argv;
{
	int pid;
	int t;

	pmap_unset(YPPROG, YPVERS);
	pmap_unset(YPPROG, YPOLDVERS);
	ypget_command_line_args(argc, argv);

	if (silent) {
		
		pid = fork();
		
		if (pid == -1) {
			logprintf(
			     "ypserv:  ypinit fork failure.\n");
			ypexit();
		}
	
		if (pid != 0) {
			exit(0);
		}
	
		if (access(logfile, W_OK)) {
			(void) freopen("/dev/null", "w", stderr);
		} else {
			(void) freopen(logfile, "a", stderr);
			(void) freopen(logfile, "a", stdout);
		}

		for (t = 3; t < 20; t++) {
			(void) close(t);
		}
	

 		t = open("/dev/tty", 2);
	
 		if (t >= 0) {
 			(void) ioctl(t, (int) TIOCNOTTY, (char *) 0);
 			(void) close(t);
 		}
	}

	(void) gethostname(myhostname, 256);

	if ((int) signal(SIGCHLD, dezombie) == -1) {
		logprintf( "Can't catch process exit signal.\n");
		ypexit();
	}

	if ((udphandle = svcudp_bufcreate(RPC_ANYSOCK, YPMSGSZ, YPMSGSZ))
	    == (SVCXPRT *) NULL) {
		logprintf( "%s%s.\n", create_failed, "udp");
		ypexit();
	}

	if ((tcphandle = svctcp_create(RPC_ANYSOCK, YPMSGSZ, YPMSGSZ))
	    == (SVCXPRT *) NULL) {
		logprintf( "%s%s.\n", create_failed, "tcp");
		ypexit();
	}

	if (!svc_register(udphandle, YPPROG, YPVERS, ypdispatch,
	    IPPROTO_UDP) ) {
		logprintf( "%s%s.\n", register_failed, "udp");
		ypexit();
	}

	if (!svc_register(tcphandle, YPPROG, YPVERS, ypdispatch,
	    IPPROTO_TCP) ) {
		logprintf( "%s%s.\n", register_failed, "tcp");
		ypexit();
	}
	
	if (!svc_register(udphandle, YPPROG, YPOLDVERS, ypolddispatch,
	    IPPROTO_UDP) ) {
		logprintf( "%s%s.\n", register_failed, "udp");
		ypexit();
	}

	if (!svc_register(tcphandle, YPPROG, YPOLDVERS, ypolddispatch,
	    IPPROTO_TCP) ) {
		logprintf( "%s%s.\n", register_failed, "tcp");
		ypexit();
	}
}

/*
 * This picks up any command line args passed from the process invocation.
 */
void
ypget_command_line_args(argc, argv)
	int argc;
	char **argv;
{
	argv++;

	while (--argc) {
		
		if ((*argv)[0] == '-') {

			switch ((*argv)[1]) {
				case 'v': {
					silent = FALSE;
				}
				default: {
					;
				}
			}
				
		}
	}
}

/*
 * This dispatches to server action routines based on the input procedure
 * number.  ypdispatch is called from the RPC function svc_getreq.
 */
void
ypdispatch(rqstp, transp)
	struct svc_req *rqstp;
	SVCXPRT *transp;
{

	switch (rqstp->rq_proc) {

	case YPPROC_NULL:

		if (!svc_sendreply(transp, xdr_void, 0) ) {
			logprintf(
			    "ypserv:  Can't reply to rpc call.\n");
		}

		break;

	case YPPROC_DOMAIN:
		ypdomain(rqstp, transp, TRUE);
		break;

	case YPPROC_DOMAIN_NONACK:
		ypdomain(rqstp, transp, FALSE);
		break;

	case YPPROC_MATCH:
		ypmatch(rqstp, transp);
		break;

	case YPPROC_FIRST:
		ypfirst(rqstp, transp);
		break;

	case YPPROC_NEXT:
		ypnext(rqstp, transp);
		break;

	case YPPROC_XFR:
		ypxfr(rqstp, transp);
		break;

	case YPPROC_CLEAR:
		ypclr_current_map();
		
		if (!svc_sendreply(transp, xdr_void, 0) ) {
			logprintf(
			    "ypserv:  Can't reply to rpc call.\n");
		}

		break;

	case YPPROC_ALL:
		ypall(rqstp, transp);
		break;

	case YPPROC_MASTER:
		ypmaster(rqstp, transp);
		break;

	case YPPROC_ORDER:
		yporder(rqstp, transp);
		break;

	case YPPROC_MAPLIST:
		ypmaplist(rqstp, transp);
		break;

	default:
		svcerr_noproc(transp);
		break;

	}

	return;
}

/*
 * This is the dispatcher for the old yp protocol.  The case symbols are
 * defined in ypv1_prot.h, and are copied (with an added "OLD") from version
 * 1 of yp_prot.h.
 */
void
ypolddispatch(rqstp, transp)
	struct svc_req *rqstp;
	SVCXPRT *transp;
{

	switch (rqstp->rq_proc) {

	case YPOLDPROC_NULL:

		if (!svc_sendreply(transp, xdr_void, 0) ) {
			logprintf(
			    "ypserv:  Can't reply to rpc call.\n");
		}

		break;

	case YPOLDPROC_DOMAIN:
		ypdomain(rqstp, transp, TRUE);
		break;

	case YPOLDPROC_DOMAIN_NONACK:
		ypdomain(rqstp, transp, FALSE);
		break;

	case YPOLDPROC_MATCH:
		ypoldmatch(rqstp, transp);
		break;

	case YPOLDPROC_FIRST:
		ypoldfirst(rqstp, transp);
		break;

	case YPOLDPROC_NEXT:
		ypoldnext(rqstp, transp);
		break;

	case YPOLDPROC_POLL:
		ypoldpoll(rqstp, transp);
		break;

	case YPOLDPROC_PUSH:
		yppush(rqstp, transp);
		break;

	case YPOLDPROC_PULL:
		yppull(rqstp, transp);
		break;

	case YPOLDPROC_GET:
		ypget(rqstp, transp);
		break;

	default:
		svcerr_noproc(transp);
		break;

	}

	return;
}

/*
 * This flushes output to stderr, then aborts the server process to leave a
 * core dump.
 */
static void
ypexit()
{
	(void) fflush(stderr);
	(void) abort();
}

/*
 * This reaps all exit statuses without looking at them to make sure zombies
 * don't accumulate.  
 */
void
dezombie()
{
	int pid;
	union wait wait_status;
	
	while (TRUE) {
		pid = wait3 (&wait_status, WNOHANG, NULL);

		if (pid == 0) {
			break;
		} else if (pid == -1) {
			break;
		}
	}
}



/*
 * This constructs a logging record.
 */
void
logprintf(arg1,arg2,arg3,arg4,arg5,arg6,arg7)
{
	struct timeval t;

	if (silent) {
		(void) gettimeofday(&t, NULL);
		fseek(stderr,0,2);
		(void) fprintf(stderr, "%19.19s: ", ctime(&t.tv_sec));
	}
	(void) fprintf(stderr,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
	fflush(stderr);
}