/*
 * Port. This file contains the callbacks from the command line parser.
 *
 * Copyright 1992 by the Massachusetts Institute of Technology.
 *
 * For copying and distribution information, please see the file
 * <mit-copyright.h>.
 *
 * Tom Coppeto
 * MIT Network Operations
 * 26 January 1992
 *
 *    $Source: /afs/.net/tools/src/port/RCS/commands.c,v $
 *    $Author: nocuser $
 *    $Locker: tom $
 * 
 */

#ifndef lint
static char *rcsid = "$Header: /afs/.net/tools/src/port/RCS/commands.c,v 1.12 1994/06/21 15:44:30 nocuser Exp tom $";
#endif

#include "port.h"
#include <mit-copyright.h>
extern getreq reply;


void
cmd_change_community(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  int i = 0;
  Agent a;
  struct hostent *hp;
  unsigned long laddr;
  char *name = (char *) NULL;
  char nbuf[32];
  char cbuf[32];
  char tbuf[32];
  caddr_t *dat;
  caddr_t datt;
  objident *obj[10];
  int type = 0;
  int op = 0;
  int o;

  prog = *argv;
  bzero(&a, sizeof(a));

  if(strcmp(*argv, "lscom") == 0)
    op = 1;

  while(*++argv)
    {
      if(string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<agent>]\n", prog);
	  return;
	}
      
      if(!name)
	name = *argv;
      else
	{
	  printf("too many agents specified.\n");
	  return;
	}
    }

  if(!name)
    {
      if(get_prompted_input("agent", "", nbuf, sizeof(nbuf)) < 0)
	return;
      if(!*nbuf)
	return;
      name = nbuf;
    }
  
  if(!(hp = gethostbyname(name)))
    if((laddr = inet_addr(name)) > 0)
      hp = gethostbyaddr((char *) &laddr, 4, AF_INET);

  if(!hp)
    {      
      fprintf(stderr, "cannot resolve name of agent, %s.\n", name);
      return;
    }	  

  strcpy(a.alias, name);
  strcpy(a.name, hp->h_name);
  upcase(a.name);
  bcopy(hp->h_addr, &(a.addr.s_addr), hp->h_length);
  strcpy(a.saddr, inet_ntoa(a.addr));

  obj[0]   = &vSysDescr;
  datt = make_snmp_query(&a, obj[0]);
  if(!datt)
    {
      printf("no response from %s. unable to continue.\n",
	     a.name);
      if(reply.errstat)
	printf("check current community.\n");
      return;
    }
  else
    printf("%s\n\n", datt);

  o = 0;
  obj[o++] = &vCommunityName;
  obj[o++] = &vCommunityType;
  obj[o++] = (objident *) NULL;

  vCommunityName.cmp[vCommunityName.ncmp - 1] = 0;  
  vCommunityType.cmp[vCommunityType.ncmp - 1] = 0;
  vCommunityName.ncmp--;
  vCommunityType.ncmp--;
  datt = make_snmp_next(&a, obj[0]);
  vCommunityName.ncmp++;
  vCommunityType.ncmp++;
  if(!datt)
    {
      printf("no response from %s. unable to continue.\n",
	     a.name);
      if(reply.errstat)
	printf("check current community.\n");
      return;
    }

  while(datt)
    {
      if(oidncmp(obj[0], &(reply.varlist.elem[0].name), 12) != 0)
	break;
      i = reply.varlist.elem[0].name.cmp[reply.varlist.elem[0].name.ncmp-1];
      vCommunityName.cmp[vCommunityName.ncmp - 1] = i;  
      vCommunityType.cmp[vCommunityType.ncmp - 1] = i;
      if(!(dat = make_lots_o_snmp_queries(&a, obj)))
	{
	  printf("unable to retrieve current community names.\n");
	  return;
	}

      bcopy(dat[1], &type, sizeof(type));
      sprintf(tbuf, "%s", type == INACTIVE ? "inactive" : 
	      type == READONLY  ? "ro" :
	      type == READWRITE ? "rw" :
	      type == SUPERUSER ? "su" : "unknown");
      
      if(!op)
	{
	  printf("%2d. \n", i);      
	  get_prompted_input("    type", tbuf, cbuf, sizeof(cbuf));
	  if(strcmp(cbuf, "ro") ==  0)
	    type = READONLY;
	  else
	    if(strcmp(cbuf, "rw") ==  0)
	      type = READWRITE;
	  else
	    if(strcmp(cbuf, "su") ==  0)
	      type = SUPERUSER;
	    else
	      type = INACTIVE;
	  
	  get_prompted_input("    name", dat[0], cbuf, sizeof(cbuf));
  
	  if((make_snmp_set(&a, obj[1], &type, INT, 0) != SUCCESS) ||
	     reply.errstat != 0)
	    {
	      printf("error during read only community type set.\n");
	      return;
	    }

	  if((make_snmp_set(&a, obj[0], cbuf, STR, 0) == SUCCESS) &&
	     reply.errstat == 0)
	    printf("read only community set successful.\n");
	  else
	    {
	      printf("error during read only community set.\n");
	      return;
	    }
	}
      else
	printf("%2d.   %-8s  %s\n", i, tbuf, dat[0]);
      
      if(!(datt = make_snmp_next(&a, obj[0])))
	{
	  printf("no response from %s.. unable to continue.\n",
		 a.name);
	  return;
	}
    }
  return;
}



