/* Hostloop -- the Hostloop Library
 * Copyright (C) 1998 Renaud Deraison
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */   


/*
 * showmount.c -- show mount information for an NFS server
 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
 *
 * 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, 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.
 *
 * This file was modified by Renaud Deraison <deraison@worldnet.fr> for
 * the hostloop library. 
 */


#ifdef TRUE
#undef TRUE
#undef FALSE
#endif
#include <includes.h>

#ifndef NESSUSNT
#ifdef HAVE_RPC_RPC_H
#include <rpc/rpc.h>
#endif



#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif

#include "mount.h"
#include "hosts_loop.h"




char * complete_hostname(char *, char *);
bool_t xdr_fhandle(XDR *xdrs, fhandle objp)
{
 if (!xdr_opaque(xdrs, objp, FHSIZE))return (FALSE);
 else return (TRUE);
}

bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp)
{
 if (!xdr_u_int(xdrs, &objp->fhs_status))return (FALSE);
 if(!objp->fhs_status && 
 !xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle))return (FALSE);
 else return (TRUE);
}

bool_t xdr_dirpath(XDR *xdrs, dirpath *objp)
{
 if (!xdr_string(xdrs, objp, MNTPATHLEN))return (FALSE);
 else return (TRUE);
}

bool_t xdr_name(XDR *xdrs, name *objp)
{
 if (!xdr_string(xdrs, objp, MNTNAMLEN))return (FALSE);
 else return (TRUE);
}

bool_t xdr_mountlist(XDR *xdrs, mountlist *objp)
{
 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody))
  return (FALSE);
 else return (TRUE);
}

bool_t xdr_mountbody(XDR *xdrs, mountbody *objp)
{
 if (!xdr_name(xdrs, &objp->ml_hostname) ||
     !xdr_dirpath(xdrs,(dirpath *)(&objp->ml_directory)) ||
     !xdr_mountlist(xdrs, (mountlist *)objp->ml_next))
  return (FALSE);
 else
  return (TRUE);
}

bool_t xdr_groups(XDR *xdrs, groups *objp)
{
 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode))
  return (FALSE);
 else return (TRUE);
}

bool_t xdr_groupnode(XDR *xdrs, groupnode *objp)
{
 if (!xdr_name(xdrs, &objp->gr_name) || !xdr_groups(xdrs, &objp->gr_next))
  return(FALSE);
 else return (TRUE);
}

bool_t xdr_exports(XDR *xdrs, exports *objp)
{
 if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode))
  return (FALSE);
 else return (TRUE);
}

bool_t xdr_exportnode(XDR *xdrs, exportnode *objp)
{
 if (!xdr_dirpath(xdrs, &objp->ex_dir) || 
   !xdr_groups(xdrs, &objp->ex_groups) ||
   !xdr_exports(xdrs, &objp->ex_next))return (FALSE);
 else return (TRUE);
}

#define MAXHOSTLEN 256

int dump_cmp(char **p, char **q)
{
 return strcmp(*p, *q);
}

int get_showmount_trusted(char * hostname, struct hostlist_t ** hostlist)
{
 enum clnt_stat clnt_stat;
 struct hostent *hp;
 struct sockaddr_in server_addr;
 int msock;
 struct timeval total_timeout;
 struct timeval pertry_timeout;
 CLIENT *mclient;
 groups grouplist;
 exports exportlist, exl;
 int n;
 int maxlen;
 struct hostlist_t * orig = *hostlist;


 if (hostname[0] >= '0' && hostname[0] <= '9')
 {
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = inet_addr(hostname);
 }
 else
 {
#ifdef USE_PTHREADS
  struct hostent * res = malloc(sizeof(struct hostent));
  char * buf = malloc(4096);
  int h_err;
  
  hp = NULL;
  bzero(res, sizeof(struct hostent));
  bzero(buf, 4096);
  gethostbyname_r(hostname, res, buf, 4096, &hp, &h_err);
#else
  hp = gethostbyname(hostname);
#endif
  if (!hp)
  {
   fprintf(stderr, "Hostloop> Showmount: can't get address for %s\n", hostname);
   return(-1);
  }
  server_addr.sin_family = AF_INET;
  memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
#ifdef USE_PTHREADS
  free(res);
  free(buf);
#endif
 }

 /* create mount deamon client */

 server_addr.sin_port = 0;
 msock = RPC_ANYSOCK;
 if ((mclient = clnttcp_create(&server_addr,  MOUNTPROG, MOUNTVERS, &msock, 0, 0)) ==
 NULL)
 {
  server_addr.sin_port = 0;
  msock = RPC_ANYSOCK;
  pertry_timeout.tv_sec = 3;
  pertry_timeout.tv_usec = 0;
  if ((mclient = clntudp_create(&server_addr, MOUNTPROG, MOUNTVERS, pertry_timeout,
  &msock)) == NULL)
   return(-2);
 }
 mclient->cl_auth = authunix_create_default();
 total_timeout.tv_sec = 5;
 total_timeout.tv_usec = 0;

 memset(&exportlist, '\0', sizeof(exportlist));
 clnt_stat = clnt_call(mclient, MOUNTPROC_EXPORT,
  (xdrproc_t) xdr_void, NULL,
  (xdrproc_t) xdr_exports, (void *)&exportlist,
  total_timeout);

 if (clnt_stat != RPC_SUCCESS)
 {
 #ifndef XWIN_ENABLED
  /* clnt_perror(mclient, "rpc mount export"); */
 #endif
  return(-1);
 }

 maxlen = 0;
 for (exl = exportlist; exl; exl = exl->ex_next)
  if ((n = strlen(exl->ex_dir)) > maxlen)
   maxlen = n;
 
 while (exportlist)
 {
  grouplist = exportlist->ex_groups;
  if (grouplist)
   while (grouplist)
   {
   struct in_addr ia_tmp;
   int good=0;
   
   
   ia_tmp = nn_resolve(grouplist->gr_name);
   
   if(ia_tmp.s_addr != INADDR_NONE)good=1;
  
   else {
   	char * tmp;
   	ia_tmp = nn_resolve((tmp = complete_hostname(grouplist->gr_name, hostname)));
   	if(ia_tmp.s_addr != INADDR_NONE)
   		{
   		good = 1;
   		free(grouplist->gr_name);
   		grouplist->gr_name = tmp;
   		}
   	}
   	
   	if(good)
  	{
   	(*hostlist)->hostname = malloc(strlen(grouplist->gr_name)+1);
   	strncpy((*hostlist)->hostname, grouplist->gr_name, strlen(grouplist->gr_name));
   	grouplist = grouplist->gr_next;
   	(*hostlist)->hostip = ia_tmp;
   	(*hostlist)->next = (struct hostlist_t *)malloc(sizeof(struct hostlist_t));
   	(*hostlist) = (*hostlist)->next;
   	}
   else grouplist = grouplist->gr_next;
   }
  exportlist = exportlist->ex_next;
 }
  *hostlist = orig;
  return(0);
}

#endif
