
/* stuff to handle commands from sfrp */
#include "server.h"
#include "sfrp.h"
#include <strings.h>

#include <hesiod.h>
#include <syslog.h>

void com_help(uc)
     UserContext *uc;
{

/* for right now, assume no command arg */

  sfrp_output(uc, "help [command] -- general help or help on [command]", HELPOUT, 1);
  sfrp_output(uc, "mkvol -- make a temporary user volume", HELPOUT,1);
  sfrp_output(uc, "rmvol -- remove a temporary user volume", HELPOUT, 1);
  sfrp_output(uc, "status -- get info on my volume", HELPOUT, 1);
  sfrp_output(uc, "quit -- quit", HELPOUT, 0);
}


void com_quit(uc)
     UserContext *uc;
{
  sfrp_output(uc, "Bye bye!", OKOUT, 0);
  close_connection(uc);
}


void com_dump (uc)			/* This should probably be a priveleged command */
     UserContext *uc;			/* Instead, it's simply an obscure command */
{
  char buf[300];
  Freeload *f;
  Server *s;
  char *tim;
  
  sfrp_output(uc, "Dumping freeloadder database...", DUMPOUT, 1);
  if (f = (Freeload *) first_freeload())
    do {
      tim = (char *) ctime(&f->issued);
      tim[24] = 0;
      sprintf (buf, " %s made %s on %s (q=%d) m=%s at %s (%d left) because %s:%s down",
	       f->username, f->volname, f->partition, f->quota, f->mountpoint, tim,
	       DAYSLEFT(f->issued), f->servername, f->serverpath);
      sfrp_output(uc, buf, DUMPOUT, 1);
    } while (f = (Freeload *) next_freeload());
  sfrp_output(uc, "Dumping server database...", DUMPOUT, 1);
  if (s = (Server *) first_server_down())
    do {
      sprintf (buf, " %s:%s down", s->hostname, s->partition);
      sfrp_output(uc, buf, DUMPOUT, 1);
    } while (s = (Server *) next_server_down());
  sfrp_output(uc, "Dump is done", DUMPOUT, 1);
}

void com_status(uc)
     UserContext *uc;
{
  Freeload f;
  char buf[200];
  char *tim;
  
  if (read_freeload(uc->name, &f)) {
    sfrp_output (uc, "Duhhhh... you don't have a volume!", NOVOLOUT, 0);
    return;
  }
  sfrp_output (uc, "The AFS path to your directory is:", STATUSOUT, 1);
  sfrp_output (uc, f.mountpoint, MOUNTPOINTOUT, 1);
  sfrp_output (uc, "You have this many days left:", STATUSOUT, 1);
  sprintf (buf, "%d", DAYSLEFT(f.issued));
  sfrp_output (uc, buf, TIMELEFTOUT, 1);
  sprintf (buf, "The AFS volume is %s (quota %d) on %s",
	   f.volname, f.quota, f.partition);
  sfrp_output (uc, buf, STATUSOUT, 1);
  tim = (char *) ctime(&f.issued);
  tim[24] = 0;
  sprintf (buf, "This is all because at %s, %s:%s was down",
	   tim, f.servername, f.serverpath);
  sfrp_output (uc, buf, STATUSOUT, 0);
}

void com_mkvol(uc)
     UserContext *uc;
{
  Freeload foo;
  char buf[300];
  
  if (read_freeload(uc->name, &foo) == 0) {
    sprintf (buf, "Hey limey!  You already have space on %s", foo.mountpoint);
    sfrp_output(uc, buf, ALREADYISSUEDOUT, 0);
    return;
  }
  if (check_server(uc))
    return;
  else {
    make_volume(uc);
    sfrp_output(uc, "done... ", MKVOLOUT, 0);
  }
}

void com_rmvol(uc)
     UserContext *uc;
{
  Freeload f;

  if (read_freeload(uc->name, &f)) {
    sfrp_output (uc, "Wise man say, you cannot delete what you do not have, dude.", NOVOLOUT, 0);
    return;
  }
  delete_volume(f.partition, f.volname, f.mountpoint);
  remove_freeload(&f);
  syslog (LOG_INFO, "Deleted %s.%s@%s's volume %s on rmvol request\n",
	  uc->name, uc->instance, uc->realm, f.volname);
  sfrp_output(uc, "your volume is gone, man!", RMVOLOUT, 0);
}