void
cmd_display(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  int i = 0;
  Agent a[50];
  Agent *ap[50];
  Agent **alist;
  struct hostent *hp;
  unsigned long laddr;
  char *name[50];
  int board = 0;
  char nbuf[32];
  int list = 0;
  int j;

  *name = (char *) NULL;
  prog = *argv;
  bzero(a, sizeof(a));

  while(*++argv)
    {
      if(string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<agent>] [-board <board>] [-key <list>]\n", prog);
	  return;
	}
      
      if(string_equiv(*argv, "-key", 2))
	{
	  if(!*++argv)
	    {
	      printf("usage: %s [<agent>] [-board <board>] [-key <list>]\n",
		     prog);
	      return;
	    }
	  if(alist = (Agent **) get_agents(*argv))
	    {
	      display_agents(alist);
	      free_agents(alist);
	    }
	  return;
	}

      if(string_equiv(*argv, "-board", 2))
	{
	  if(!*++argv)
	    {
	      printf("board number must follow -board option.\n");
	      return;
	    }
	  board = atoi(*argv);
	  if(board < 1)
	    {
	      printf("board number must be greater than zero.\n");
	      return;
	    }
	  continue;
	} 
      
      name[i++] = *argv;
      if(i == 50)
	break;
    }

  if(!name[0])
    {
      if(get_prompted_input("agent", "", nbuf, sizeof(nbuf)) < 0)
	return;
      if(!*nbuf)
	return;
      name[0] = nbuf;
      i = 1;
    }
  
  for(j = 0; j < i; j++)
    {
      if(!(hp = gethostbyname(name[j])))
	{
          if(!isdigit(name[j][0]))
            {
               fprintf(stderr, "cannot resolve name of agent, %s.\n", name[j]);
               return;
            }
	  if((laddr = inet_addr(name[j])) > 0)
	    {
	      if(!(hp = gethostbyaddr((char *) &laddr, 4, AF_INET)))
		{
		  fprintf(stderr, 
			  "warning: cannot resolve name of agent, %s.\n", 
			  name[j]);
		  a[j].addr.s_addr = laddr;
		}
	    }
	  else
	    {
	      fprintf(stderr, "cannot resolve name of agent, %s.\n", name[j]);
	      return;
	    }
	}
      else
	{
	  bcopy(hp->h_addr, &(a[j].addr.s_addr), hp->h_length);
	  strcpy(a[j].name, hp->h_name);
	}
      strcpy(a[j].alias, name[j]);      
      upcase(a[j].name);
      strcpy(a[j].saddr, inet_ntoa(a[j].addr));
      ap[j] = &a[j];
    }

  if(i > 1)
    display_agents(ap);
  else
    if(board < 1)
      display_boards(a);
    else 
      display_ports(a, board);
}



void
cmd_reset(argc, argv)
     int argc;
     char **argv;
{
  Agent a;
  struct hostent *hp;
  unsigned long laddr;
  char *name = (char *) NULL;
  char nbuf[32];
  char *prog;

  prog = *argv;
  bzero(&a, sizeof(a));

  while(*++argv)
    {
      if(string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<agent>]\n", prog);
	  return;
	}
      
      name = *argv;
    }

  if(!name)
    {
      if(get_prompted_input("agent", "", nbuf, sizeof(nbuf)) < 0)
	return;
      if(!*nbuf)
	return;
      name = nbuf;
    }
  
  if(!(hp = gethostbyname(name)))
    if((laddr = inet_addr(name)) > 0)
      if(!(hp = gethostbyaddr((char *) &laddr, 4, AF_INET)))
	{
	  fprintf(stderr, "cannot resolve name of agent, %s.\n", name);
	  return;
	}	

  strcpy(a.alias, name);
  strcpy(a.name, hp->h_name);
  upcase(a.name);
  bcopy(hp->h_addr, &(a.addr.s_addr), hp->h_length);
  strcpy(a.saddr, inet_ntoa(a.addr));

  printf("sneding... ");
  fflush(stdout);
  if(restart_agent(&a) == SUCCESS)
    printf(" done.\n");  
}
  


