/*
 * 
 * nfs_world_export
 *
 * This plugin was written by Renaud Deraison and is released
 * under the GPL
 *
 */
/*
 * 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.
 
 
 	
 */


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

#if HAVE_RPC_RPC_H
#include <rpc/rpc.h>
#endif


#include "mount.h"




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 showmount(char *hostname, char **result)
{
 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;

 char * tmp = malloc(4096);


 if (hostname[0] >= '0' && hostname[0] <= '9')
 {
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = inet_addr(hostname);
 }
 else
 {
  if ((hp = gethostbyname(hostname)) == NULL)
  {
   return(-1);
  }
  server_addr.sin_family = AF_INET;
  memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
 }

 /* 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, &exportlist,
  total_timeout);

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

 sprintf(tmp, "Export list for %s:\n", hostname);
 maxlen = 0;
 for (exl = exportlist; exl; exl = exl->ex_next)
  if ((n = strlen(exl->ex_dir)) > maxlen)
   maxlen = n;

 while (exportlist)
 {
  sprintf(tmp, "%s%-*s ", tmp, maxlen, exportlist->ex_dir);
  grouplist = exportlist->ex_groups;
  if (grouplist)
   while (grouplist)
   {
    sprintf(tmp, "%s%s%s", tmp, grouplist->gr_name, grouplist->gr_next ? " , " : "");
    grouplist = grouplist->gr_next;
   }
  else
   sprintf(tmp, "%s(everyone)", tmp);
  sprintf(tmp, "%s\n", tmp);
  exportlist = exportlist->ex_next;
 }

 *result = malloc(strlen(tmp)+1);
 strncpy(*result, tmp, strlen(tmp));
 free(tmp);

 return(0);
}
