/*
    YPS-0.2, NIS-Server for Linux
    Copyright (C) 1994  Tobias Reber

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
static char rcsid[]="(#)$Id: ypserv_s.c,v 0.16 1994/01/02 21:59:08 root Exp $";

/*
 *	$Author: root $
 *	$Log: ypserv_s.c,v $
 * Revision 0.16  1994/01/02  21:59:08  root
 * Strict prototypes
 *
 * Revision 0.15  1994/01/02  20:10:08  root
 * Added GPL notice
 *
 * Revision 0.14  1994/01/02  18:00:38  root
 * Changed arguments to ypxfr
 *
 * Revision 0.13  1993/06/12  10:49:35  root
 * Align with include-4.4
 *
 */

#include <stdio.h>
#include <sys/ioctl.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <fcntl.h>
#include <termios.h>
#include <rpcsvc/yp.h>
#include <signal.h>

#ifdef DEBUG
#define PRINTF(x) printf x;
#else
#define PRINTF(x)
#endif

struct sockaddr_in *caller;
 
static void ypprog_2( struct svc_req *rqstp, SVCXPRT *transp);
 
static void ypserv(void);

void
main(int argc, char **argv)
{
	switch(fork()) {
	case 0:		/* child */
		{
			int fd=open("/dev/tty", O_RDWR);
			ioctl(fd, TIOCNOTTY, NULL);
			close(fd);
		}
		ypserv();
		exit(1);
	case (-1):
		perror("fork");
		exit(1);
	default:
		exit(0);
	}
}

static void
ypserv(void)
{
        SVCXPRT *transp;
 
	signal(SIGCHLD, SIG_IGN);

        pmap_unset(YPPROG, YPVERS);
 
        transp = svcudp_create(RPC_ANYSOCK);
        if (transp == NULL) {
                fprintf(stderr, "cannot create udp service.\n");
                exit(1);
        }
        if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, IPPROTO_UDP)) {
                fprintf(stderr, "unable to register (YPPROG, YPVERS, udp).\n");
                exit(1);
        }
 
        transp = svctcp_create(RPC_ANYSOCK, 0, 0);
        if (transp == NULL) {
                fprintf(stderr, "cannot create tcp service.\n");
                exit(1);
        }
        if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, IPPROTO_TCP)) {
                fprintf(stderr, "unable to register (YPPROG, YPVERS, tcp).\n");
                exit(1);
        }
        svc_run();
        fprintf(stderr, "svc_run returned\n");
        exit(1);
}
 
static void
ypprog_2( struct svc_req *rqstp, 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;
        bool_t (*xdr_argument)(XDR *, void *), (*xdr_result)(XDR *, void *);
        char *(*local)(void *, struct svc_req *);
 
        caller=svc_getcaller(transp);
        switch (rqstp->rq_proc) {
        case YPPROC_NULL:
                xdr_argument = (bool_t (*)(XDR *, void *))xdr_void;
                xdr_result = (bool_t (*)(XDR *, void *))xdr_void;
                local = (char *(*)(void *, struct svc_req *)) ypproc_null_2;
                break;
 
        case YPPROC_DOMAIN:
                xdr_argument = xdr_domainname;
                xdr_result = (bool_t (*)(XDR *, void *))xdr_bool;
                local = (char *(*)(void *, struct svc_req *)) ypproc_domain_2;
                break;
 
        case YPPROC_DOMAIN_NONACK:
                xdr_argument = xdr_domainname;
                xdr_result = (bool_t (*)(XDR *, void *))xdr_bool;
                local = (char *(*)(void *, struct svc_req *)) ypproc_domain_nonack_2;
                break;
 
        case YPPROC_MATCH:
                xdr_argument = xdr_ypreq_key;
                xdr_result = xdr_ypresp_val;
                local = (char *(*)(void *, struct svc_req *)) ypproc_match_2;
                break;
 
        case YPPROC_FIRST:
                xdr_argument = xdr_ypreq_nokey;
                xdr_result = xdr_ypresp_key_val;
                local = (char *(*)(void *, struct svc_req *)) ypproc_first_2;
                break;
 
        case YPPROC_NEXT:
                xdr_argument = xdr_ypreq_key;
                xdr_result = xdr_ypresp_key_val;
                local = (char *(*)(void *, struct svc_req *)) ypproc_next_2;
                break;
 
        case YPPROC_XFR:
                xdr_argument = xdr_ypreq_xfr;
                xdr_result = xdr_ypresp_xfr;
                local = (char *(*)(void *, struct svc_req *)) ypproc_xfr_2;
                break;
 
        case YPPROC_CLEAR:
                xdr_argument = (bool_t (*)(XDR *, void *))xdr_void;
                xdr_result = (bool_t (*)(XDR *, void *))xdr_void;
                local = (char *(*)(void *, struct svc_req *)) ypproc_clear_2;
                break;
 
        case YPPROC_ALL:
                xdr_argument = xdr_ypreq_nokey;
                xdr_result = xdr_ypresp_all;
                local = (char *(*)(void *, struct svc_req *)) ypproc_all_2;
                break;
 
        case YPPROC_MASTER:
                xdr_argument = xdr_ypreq_nokey;
                xdr_result = xdr_ypresp_master;
                local = (char *(*)(void *, struct svc_req *)) ypproc_master_2;
                break;
 
        case YPPROC_ORDER:
                xdr_argument = xdr_ypreq_nokey;
                xdr_result = xdr_ypresp_order;
                local = (char *(*)(void *, struct svc_req *)) ypproc_order_2;
                break;
 
        case YPPROC_MAPLIST:
                xdr_argument = xdr_domainname;
                xdr_result = xdr_ypresp_maplist;
                local = (char *(*)(void *, struct svc_req *)) ypproc_maplist_2;
                break;
 
        default:
                svcerr_noproc(transp);
                return;
        }
        bzero(&argument, sizeof(argument));
        if (!svc_getargs(transp, xdr_argument, &argument)) {
                svcerr_decode(transp);
                return;
        }
        result = (*local)(&argument, rqstp);
        if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
                svcerr_systemerr(transp);
        }
        if (!svc_freeargs(transp, xdr_argument, &argument)) {
                fprintf(stderr, "unable to free arguments\n");
                exit(1);
        }
}
