/*
    YPS-0.2, NIS-Server for Linux
    Copyright (C) 1994  Tobias Reber

    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 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
static char rcsid[]="@(#)$Id: ypwhich.c,v 1.6 1994/01/02 22:09:45 root Exp $";
/*
 *	$Author: root $
 *	$Log: ypwhich.c,v $
 * Revision 1.6  1994/01/02  22:09:45  root
 * Added strict prototypes
 *
 * Revision 1.5  1994/01/02  20:08:15  root
 * Added GPL notice
 *
 * Revision 1.4  1993/12/31  18:09:11  root
 * Use ypclnt from libc
 *
 * Revision 1.3  1993/06/12  10:37:23  root
 * Align with include-4.4
 *
 * Revision 1.2  1993/06/11  21:30:24  root
 * Initial revision
 *
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <rpc/rpc.h>
#include <netdb.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <arpa/inet.h>
#include "yp_xlate.h"

typedef char *domainname;
#ifdef YP_LIBC
typedef struct ypmaplist ypmaplist;
#else
typedef struct _ypmaplist {
	char *ypml_name;
	struct _ypmaplist *ypml_next;
} ypmaplist;
#endif

extern _yp_maplist(char *, ypmaplist **);

static bool_t
getBinding(domainname *domain)
{
   struct ypbind_resp ypbind;
   int rpcstat;
   CLIENT *udpClient;
   struct sockaddr_in ServerAddress;
   struct sockaddr_in localHost;
   struct timeval tout;
   int s;
 
   memset(&localHost, '\0', sizeof localHost);
   localHost.sin_family=AF_INET;
   localHost.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
   tout.tv_sec=25; tout.tv_usec=0;
   s=RPC_ANYSOCK;

   udpClient=clntudp_create(&localHost, YPBINDPROG, YPBINDVERS, tout, &s);
   if (udpClient==NULL) {
      clnt_pcreateerror("udpClient");
      return FALSE;
   }

   tout.tv_sec=5; tout.tv_usec=0;
#ifdef YP_LIBC
   rpcstat=clnt_call(udpClient, YPBINDPROC_DOMAIN, xdr_domainname, *domain,
      xdr_ypbind_resp, &ypbind, tout);
#else
   rpcstat=clnt_call(udpClient, YPBINDPROC_DOMAIN, xdr_domainname, domain,
      xdr_ypbind_resp, &ypbind, tout);
#endif
   if (rpcstat!=RPC_SUCCESS) {
      clnt_perror(udpClient, "clnt_call");
      return FALSE;
   }

   switch (ypbind.ypbind_status) {
   case YPBIND_SUCC_VAL:
      bzero(&ServerAddress, sizeof(ServerAddress));
      ServerAddress.sin_family=AF_INET;
      bcopy(&ypbind.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr,
	 &ServerAddress.sin_addr.s_addr,4);
      ServerAddress.sin_port=ypbind.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port;
      {
	 struct hostent *h=gethostbyaddr((char *)&ServerAddress.sin_addr,
            sizeof (ServerAddress.sin_addr), ServerAddress.sin_family);
	 if (h) {
	    printf("%s\n", h->h_name);
	 } else {
    	    printf("[%s]\n", inet_ntoa(ServerAddress.sin_addr));
	 }
      }
      return TRUE;
   case YPBIND_FAIL_VAL:
      switch(ypbind.ypbind_respbody.ypbind_error) {
      case YPBIND_ERR_ERR:
         fprintf(stderr, "YPBIND: Internal error\n");
         return FALSE;
      case YPBIND_ERR_NOSERV:
         fprintf(stderr, "YPBIND: No bound server for passed domain\n");
         return FALSE;
      case YPBIND_ERR_RESC:
         fprintf(stderr, "YPBIND: System resource allocation failure\n");
         return FALSE;
      default:
         return FALSE;
      }
   default:
      fprintf(stderr, "Unknown status %x\n",ypbind.ypbind_status);
      return FALSE;
   }
}

static bool_t
getMaster(char *domain, char *map) 
{
   char *mastername;
   int y;

   if ((y=yp_master(domain, map, &mastername))) {
      fprintf(stderr, "%s: %s\n", map, yperr_string(y));
      return FALSE;
   }
   printf("%s %s\n", map, mastername);
   return TRUE;
}
 
static bool_t
getMaplist(char *domain)
{
   int y;
   ypmaplist *maplist, *m;

   if ((y=_yp_maplist(domain, &maplist))) {
      fprintf(stderr, "%s: %s\n", domain, yperr_string(y));
      return FALSE;
   }
   for (m=maplist; m; m=m->ypml_next) {
      getMaster(domain, m->ypml_name);
   }
   return TRUE;
}
   
void
main(int argc, char **argv)
{
   domainname domain;
   int firstMap=0, lastMap=0;
   int i;
   char c;
   int TranslateMaps=TRUE;

   yp_get_default_domain(&domain);

   while((c=getopt(argc, argv, "d:mxt"))!=EOF) {
      extern char *optarg;
      extern int optind;

      switch(c) {
      case 'x':
         for(i=0; ypXlateFrom[i]; i++) 
            fprintf(stderr, "Use \"%s\" for map \"%s\"\n", ypXlateFrom[i],
               ypXlateTo[i]);
         exit(0);
      case 't':
         TranslateMaps=FALSE;
         break;
      case 'd':
         domain=optarg;
         break;
      case 'm':
         firstMap=optind;
         while (argv[optind]&&*argv[optind]!='-') optind++;
         lastMap=optind-1;
         break;
      }
   }
 
   if (firstMap && firstMap<=lastMap)
      for (; firstMap<=lastMap; firstMap++) {
         char *mapName=argv[firstMap];
         if (TranslateMaps)
            for(i=0; ypXlateFrom[i]; i++) {
               if (strcmp(mapName, ypXlateFrom[i])) continue;
                  mapName=ypXlateTo[i];
            }
         getMaster(domain, mapName);
      }
   else if (firstMap)
      getMaplist(domain);
   else {
      getBinding(&domain);
   }
}
