/*
 * And thus spoke RPCGEN:
 *    Please do not edit this file.
 *    It was generated using rpcgen.
 *
 * And thus replied Lpd@NannyMUD:
 *    Who cares? :-) /Peter Eriksson <pen@signum.se>
 */

#include "system.h"

#include "yp.h"
#include <stdio.h>
#include <stdlib.h>
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <syslog.h>

extern char version[];


#ifdef __STDC__
#define SIG_PF void(*)(int)
#endif

static void
ypprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
{
	union {
		domainname ypproc_domain_2_arg;
		domainname ypproc_domain_nonack_2_arg;
		ypreq_key ypproc_match_2_arg;
		ypreq_key ypproc_first_2_arg;
		ypreq_key ypproc_next_2_arg;
		ypreq_xfr ypproc_xfr_2_arg;
		ypreq_nokey ypproc_all_2_arg;
		ypreq_nokey ypproc_master_2_arg;
		ypreq_nokey ypproc_order_2_arg;
		domainname ypproc_maplist_2_arg;
	} argument;
	char *result;
	xdrproc_t xdr_argument, xdr_result;
	char *(*local)(char *, struct svc_req *);

	switch (rqstp->rq_proc) {
	case YPPROC_NULL:
		xdr_argument = (xdrproc_t) xdr_void;
		xdr_result = (xdrproc_t) xdr_void;
		local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc;
		break;

	case YPPROC_DOMAIN:
		xdr_argument = (xdrproc_t) xdr_domainname;
		xdr_result = (xdrproc_t) xdr_bool;
		local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc;
		break;

	case YPPROC_DOMAIN_NONACK:
		xdr_argument = (xdrproc_t) xdr_domainname;
		xdr_result = (xdrproc_t) xdr_bool;
		local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc;
		break;

	case YPPROC_MATCH:
		xdr_argument = (xdrproc_t) xdr_ypreq_key;
		xdr_result = (xdrproc_t) xdr_ypresp_val;
		local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc;
		break;

	case YPPROC_FIRST:
#if 0 /* Bug in Sun's yp.x RPC prototype file */
		xdr_argument = (xdrproc_t) xdr_ypreq_key;
#else
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
#endif
		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
		local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc;
		break;

	case YPPROC_NEXT:
		xdr_argument = (xdrproc_t) xdr_ypreq_key;
		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
		local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc;
		break;

	case YPPROC_XFR:
		xdr_argument = (xdrproc_t) xdr_ypreq_xfr;
		xdr_result = (xdrproc_t) xdr_ypresp_xfr;
		local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc;
		break;

	case YPPROC_CLEAR:
		xdr_argument = (xdrproc_t) xdr_void;
		xdr_result = (xdrproc_t) xdr_void;
		local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc;
		break;

	case YPPROC_ALL:
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
		xdr_result = (xdrproc_t) xdr_ypresp_all;
		local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc;
		break;

	case YPPROC_MASTER:
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
		xdr_result = (xdrproc_t) xdr_ypresp_master;
		local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc;
		break;

	case YPPROC_ORDER:
		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
		xdr_result = (xdrproc_t) xdr_ypresp_order;
		local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc;
		break;

	case YPPROC_MAPLIST:
		xdr_argument = (xdrproc_t) xdr_domainname;
		xdr_result = (xdrproc_t) xdr_ypresp_maplist;
		local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc;
		break;

	default:
		svcerr_noproc(transp);
		return;
	}
	(void) memset((char *)&argument, 0, sizeof (argument));
	if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
		svcerr_decode(transp);
		return;
	}
	result = (*local)((char *)&argument, rqstp);
	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
		svcerr_systemerr(transp);
	}
	if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
		fprintf(stderr, "unable to free arguments");
		exit(1);
	}
	return;
}

