/* -*- c++ -*- (enables emacs c++ mode) */
/*========================================================================

 Copyright (C) 2006-2009 Yves Renard, Julien Pommier.

 This file is a part of GETFEM++

 Getfem++ is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as
 published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
 You should have received a copy of the GNU Lesser General Public
 License along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301,
 USA.

 ========================================================================*/

/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#include "gfi_rpc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#ifndef __MINGW32__
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

#ifndef SIG_PF
#define SIG_PF void(*)(int)
#endif

#ifdef WIN32
#define STR_LAST_ERROR strerror(WSAGetLastError())
#else
#define STR_LAST_ERROR strerror(errno)
#endif

static void *
_gfmrpc_null_1 (void  *argp, struct svc_req *rqstp)
{
        return (gfmrpc_null_1_svc(rqstp));
}

static void *
_gfmrpc_chdir_1 (char * *argp, struct svc_req *rqstp)
{
	return (gfmrpc_chdir_1_svc(*argp, rqstp));
}

static gfi_output *
_gfmrpc_call_1 (gfmrpc_call_1_argument *argp, struct svc_req *rqstp)
{
	return (gfmrpc_call_1_svc(argp->config_id, argp->fname, argp->in, argp->nlhs, rqstp));
}

static void
gfmrpc_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
	union {
		char *gfmrpc_chdir_1_arg;
		gfmrpc_call_1_argument gfmrpc_call_1_arg;
	} argument;
	char *result;
	xdrproc_t _xdr_argument, _xdr_result;
	char *(*local)(char *, struct svc_req *);

	switch (rqstp->rq_proc) {
	case GFMRPC_NULL:
	  _xdr_argument = (xdrproc_t) xdr_void;
	  _xdr_result = (xdrproc_t) xdr_void;
	  local = (char *(*)(char *, struct svc_req *)) _gfmrpc_null_1;
	  break;
	case GFMRPC_CHDIR:
		_xdr_argument = (xdrproc_t) xdr_wrapstring;
		_xdr_result = (xdrproc_t) xdr_void;
		local = (char *(*)(char *, struct svc_req *)) _gfmrpc_chdir_1;
		break;

	case GFMRPC_CALL:
		_xdr_argument = (xdrproc_t) xdr_gfmrpc_call_1_argument;
		_xdr_result = (xdrproc_t) xdr_gfi_output;
		local = (char *(*)(char *, struct svc_req *)) _gfmrpc_call_1;
		break;

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

void sigint(int sig) {
  fprintf(stderr, "shuting down getfem_interface ...\n");
  exit(0);
}

int
main (int argc, char **argv)
{
	register SVCXPRT *transp;
#ifdef __MINGW32__
        rpc_nt_init();
#endif
	signal(SIGINT, sigint);
        if (argc > 1 && strcmp(argv[1], "-tcp") == 0) {
          pmap_unset (GFMRPC, GFMRPC_VERS_1);
          transp = svctcp_create(RPC_ANYSOCK, 0, 0);
          if (transp == NULL) {
            fprintf (stderr, "cannot create tcp service.\n");
            exit(1);
          }
          if (!svc_register(transp, GFMRPC, GFMRPC_VERS_1, gfmrpc_1, IPPROTO_TCP)) {
            fprintf (stderr, "unable to register (GFMRPC, GFMRPC_VERS_1, tcp).");
            exit(1);
          }
	  printf("getfem interface server is up and listenning on port %d\n", transp->xp_port);
	  printf("You can now establish the connection from the matlab prompt with:\n");
	  printf("      gf_workspace('connect','localhost'); gf_workspace('stats')\n");
	  printf("This requires that you have the portmap service running\n");
        } else if (argc > 1 && strcmp(argv[1],"-slave") == 0) {
#ifndef __MINGW32__
	  struct stat st;
	  if (fstat(4,&st) == -1 || !S_ISSOCK(st.st_mode)) {
	    fprintf(stderr, "missing socket, can't start %s in slave mode\n", argv[0]);
          }
#endif
          transp = (SVCXPRT*)svcfd_create(4,0,0);
	  /*transp = svcunix_create(-1, 0, 0, local_sockname);*/
          if (transp == NULL) {
            fprintf (stderr, "cannot create unix domain socket service\n");
            exit(1);
          }
          if (!svc_register(transp, GFMRPC, GFMRPC_VERS_1, gfmrpc_1, 0)) {
            fprintf (stderr, "unable to register (GFMRPC, GFMRPC_VERS_1, unix).\n");
            exit(1);
          }
	  printf("getfem interface server started\n");
        } else if (argc > 1 && atoi(argv[1])>0) {
          int sock;
          struct sockaddr_in addr;
          struct hostent *h;
          if ((sock = socket(AF_INET, SOCK_STREAM,0)) == -1) {
            fprintf(stderr, "can't create socket : %s", STR_LAST_ERROR); exit(1);
          }
          memset(&addr,0,sizeof(struct sockaddr_in));
          addr.sin_family = AF_INET;
          addr.sin_port = atoi(argv[1]);
          addr.sin_addr.s_addr = INADDR_ANY; 
          if (bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1) {
            close(sock);
            perror("bind"); exit(1);
          }
          transp = svctcp_create(RPC_ANYSOCK, 0, 0);
          if (transp == NULL) {
            fprintf (stderr, "cannot create tcp service.\n");
            exit(1);
          }
	  printf("getfem interface server is up and listenning on port %d - %d\n", transp->xp_port, addr.sin_port);

        } else {
          fprintf(stderr,"arguments:\n  %s -tcp : register a tcp service\n  %s -slave : register a local (unix socket) service\n", argv[0], argv[0]);
          exit(1);
        }
	svc_run ();
	fprintf (stderr, "svc_run returned");
	exit (1);
	/* NOTREACHED */
}
