/*
 * This file is part of an snmp query application.
 * This file contains routines that manage the list of hosts to be polled.
 *
 * Copyright 1990 by the Massachusetts Institute of Technology.
 *
 * For copying and distribution information, please see the file
 * <mit-copyright.h>.
 *
 * Tom Coppeto
 * MIT Network Services
 * 15 April 1990
 *
 *    $Source: /afs/net.mit.edu/tools/src/simon/RCS/agent.c,v $
 *    $Author: tom $
 *    $Locker:  $
 *    $Log:	agent.c,v $
 * Revision 1.6  91/02/25  13:36:22  tom
 * fixed yet another addr resolv problem
 * 
 * Revision 1.5  91/02/21  13:52:45  tom
 * changed array to link list
 * 
 * Revision 1.4  90/07/25  21:52:23  tom
 * suppress compiler warning
 * 
 * Revision 1.3  90/07/25  10:26:42  tom
 * prints a warning is address isn't defined in name service, but allows
 * it to be added 
 * 
 * Revision 1.2  90/07/24  11:14:18  tom
 * allow ip addrs
 * 
 * Revision 1.1  90/07/20  21:17:15  tom
 * Initial revision
 * 
 *
 */

#ifndef lint
static char *rcsid = "$Header: /afs/net.mit.edu/tools/src/simon/RCS/agent.c,v 1.6 91/02/25 13:36:22 tom Exp $";
#endif


#include <simon.h>
#include <sys/socket.h>
#include <mit-copyright.h>


/*
 * callbacks
 */


/*
 * Function:    cmd_change_agent()
 * Description: cmd_change_agent <new_agent> <old_agent>
 *              (arguments optional)
 *              Swaps new_agent for old_agent in list.
 */

void
cmd_change_agent(argc, argv)     
     int argc;
     char *argv[];
{
  CLUSTER *cluster;
  char    old[HOST_SIZE];
  char    new[HOST_SIZE];
  int     status;

  pname = argv[0];
  bzero(old, sizeof(old));
  bzero(new, sizeof(new));
  cluster = stuff.cluster;

  while (*++argv)
    {
      if(**argv != '-')
	{
	  if(*old == '\0')
	    {      
	      strncpy(old, *argv, sizeof(old));
	      continue;
	    }
	  else
	    if(*new == '\0')
	      {
		strncpy(new, *argv, sizeof(new));
		continue;
	      }
	    else
	      fprintf(stderr, "Too many agents specified on command line.\n");
	}
      else	
	if(strcmp(*argv, "-help") != 0)
	  fprintf(stderr, "Unknown option \"%s\".\n", *argv);

      printf("usage: %s [<old agent> <new agent>]\n", pname);
      return;
    }

  if(*new == '\0')
    {
      strcpy(new, old);
      *old = '\0';
    }

  if(!ClusterList)
    {
      printf("...but there are no clusters defined!\n");
      return;
    }
  
  if(!cluster)
    if(!(cluster = prompt_for_cluster("in cluster: ", NULL)))
      {
	printf("command aborted.\n");
	return;
      }

  if(!*old && cluster->agents && cluster->agents->next)
    {
      get_prompted_input("agent to remove: ", old, sizeof(old));
      if(!*old)
	{
	  printf("OK, nothing changed.\n");
	  return;
	}
    }
  else
    if(cluster->agents)
      strncpy(old, cluster->agents->name, sizeof(old));
  
  if(*new == '\0')
    {
      get_prompted_input("agent to add: ", new, sizeof(new));
      if(*new == '\0')
	{
	  printf("OK, nothing changed.\n");
	  return;
	}
    }

  if(is_agent(cluster->agents, new))
    {
      fprintf(stderr, "%s is already in the list of agents.\n", new);
      fprintf(stderr, "No action taken.\n");
      return;
    }

  if(*old) 
    {
      cluster->agents = delete_agent(cluster->agents, old, &status);
      if(status != SUCCESS)
	{
	  fprintf(stderr, "%s is not in the agent list.\n", old);
	  return;
	}
    }

  cluster->agents = add_agent(cluster->agents, new, &status);
  if(status != SUCCESS)
    {
      fprintf(stderr, "Unable to add %s to agent list.\n", new);
      return;
    }

  if(*old)
    printf("%s replaced %s in %s.\n", new, old, cluster->name);
  else
    printf("Current agent is %s.\n", new);

  return;
}