#if 0
static void
yppush_xfrrespprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
	union {
		int fill;
	} argument;
	char *result;
	xdrproc_t xdr_argument, xdr_result;
	char *(*local)(char *, struct svc_req *);

	switch (rqstp->rq_proc) {
	case YPPUSHPROC_NULL:
		xdr_argument = (xdrproc_t) xdr_void;
		xdr_result = (xdrproc_t) xdr_void;
		local = (char *(*)(char *, struct svc_req *)) yppushproc_null_1_svc;
		break;

	case YPPUSHPROC_XFRRESP:
		xdr_argument = (xdrproc_t) xdr_void;
		xdr_result = (xdrproc_t) xdr_yppushresp_xfr;
		local = (char *(*)(char *, struct svc_req *)) yppushproc_xfrresp_1_svc;
		break;

	default:
		svcerr_noproc(transp);
		return;
	}
	(void) memset((char *)&argument, 0, sizeof (argument));
	if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
		svcerr_decode(transp);
		return;
	}
	result = (*local)((char *)&argument, rqstp);
	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
		svcerr_systemerr(transp);
	}
	if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
		fprintf(stderr, "unable to free arguments");
		exit(1);
	}
	return;
}

static void
ypbindprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
{
	union {
		domainname ypbindproc_domain_2_arg;
		ypbind_setdom ypbindproc_setdom_2_arg;
	} argument;
	char *result;
	xdrproc_t xdr_argument, xdr_result;
	char *(*local)(char *, struct svc_req *);

	switch (rqstp->rq_proc) {
	case YPBINDPROC_NULL:
		xdr_argument = (xdrproc_t) xdr_void;
		xdr_result = (xdrproc_t) xdr_void;
		local = (char *(*)(char *, struct svc_req *)) ypbindproc_null_2_svc;
		break;

	case YPBINDPROC_DOMAIN:
		xdr_argument = (xdrproc_t) xdr_domainname;
		xdr_result = (xdrproc_t) xdr_ypbind_resp;
		local = (char *(*)(char *, struct svc_req *)) ypbindproc_domain_2_svc;
		break;

	case YPBINDPROC_SETDOM:
		xdr_argument = (xdrproc_t) xdr_ypbind_setdom;
		xdr_result = (xdrproc_t) xdr_void;
		local = (char *(*)(char *, struct svc_req *)) ypbindproc_setdom_2_svc;
		break;

	default:
		svcerr_noproc(transp);
		return;
	}
	(void) memset((char *)&argument, 0, sizeof (argument));
	if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
		svcerr_decode(transp);
		return;
	}
	result = (*local)((char *)&argument, rqstp);
	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
		svcerr_systemerr(transp);
	}
	if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
		fprintf(stderr, "unable to free arguments");
		exit(1);
	}
	return;
}
#endif

extern int debug_flag;
extern int dns_flag;

#ifndef _PATH_YP
#define _PATH_YP   "/var/yp"
#endif
char *path_ypdb = _PATH_YP;

char *progname;