restart_agent(agent)
     Agent *agent;
{
  int state;

  determine_vendor(agent);
  state = DEVICE_RESTART[agent->vendor];

  if(make_snmp_set(agent, &vDeviceRestart[agent->vendor], &state, INT, 1)
     ==  SUCCESS)
    return(SUCCESS);
  else
    return(ERROR);
}

void
cmd_set_timeout(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  int u = 0;

  prog = *argv;
  if(argc == 1)
    {
      printf("Time out is set to %d second%s. \n", the_timeout,
	     the_timeout > 1 ? "s" : "");
      return;
    }

  while(*++argv)
    {
      if(u || string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<seconds>]\n", prog);
	  return;
	}

      if(isnumber(*argv))
	u = atoi(*argv);
      else
	{
	  fprintf(stderr, "%s needs to be a number!\n");
	  printf("usage: %s [<seconds>]\n", prog);
	  return;
	}
    }
  
  if(u <= 0)
    fprintf(stderr, "timeout needs to be greater than zero.\n");
      
  while(u <= 0)
    u = input_number("timeout: ", 0);
  
  the_timeout = u;
  return;
}



void
cmd_set_agent(argc, argv)
     int argc;
     char **argv;
{

}



void
cmd_set_burst(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  int u = 0;

  prog = *argv;
  if(argc == 1)
    {
      printf("Burst count is set to %d packet%s. Please make a note of it.\n",
	     the_burst, the_burst > 1 ? "s" : "");
      return;
    }

  while(*++argv)
    {
      if(u || string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<packets>]\n", prog);
	  return;
	}

      if(isnumber(*argv))
	u = atoi(*argv);
      else
	{
	  fprintf(stderr, "%s needs to be a number!\n");
	  printf("usage: %s [<packets>]\n", prog);
	  return;
	}
    }
  
  if(u <= 0)
    fprintf(stderr, "burst count needs to be greater than zero.\n");
      
  while(u <= 0)
    u = input_number("burst: ", 0);
  
  if(u > 1000)
    {
      if(the_burst <= 1000)
	printf("aren't we getting a bit carried away?\n");
      return;
    }
  if((u > 100) && (the_burst < 100))
    printf("nuke `em!\n");
  else
    if((u >= 50) && (the_burst < 50))
      printf("\n");
    else
      if((u > 30) && (the_burst < 30))
	printf("over there! ....  over there!\n");
      else
	if((u > 10) && (the_burst < 10))
	  printf("\n");
	else
	  if((u > 5) && (the_burst < 5))
	    printf("ready.. aim...\n");

  the_burst = u;

  return;
}


void
cmd_set_community(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  char *u = (char *) NULL;

  prog = *argv;
  if(argc == 1)
    {
      printf("Default community is %s.\n", strcmp(the_community, "public") ?
	     reverse(the_community) : the_community);
      return;
    }

  while(*++argv)
    {
      if(u || string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<community>]\n", prog);
	  return;
	}

      u = *argv;
    }
  
  if(u)
    the_community = copy_string(u);
  else
    while(!u)
      u = input_string("community: ", (char *) NULL);
  
  return;
}


void
cmd_set_retry(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  int u = -1;

  prog = *argv;
  if(argc == 1)
    {
      printf("Retry count is set to %d.\n", the_retry);
      return;
    }

  while(*++argv)
    {
      if((u >= 0) || string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<retries>]\n", prog);
	  return;
	}

      if(isnumber(*argv))
	u = atoi(*argv);
      else
	{
	  fprintf(stderr, "%s needs to be a number!\n");
	  printf("usage: %s [<retries>]\n", prog);
	  return;
	}
    }
  
  if(u < 0)
    fprintf(stderr, "retry count cannot be negative.\n");
      
  while(u < 0)
    u = input_number("retries: ", 0);
  
  the_retry = u;
  return;
}