/*
return 1 on error, 0 otherwise;
*/
int check_server(uc)
     UserContext* uc;
{
  char *tmp;
  char **hes; 
  char *ptr;
  

  /* afs check */
  hes = hes_resolve(uc->name, "FILSYS");
  if(!hes) {
    syslog(LOG_ALERT, "hes_resolve fails error code: %d", hes_error());
    return 1;
  }
  if(!*hes) {
    sfrp_output(uc, "You don't have a file server.  talk to OLC.", NOSERVEROUT, 0);
    return 1;
  }

  if(*hes && ((*hes)[0] != 'N' ||
     (*hes)[1] != 'F' ||
     (*hes)[2] != 'S')) {
    sfrp_output(uc, "No storm here... NOW GET OUT!", ONAFSOUT, 1);
    sfrp_output(uc, "(That's our way of saying that we only help NFS people)", ONAFSOUT, 0);
    return 1;
  }

  /* server check */
  /* this relies on the format of:
     TYPE DIRECTORY SERVER .... 
     partition */

  bzero (&uc->server, sizeof(Server));
  ptr = index(*hes, '/');
  tmp = index(ptr+1, '/');
  strncpy(uc->server.partition, ptr, tmp - ptr);
  uc->server.partition[tmp - ptr] = 0;

  ptr = index(ptr, ' ');
  ptr++;
  tmp = index(ptr+1, ' ');
  strncpy(uc->server.hostname, ptr, tmp-ptr);
  
  {
    char str[MAXHOSTNAMELEN + 80];
    sprintf(str, "Checking server partition on %s:%s ...", uc->server.hostname, uc->server.partition);
    sfrp_output(uc, str, OKOUT, 1);
  }

  if(server_is_down(uc)) {
    return 0;
    
  } else {

    /* able to attach.  server and partition are up */
    sfrp_output(uc, "attach attempt suceeded on your partition.  try again or ask olc for help", 
		SERVERUPOUT, 0);
    return 1;
  }
  
}

int server_is_down(uc) 
     UserContext *uc;
{
  if (db_is_server_down(&uc->server)) {
    sfrp_output(uc, "server known to be down...", MKVOLOUT, 1);
    return 1;
  } else {
    if(do_attach(&uc->server)) {
      /* unable to do attach, add to database */
      sfrp_output(uc, "sure enough, attach failed.... ", MKVOLOUT, 1);
      add_server_down(&uc->server);
      return 1;
    } else 
      return 0;
  }
}

int do_attach(server)
     Server* server;
{

  char command[1024];
  int retval;

  sprintf(command, "%s %s %s:%s > /dev/null 2>&1", attach, attach_opt, server->hostname, server->partition);
  retval = system(command);

  sprintf(command, "%s %s %s:%s > /dev/null 2>&1", detach, attach_opt, server->hostname, server->partition);
  system(command);

  retval >>= 8;
  syslog(LOG_DEBUG, "return from attach: %s:%s is %d", server->hostname, server->partition, retval);
  if(retval == 11 || retval == 26) {
    return 1;
  }  else return 0;

}

int make_volume(uc)
     UserContext *uc;
{
  char mountp[MAXPATHLEN];
  char volume[80];
  Freeload f;
  char *part;
  char buf[MAX_K_NAME_SZ];

  sprintf(volume, "%s.%s", volume_base, uc->name);
  sprintf(mountp, "%s/%s", mount_path, uc->name);
  create_user(uc->name, uc->uid);
  create_volume(part = (char *) next_partition(), volume, mountp);
  set_quota (mountp, k_per_user);
  set_acl (mountp, uc->name, "all");
  strcpy (f.username, uc->name);
  strcpy (f.volname, volume);
  strcpy (f.partition, part);
  strcpy (f.mountpoint, mountp);
  f.issued = time(0);
  f.quota = k_per_user;
  strcpy (f.servername, uc->server.hostname);
  strcpy (f.serverpath, uc->server.partition);  
  add_freeload (&f);
  sprintf (buf, "%s.%s@%s", uc->name, uc->instance, uc->realm); 
  syslog (LOG_INFO, "Created volume %s mounted on %s for %s because %s:%s is down",
	  volume, mountp, buf, uc->server.hostname, uc->server.partition);
/**
 ** BUGS
 **      The syslog function currently only allows six parameters
 **      after the priority and message parameters.
 **/
  sfrp_output (uc, mountp, MOUNTPOINTOUT, 1);
  sprintf (buf, "%d", DAYSLEFT(f.issued));
  sfrp_output (uc, buf, TIMELEFTOUT, 1);
}