/*
 * Function:    cmd_add_agent()
 * Description: cmd_add_agent <new_agent>
 *              (arguments optional)
 *              adds new_agent to list.
 */

void 
cmd_add_agent(argc, argv)
     int argc;
     char *argv[];
{
  CLUSTER *cluster;
  int     status;
  int     i = 0;
  int     n, j;

  pname = argv[0];
  cluster = stuff.cluster;

  while(*++argv)
    {
      if(**argv != '-')
	{
	  argptr[i++] = *argv;
	  argptr[i]   = (char *) NULL;
	  continue;
	}
      else
	if(strcmp(*argv, "-help") != 0)
	  fprintf(stderr, "Unknown option \"%s\".\n", *argv);

      printf("usage: %s [<new agents>]\n", pname);
      return;
    }
  
  if(!ClusterList)
    {
      printf("...but there are no clusters defined!\n");
      return;
    }

  if(!cluster)
    if(!(cluster = prompt_for_cluster("to cluster: ", NULL)))
      {
	printf("command aborted.\n");
	return;
      }

  if(i == 0)
    {
      bzero(cmdbuf, sizeof(cmdbuf));
      get_prompted_input("agent to add: ", cmdbuf, sizeof(cmdbuf));
      if(strlen(cmdbuf) < 1)
	{
	  printf("OK, nothing changed.\n");
	  return;
	}
      argptr[i++] = cmdbuf;
      argptr[i]   = (char *) NULL;
    }

  for(j = 0; j < i; j++)
    {
      if(is_agent(cluster->agents, argptr[j]))
	{
	  fprintf(stderr, "%s is already in the list of agents.\n", argptr[j]);
	  return;
	}

      status = ERROR;
      while(status != SUCCESS)
	{
	  cluster->agents = add_agent(cluster->agents, argptr[j], &status);
	  if(status != SUCCESS)
	    {
	      fprintf(stderr, "Unable to add %s to agent list. Try again.\n", 
		      argptr[j]);
	      bzero(cmdbuf, sizeof(cmdbuf));
	      get_prompted_input("agent to add: ", cmdbuf, sizeof(cmdbuf));
	      if(strlen(cmdbuf) < 1)
		{
		  if(i < 1)
		    {
		      printf("OK, nothing changed.\n");
		      return;
		    }
		  else
		    printf("continuing...\n");
		}
	      argptr[j] = cmdbuf;
	    }      
	}
      printf("%s is now the %d%s agent in %s.\n", argptr[j], n+1, 
	     numeric_suffix(n+1), cluster->name);
    }
  return;
}



/*
 * Function:    cmd_delete_agent()
 * Description: cmd_delete_agent <agent>
 *              (arguments optional)
 *              deletes agent from list.
 */

void 
cmd_delete_agent(argc, argv)
     int argc;
     char *argv[];
{
  CLUSTER *cluster;
  int     status;
  int     i = 0;
  int     j;

  pname = argv[0];
  cluster = stuff.cluster;

  while (*++argv)
    {
      if(**argv != '-')
	{
	  argptr[i++] = *argv;
	  argptr[i]   = (char *) NULL;
	  continue;
	}
      else
	if(strcmp(*argv, "-help") != 0)
	  fprintf(stderr, "Unknown option \"%s\".\n", *argv);

      printf("usage: %s [<old agents>]\n", pname);
      return;
    }
   
  if(!ClusterList)
    {
      printf("...but there are no clusters defined!\n");
      return;
    }

  
  if(!cluster)
    if(!(cluster = prompt_for_cluster("from cluster: ", NULL)) )
      {
	printf("command aborted.\n");
	return;
      }

  if(i == 0)
    {
      bzero(cmdbuf, sizeof(cmdbuf));
      get_prompted_input("agent to remove: ", cmdbuf, sizeof(cmdbuf));
      if(strlen(cmdbuf) < 1)
	{
	  printf("OK, nothing changed.\n");
	  return;
	}
      argptr[i++] = cmdbuf;
      argptr[i]   = (char *) NULL;
    }

  for(j = 0; j < i; j++)
    {
      if(is_agent(cluster->agents, argptr[j]) == FALSE)
	{
	  fprintf(stderr, "%s not in the \"%s\" agent list.\n", 
		  cluster->name, argptr[j]);
	  return;
	}

      status = ERROR;
      while(status != SUCCESS)
	{
	  cluster->agents = delete_agent(cluster->agents, argptr[j], &status);
	  if(status != SUCCESS)
	    {
	      fprintf(stderr, "%s is not a known agent. Try again.\n", 
		      argptr[j]);
	      bzero(cmdbuf, sizeof(cmdbuf));
	      get_prompted_input("agent to remove: ", cmdbuf, sizeof(cmdbuf));
	      if(strlen(cmdbuf) < 1)
		{
		  if(i > 1)
		    {
		      printf("Request cancelled.\n");
		      return;
		    }
		  else
		    printf("ok, continuing...\n");
		}
	      argptr[j] = cmdbuf;
	    }
	}
      printf("%s deleted.\n", argptr[j]);      
    }
  return;
}

    