void
cmd_set_update(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  int u = -1;

  prog = *argv;
  if(argc == 1)
    {
      printf("Update interval is set to %d second%s.\n", the_update,
	     the_update > 1 ? "s" : "");
      return;
    }

  while(*++argv)
    {
      if((u >= 0) || string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<seconds>]\n", prog);
	  return;
	}

      if(isnumber(*argv))
	u = atoi(*argv);
      else
	{
	  fprintf(stderr, "%s needs to be a number!\n");
	  printf("usage: %s [<seconds>]\n", prog);
	  return;
	}
    }
  
  if(u < 0)
    fprintf(stderr, "update interval must be greater than zero.\n");
      
  while(u < 0)
    u = input_number("update interval: ", 0);
  
  the_update = u;
  return;
}



void
cmd_disaster(argc, argv)
     int argc;
     char **argv;
{
  if(argc != 1)
    {
      printf("usage: %s\n", argv[0]);
      return;
    }

  the_retry   = dis_retry;
  the_update  = dis_update;
  the_timeout = dis_timeout;
  the_burst   = dis_burst;

  return;
}



void
cmd_normal(argc, argv)
     int argc;
     char **argv;
{
  if(argc != 1)
    {
      printf("usage: %s\n", argv[0]);
      return;
    }

  the_retry   = norm_retry;
  the_update  = norm_update;
  the_timeout = norm_timeout;
  the_burst   = norm_burst;

  return;
}



void
cmd_toggle(argc, argv)
     int argc;
     char **argv;
{
  char *prog;
  Agent a;
  struct hostent *hp;
  unsigned long laddr;
  char *name = (char *) NULL;
  int board  = 0;
  int port   = 0;
  char nbuf[32];
  char bbuf[10];
  int status = 0;

  prog = *argv;
  bzero(&a, sizeof(a));

  while(*++argv)
    {
      if(string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s [<agent>] [-board <board>] [-port <port>]\n", 
		 prog);
	  return;
	}
      
      if(string_equiv(*argv, "-board", 2))
	{
	  if(!*++argv)
	    {
	      printf("board number must follow -board option.\n");
	      return;
	    }
	  board = atoi(*argv);
	  if(board < 1)
	    {
	      printf("board number must be greater than zero.\n");
	      return;
	    }
	  continue;
	} 
      
      if(string_equiv(*argv, "-port", 2))
	{
	  if(!*++argv)
	    {
	      printf("port number must follow -port option.\n");
	      return;
	    }
	  port = atoi(*argv);
	  if(port < 1)
	    {
	      printf("port number must be greater than zero.\n");
	      return;
	    }
	  continue;
	} 

      name = *argv;
    }

  if(!name)
    {
      if(get_prompted_input("agent", "", nbuf, sizeof(nbuf)) < 0)
	return;
      if(!*nbuf)
	{	  
	  printf("punting.\n");
	  return;
	}
      name = nbuf;
    }
  
  if(!(hp = gethostbyname(name)))
    if((laddr = inet_addr(name)) > 0)
      if(!(hp = gethostbyaddr((char *) &laddr, 4, AF_INET)))
	{
	  fprintf(stderr, "cannot resolve name of agent, %s.\n", name);
	  return;
	}	

  strcpy(a.alias, name);
  strcpy(a.name, hp->h_name);
  upcase(a.name);
  bcopy(hp->h_addr, &(a.addr.s_addr), hp->h_length);
  strcpy(a.saddr, inet_ntoa(a.addr));

  if(!board)
    {
      if(get_prompted_input("board", "", bbuf, sizeof(bbuf)) < 0)
	return;
      if(!*bbuf)
	return;
      board = atoi(bbuf);
      if(board <= 0)
	{
	  printf("punting.\n");
	  return;
	}
    }

  if(!port)
    {
      if(get_prompted_input("port", "", bbuf, sizeof(bbuf)) < 0)
	return;
      if(!*bbuf)
	return;
      port = atoi(bbuf);
      if(port <= 0)
	{
	  printf("punting.\n");
	  return;


	}
    }

  determine_vendor(&a);

  if(strcmp(prog, "enable") == 0)
    status = ADMIN_ON[a.vendor];
  else
    if(strcmp(prog, "disable") == 0)
      status = ADMIN_OFF[a.vendor];
  
  if(toggle_port(&a, board, port, status) == SUCCESS)
    {
      if(reply.varlist.elem[0].val.value.intgr == ADMIN_ON[a.vendor])
	printf("current state is on.\n");
      else
	if(reply.varlist.elem[0].val.value.intgr == ADMIN_OFF[a.vendor])
	  printf("current state is off.\n");
	else
	  printf("current state is massachusetts.\n");
    }
  else
    printf("error in getting reply. current state is unknown.\n");
}



