/*
** pat_rpcnum.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:41:38 1999 
** Last update Thu Oct 28 20:19:41 1999 
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "mg.h"
#include <rpc/rpc.h>
#ifdef HAVE_RPC_RPCENT_H
# include <rpc/rpcent.h>
#endif
#include <rpc/pmap_prot.h>
#include <netdb.h>
#include "pat.h"
#include "pat_rpcnum.h"
#include "pat_32.h"

/* converts a string into a rpc number.
   It uses getservbyname(3) and reverts to atoi(3) if not found.
   Returns the rpc number */
int			rpcnum_from_str(str,resolve)
char			*str;		/* A service name or a number */
t_boolean		resolve;	/* If FALSE,bypasses getrpcbyname(3)*/
{
  if (resolve)
    {
      struct rpcent	*rpcentry;

      setrpcent(0);
      if (rpcentry = getrpcbyname(str))
	{
	  int		rpc;
	  
	  rpc = rpcentry->r_number;

	  endrpcent();
	  return (rpc);
	}
      endrpcent();
    }
  return (atoi(str));
}

/* converts-and-catenates a rpc number to a bridled string.
   It uses getservbyrpc(3) and reverts to long_to_str(3) if not found.
   Returns 0 if OK, might return various errors */
t_status		rpcnum_to_str(rpc,str,max_len,resolve)
int			rpc;		/* Rpc number */
char			*str;		/* Valid string */
int			max_len;	/* Maximum length */
t_boolean		resolve;      /* If FALSE, bypasses getrpcbynumber(3)*/
{
  if (resolve)
    {
      struct rpcent	*rpcentry;

      setrpcent(0);
      if (rpcentry = getrpcbynumber(rpc))
	{
	  char		*name;
	  
	  name = rpcentry->r_name;
	  endrpcent();
	  return (str_cat_str(str,max_len,name));
	}
      endrpcent();
    }
  return (ulong_to_str((unsigned long)rpc,
		       pat_base,
		       str,
		       max_len));
}

int	rpcnum_resolved_chan;

PAT_NAME_GENERIC(rpcnum_resolved_pat_name,
		 (VOID_PTR)&rpcnum_resolved_chan,
		 "rpcnum_resolved")

PAT_EXTRACT_DECL(rpcnum_resolved_pat_extract)
{
  t_u32		u32;
  t_status	status;
  
  if (len < sizeof (t_u32))
    return (ERR_PAT_TRUNC_FIELD);
  FBCOPY(buf,&u32,sizeof (t_u32));
  u32 = UNSAFE_NTOHL(u32);
  return (rpcnum_to_str(u32,
			str,
			max_len,
			pat_resolve));
}

PAT_INSERT_DECL(rpcnum_resolved_pat_insert)
{
  t_u32		u32;
  t_status	status;	
  int		rpc;
	
  if (len < sizeof (u32))
    return (ERR_PAT_TRUNC_FIELD);
  if ((rpc = rpcnum_from_str(value,
			     TRUE)) != 0)
    return (rpc);
  u32 = rpc;
  u32 = UNSAFE_HTONL(u32);
  FBCOPY(&u32,buf,sizeof (u32));
  return (0);
}

PAT_GET_CHOICES_DECL(rpcnum_resolved_pat_get_choices)
{
  struct rpcent	*rpcentry;
  t_status	status;

  setrpcent(0);
  while (rpcentry = getrpcent())
    {
      if ((status = vec_str_add(vec_str,
				rpcentry->r_name)) != 0)
	return (status);
    }
  endrpcent();
  return (0);
}

t_pat				rpcnum_resolved_pat = 
{
  rpcnum_resolved_pat_name,	/* t_pat_name_proc		*/
  NULL,				/* t_pat_off_proc		*/
  NULL,				/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  NULL,				/* t_pat_get_field_proc		*/
  NULL,				/* t_pat_set_field_proc		*/
  NULL,				/* t_pat_get_fields_proc	*/
  NULL,				/* t_pat_get_tmpl_proc		*/
  NULL,				/* t_pat_get_tmpl2_proc		*/
  NULL,				/* t_pat_has_opt_proc		*/
  NULL,				/* t_pat_adapt_len_proc		*/
  NULL,				/* t_pat_get_field_pat_proc	*/
  rpcnum_resolved_pat_extract,	/* t_pat_extract_proc		*/
  rpcnum_resolved_pat_insert,	/* t_pat_insert_proc		*/
  rpcnum_resolved_pat_get_choices,/* t_pat_get_choices_proc	*/
};