/*
 * utilities
 */



int
make_agent(cluster, agent)
     CLUSTER *cluster;
     char    *agent;
{
  char  buf[NAME_SIZE];
  int   status; 
 
  if(cluster == (CLUSTER *) NULL)
    return(ERROR);

  *buf = '\0';
  if(agent == (char *) NULL)
    agent = &buf[0];

  do
    {
      if(*agent == '\0')
	{
	  get_prompted_input("hostname: ", agent, NAME_SIZE);
	  if(*agent == '\0')
	    return(ERROR);
	}      
      cluster->agents = add_agent(cluster->agents, agent, &status);
      if(status == UNKNOWN)
	agent = &buf[0];
      *agent  = '\0';
    } 
  while (status == UNKNOWN);

  return(status);
}





/*
 * Function:    add_agent()
 * Description: 
 */

AGENT *
add_agent(list, agent, status)
     AGENT *list;
     char  *agent;
     int   *status;
{
  AGENT *a;
  AGENT *last;
  unsigned long addr  = 0;
  struct hostent *hp = (struct hostent *) NULL;
  int n;

  if(is_agent(list, agent))
    list = delete_agent(list, agent, &n);

  if((*agent >= '0') && (*agent <= '9'))
    {
       addr = inet_addr(agent);
       if(addr > 0)
	 {
	   hp = gethostbyaddr((char *) &addr, 4, AF_INET);
	   if(!hp)
	     printf("warning: cannot resolve address %s.\n", agent);
	 }
    }
  
  if(!hp)
    {
      hp = gethostbyname(agent);
      if(!hp && !addr)
	{
	  fprintf(stderr, "Cannot resolve name of agent, %s.\n", agent);
	  *status = UNKNOWN;
	  return(list);
	}
      else
	if(hp)
	  addr = 0;
    }
  
  if(!(a = (AGENT *) malloc(sizeof(AGENT))))
    {
      perror("add_agent");
      *status = ERROR;
      return(list);
    }

  bzero(a, sizeof(AGENT));
  strncpy(a->name, agent, sizeof(a->name));
  if(addr > 0)
    a->in.s_addr = addr;
  else
    bcopy(hp->h_addr, &(a->in.s_addr), hp->h_length);

  if(!list)
    list = a;
  else
    {
      last = list;
      while(last->next)
	last = last->next;
      last->next = a;
    }
  *status = SUCCESS;
  return(list);
}

 

/*
 * Function:    delete_agent()
 * Description: 
 */

AGENT *
delete_agent(list, agent, status)
     AGENT *list;
     char  *agent;
     int   *status;
{
  AGENT *a;
  AGENT *s;

  if(!list)
    {
      *status = ERROR;
      return(list);
    }

  a = list;
  s = (AGENT *) NULL;
  while(a)
    {
      if(strncmp(a->name, agent, sizeof(a->name)) == 0)
	{
	  if(s)
	    s->next = a->next;
	  else 
	    list = a->next;

	  (void) free(a);
	  *status = SUCCESS;
	  return(list);
	}
      s = a;
      a = a->next;
    }
  *status = ERROR;
  return(list);
}




/*
 * Function:    is_agent()
 * Description: 
 */

int
is_agent(list, agent)
     AGENT *list;
     char  *agent;
{
  AGENT *a;
  int i = 0;
  
  a = list;
  while(a)
    if(strcmp(agent, a->name) == 0)
      return(TRUE);
    else
      a = a->next;

  return(FALSE);
} 