cmd_locate_addr(argc, argv)
     int argc;
     char **argv;
{
  char *name[50];
  char nbuf[32];
  Agent a[50];
  Agent *ap[50];
  Agent **alist = (Agent **) NULL;

  char *target;
  char macaddr[6];
  struct in_addr proto;
  struct hostent *hp;
  unsigned long laddr;
  char *prog;
  int i=0,j=0;

  bzero(a, sizeof(a));
  bzero(ap, sizeof(ap));
  bzero(name, sizeof(name));

  prog = *argv++;
  if(!(target = *argv++))
    {
      fprintf(stderr, "no name or address given.\n");
      return;
    }


  while(*argv)
    {
      if(string_equiv(*argv, "-help", 2))
	{
	  printf("usage: %s <name|address> [<agent>] [-key <list>]\n", prog);
	  return;
	}
      
      if(string_equiv(*argv, "-key", 2))
	{
	  if(!*++argv)
	    {
	      printf("usage: %s <name|address> [<agent>] [-key <list>]\n", 
		     prog);
	      return;
	    }
	  if(!(alist = (Agent **) get_agents(*argv)))
	    return;
	}
      else
	{
	  name[i++] = *argv;
	  if(i == 50)
	    break;
	}
      ++argv;
    }

  if(!alist && !name[0])
    {
      if(get_prompted_input("agent", "", nbuf, sizeof(nbuf)) < 0)
	return;
      if(!*nbuf)
	return;
      name[0] = nbuf;
      i = 1;
    }
  if(!alist)
    for(j = 0; j < i; j++)
      {
	if(!(hp = gethostbyname(name[j])))
	  {
            if(!isdigit(name[j][0]))
              {
                 fprintf(stderr, "cannot resolve name of agent, %s.\n", name[j]);
                 return;
               }
	    if((laddr = inet_addr(name[j])) > 0)
	      {
		if(!(hp = gethostbyaddr((char *) &laddr, 4, AF_INET)))
		  {
		    fprintf(stderr, 
			    "warning: cannot resolve name of agent, %s.\n", 
			    name[j]);
		    bcopy(&laddr, &(a[j].addr.s_addr), hp->h_length);
		  }
		else
		  bcopy(hp->h_addr, &(a[j].addr.s_addr), hp->h_length);
	      }
	    else
	      return;
	  }
	else
	  bcopy(hp->h_addr, &(a[j].addr.s_addr), hp->h_length);
	strcpy(a[j].alias, name[j]);	
	strcpy(a[j].name, hp->h_name);
	upcase(a[j].name);
	strcpy(a[j].saddr, inet_ntoa(a[j].addr));
	ap[j] = &a[j];
      }
  if(i)
    alist = ap;
  /* 
   * see if it is a domain name
   */

  bzero(&proto, sizeof(proto));
  if(*target != '*')
    {
      if(!(hp = gethostbyname(target)))
	if((laddr = inet_addr(target)) > 0)
	  if(!(hp = gethostbyaddr((char *) &laddr, 4, AF_INET)))
	    {
	      fprintf(stderr, "cannot resolve name of agent, %s.\n", target);
	      return;
	    }	
      bcopy(hp->h_addr, &(proto.s_addr), hp->h_length);
    }

  if(proto.s_addr || (index(target, '.') && 
		      (proto.s_addr = inet_addr(target)) >= 0))
    locate(alist, proto, NULL);
  else
    if((strlen(target) == 12) || (*target == '*'))
      locate(alist, proto, target);
    else
      fprintf(stderr, "unknown host \"%s\"\n", target);

  return;
}



toggle_port(agent, board, port, val)
     Agent *agent;
     int board;
     int port;
     int val;
{
  vPortAdminStatus[agent->vendor].cmp[vPortAdminStatus[agent->vendor].ncmp - 2]
    = board;
  vPortAdminStatus[agent->vendor].cmp[vPortAdminStatus[agent->vendor].ncmp - 1]
    = port;
  if((make_snmp_set(agent, &vPortAdminStatus[agent->vendor], &val, INT, 0) == 
      SUCCESS) &&
     reply.errstat == 0)
    return(SUCCESS);
  else
    return(ERROR);
}




toggle_interface(agent, port, val)
     Agent *agent;
     int port;
     int val;
{
  vIfAdminStatus.cmp[vIfAdminStatus.ncmp - 1] = port;
  if((make_snmp_set(agent, &vIfAdminStatus, &val, INT, 0) == SUCCESS) &&
     reply.errstat == 0)
    return(SUCCESS);
  else
    return(ERROR);
}



void
cmd_foo()
{
}

