/*
 * Copyright 1993, 1994 by Ulrich Khn. All rights reserved.
 *
 * THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY, NOT
 * EVEN THE IMPLIED WARRANTIES OF MERCHANTIBILITY OR
 * FITNESS FOR A PARTICULAR PURPOSE. USE AT YOUR OWN
 * RISK.
 */

/*
   File : nfsd.c
          main driver for the nfs server daemon

   Autor: Ulrich Khn
*/

#include <stdio.h>
#include <osbind.h>
#include <mintbind.h>
#include <signal.h>
#include <string.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "thread.h"
#include "../xfs/nfs.h"
#include "rpc.h"
#include "svc.h"
#include "nfssvc.h"
#include "auth.h"
#include "version.h"


#define NFS_PORT  2049


char msg[] = "\r\nNFSD " VERSION ", (C) Ulrich Khn\r\n"
"\033pUSE IT AT OWN RISK!\033q\r\n\r\n";

#define NFSD_NAME  "nfsd"

char whatmsg[] = "@(#)nfsd " VERSION ", (C) Ulrich Khn  " __DATE__;


extern int __mint;
int daemon_fd;

int debug = 0;



void
init_signals()
{
	signal(SIGHUP, handle_sighup);
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);
}



void
do_timeout(long val)
{
	fh_update(NULL);
}



int
do_daemon(long dummy)
{
	long res, maxmsgsiz = 10240;
	SVCXPRT *xprt;
	struct sockaddr_in sin;

	init_signals();
	res = socket(PF_INET, SOCK_DGRAM, 0);
	if (res < 0)
	{
		Cconws("nfsd: could not open socket\r\n");
		return res;
	}
	daemon_fd = res;

	res = setsockopt(daemon_fd, SOL_SOCKET, SO_RCVBUF,
	                                  &maxmsgsiz, sizeof(long));
	if (res < 0)
	{
		Cconws("nfsd: could not set socket options\r\n");
		return res;
	}
	res = setsockopt(daemon_fd, SOL_SOCKET, SO_SNDBUF,
	                                  &maxmsgsiz, sizeof(long));
	if (res < 0)
	{
		Cconws("nfsd: could not set socket options\r\n");
		return res;
	}

	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = htonl(INADDR_ANY);
	sin.sin_port = htons(NFS_PORT);
	res = bind(daemon_fd, (struct sockaddr*)&sin, sizeof(sin));
	if (res < 0)
	{
		Cconws("nfsd: could not bind socket\r\n");
		return 1;
	}

	xprt = svc_create(daemon_fd, maxmsgsiz, maxmsgsiz);
	if (!xprt)
	{
		Cconws("nfsd: could not create service\r\n");
		return -1;
	}

	if (!svc_register(xprt, NFS_PROGRAM, NFS_VERSION, nfsprog_2, IPPROTO_UDP))
	{
		Cconws("nfsd: could not register service\r\n");
		return -1;
	}
	svc_timeout(xprt, 10000, do_timeout);

	xprt_register(xprt);
	fh_init();

	svc_run();
	return 0;
}



int
main(int argc, char *argv[])
{
	long r;

	/* switch to MiNT's root drive */
	Dsetdrv('u'-'a');
	Dsetpath("\\");      

	/* set up command line options */
	if ((argc == 2) && !strncmp(argv[1], "-d", 2))
	{
		if (argv[1][2])
			debug = argv[1][2] - '0';
		else
			debug = 1;
		Cconws("Debugging enabled at level");
		Cconout(debug+'0');
		Cconws("\r\n");
	}
	else
		debug = 0;

	/* read the export file */
	r = auth_init();
	if (r < 0)
	{
		if (argv[0])
			Cconws(argv[0]);
		else
			Cconws("NFSD");
		Cconws(": error while reading exports file.\r\n");
		return 1;
	}

	/* now fork off the daemon process into the background */
	if (thread(NFSD_NAME, do_daemon, 0) >= 0)
		Cconws(msg);
	else
	{
		if (argv[0])
			Cconws(argv[0]);
		else
			Cconws("NFSD");
		Cconws(": cannot fork.\r\n");
		return 1;
	}
	return 0;
}