int main(int argc, char **argv)
{
    register SVCXPRT	*transp;
    int	         	i;
    int			my_port = -1;
    int			my_socket;
    struct sockaddr_in	socket_address;
    int			result;

    
    progname = strrchr (argv[0], '/');
    if (progname == (char *) NULL)
	progname = argv[0];
    else
	progname++;

    for (i = 1; i < argc && argv[i][0] == '-'; i++)
    {
	if (strcmp(argv[i], "-debug") == 0 || strcmp(argv[i], "-d") == 0)
	    debug_flag = 1;
	else if (strcmp(argv[i], "-dns") == 0 || strcmp(argv[i], "-b") == 0)
	    dns_flag = 1;
	else if ((argv[i][1] == 'p') && (argv[i][2] >= '0') && (argv[i][2] <= '9'))
	    my_port = atoi(argv[i] + 2);
	else
	{
	    fprintf(stderr, "%s: Unknown command line switch: %s\n",
		    progname,
		    argv[i]);
	    exit(1);
	}
    }

    if (debug_flag)
	fprintf(stderr, "[Welcome to the NYS YP Server, version %s]\n",
		version);
    else
    {
	int i;
	
	if (fork())
	    exit(0);

	for (i = 0; i < 255; i++)
	    close(i);
	
	if (fork())
	    exit(0);
    }

#if TCP_WRAPPER
    openlog(progname, LOG_PID, TCPW_FACILITY);
#endif
    
    if (i < argc)
    {
	path_ypdb = argv[i];
	if (debug_flag)
	    fprintf(stderr, "Using database directory: %s\n", path_ypdb);
    }

    /* Change current directory to database location */
    if (chdir(path_ypdb) < 0)
    {
	fprintf(stderr, "%s: chdir: ", argv[0]);
	perror(path_ypdb);
	exit(1);
    }
	
    (void) pmap_unset(YPPROG, YPVERS);
#ifdef SUNOS_COMPATIBILITY_KLUDGE
    (void) pmap_unset(YPPROG, 1);
#endif
    
    if (my_port >= 0)
    {
	my_socket = socket (AF_INET, SOCK_DGRAM, 0);
	if (my_socket < 0)
	{
	    fprintf (stderr, "%s: can not create UDP ",
		     progname);
	    perror("socket");
	    exit (1);
	}

	socket_address.sin_family = AF_INET;
	socket_address.sin_addr.s_addr = htonl (INADDR_ANY);
	socket_address.sin_port = htons (my_port);

	result = bind (my_socket, (struct sockaddr *) &socket_address,
		       sizeof (socket_address));
	if (result < 0)
	{
	    fprintf (stderr, "%s: can not bind UDP ",
		     progname);
	    perror("socket");
	    exit (1);
	}
    }
    else
	my_socket = RPC_ANYSOCK;

    transp = svcudp_create(my_socket);
    if (transp == NULL) {
	fprintf(stderr, "cannot create udp service.");
	exit(1);
    }
    if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, IPPROTO_UDP)) {
	fprintf(stderr, "unable to register (YPPROG, YPVERS, udp).");
	exit(1);
    }

#ifdef SUNOS_COMPATIBILITY_KLUDGE
    /*
    ** This is just to make us reply to YP version 1 calls which SunOS 4's
    ** ypbind seems to insist on finding. If someone _really_ tries to
    ** use this the they will probably be bitten - _hard_, since I haven't
    ** got the faintest idea on how the XDR calls for YP version 1 should
    ** look like. The Domain_NoNack call seems to be compatible though :-)
    */
    if (!svc_register(transp, YPPROG, 1, ypprog_2, IPPROTO_UDP)) {
	fprintf(stderr, "unable to register (YPPROG, 1, udp).");
	exit(1);
    }
#endif
    
    if (my_port >= 0)
    {
	my_socket = socket (AF_INET, SOCK_STREAM, 0);
	if (my_socket < 0)
	{
	    fprintf (stderr, "%s: can not create TCP ",
		     progname);
	    perror("socket");
	    exit (1);
	}

	socket_address.sin_family = AF_INET;
	socket_address.sin_addr.s_addr = htonl (INADDR_ANY);
	socket_address.sin_port = htons (my_port);

	result = bind (my_socket, (struct sockaddr *) &socket_address,
		       sizeof (socket_address));
	if (result < 0)
	{
	    fprintf (stderr, "%s: can not bind TCP ",
		     progname);
	    perror("socket");
	    exit (1);
	}
    }
    else
	my_socket = RPC_ANYSOCK;

    transp = svctcp_create(my_socket, 0, 0);
    if (transp == NULL) {
	fprintf(stderr, "%s: cannot create tcp service\n", progname);
	exit(1);
    }
    if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, IPPROTO_TCP)) {
	fprintf(stderr, "%s: unable to register (YPPROG, YPVERS, tcp)\n", progname);
	exit(1);
    }
	
    svc_run();
    fprintf(stderr, "svc_run returned");
    exit(1);
    /* NOTREACHED */
}
