

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "client.h"
#include "sfrp.h"


interactive_mode(host)
     char *host;
{
  Connection con;
  char buf[100];
  
  printf ("\nFreeloader Temporary Filespace Service\n\n");
#ifdef KERBEROS  
  check_kerberos(host);
#endif
  open_server (host, &con);
  if (con.closed) {
    printf ("\nOops, I couldn't get a connection to the freeload server (%s)\n", host);
    printf ("Talk to SIPB for help!\n\n");
    exit(1);
  }
  get_status(&con);
  if (!con.hasvolume) {
    printf ("Would you like me to ask for a volume? ");
    gets(buf);
    if (buf[0] == 'y')
      ask_volume(&con);
  }
  if (con.hasvolume) {
    printf ("\nDo you want to attach your volume, or delete it?\n");
    printf ("There is no way to undo the delete, by the way...\n");
    printf ("(type a to attach or delete to delete): ");
    gets(buf);
    if (!strcmp(buf, "delete"))
      delete_volume(&con);
    else
      attach_volume(&con);
  }
  printf ("Bye, now...\n");
}



#ifdef KERBEROS  
#include <krb_err.h>

check_kerberos(host)
     char *host;
{
  KTEXT_ST tick;
  int status;
  
  printf ("Checking your Kerberos tickets ... "); fflush(stdout);
  status = get_authenticator (host, &tick);
  switch (status + ERROR_TABLE_BASE_krb) {
  case KRBET_KSUCCESS:
    printf ("ok\n");
    break;
  case KRBET_KDC_PR_UNKNOWN:
    printf ("this is weird.\n");
    printf ("The error is `principal unknown', which means that the\n");
    printf ("freeload server doesn't have a service key!  Are you sure\n");
    printf ("that %s is a kerberized freeload server?\n", host);
    exit(1);
  case KRBET_NO_TKT_FIL:
  case KRBET_TKT_FIL_FMT:
  case KRBET_TKT_FIL_ACC:
    printf ("yuck.\n");
    printf ("Your ticket file is a mess.  Run kinit... if that doesn't\n");
    printf ("work, try:  setenv KRBTKFILE /tmp/bleeeech.$$; kinit\n");
    printf ("or contact olc or SIPB for help.\n");
    exit(1);
  case KRBET_RD_AP_EXP:
    printf ("you lose.\n");
    printf ("Your tickets have expired.  Run kinit and try again.\n");
    exit(1);
  default:
    printf ("oh no!\n");
    printf ("I got code %d which means %s\n", status, krb_err_txt[status]);
    printf ("I don't know what this means.  Talk to olc or SIPB.  Sorry!\n");
    exit(1);
  }
}

#endif


int do_general (con, cmd, filter)
     Connection *con;
     char *cmd;
     int (*filter)();
{
  char buf[1024];
  int code;
  int more;
  char *msg;
  
  write_server (con, cmd, strlen(cmd));
  write_server (con, "\n", 1);
  do {
    read_server_response (con, buf, sizeof(buf));
    msg = (char *) parse_server_response (buf, &code, &more);
    switch (code) {
    case MOUNTPOINTOUT:
      con->hasvolume = 1;
      strcpy (con->mountpoint, msg);
      break;
    case TIMELEFTOUT:
      con->hasvolume = 1;
      con->daysleft = atoi (msg);
      break;
    case NOVOLOUT:
      con->hasvolume = 0;
      break;
    }
    (*filter)(con, code, more);
  } while (more);
  return code;
}

no_filter ()
{}

handle_error (code)
{
  printf ("(%d) ", code);
  switch (code) {
  case ERROUT:
    printf ("Hmm... generic error... I'm losing!\n");
    break;
  case ALREADYISSUEDOUT:
    printf ("It says you already have a volume... weird.\n");
    break;
  case OUTOFSPACEOUT:
    printf ("Sorry, there's no space left for new freeloaders!\n");
    break;
  case NOVOLOUT:
    printf ("It says you don't have a volume... That's news to me!\n");
    break;
  case SERVERDIEDOUT:
    printf ("Ack!  We lost our connection to the server!\n");
    printf ("Try re-running me and hope for the best.\n");
    break;
  case ONAFSOUT:
    printf ("Sorry, we only help people who use NFS.  You lose!\n");
    break;
  case NOSERVEROUT:
    printf ("Hesiod says that you don't HAVE a home directory at all!\n");
    printf ("Talk to OLC if you don't think this should be the case.\n");
    break;
  default:
    printf ("Ayyyyeeeee --- unknown error code!!!\n");
  }
}

     
     
get_status (con)
     Connection *con;
{
  int code;

  printf ("Checking your status...\n");
  code = do_general (con, "status", no_filter);
  if (code == NOVOLOUT) {
    printf ("You do not [yet] have a volume.\n");
    return;
  }
  if (ISERROROUT(code))
    handle_error(code);
  if (con->hasvolume) {
    printf ("You have a volume that expires in %d days.\n", con->daysleft);
    if (con->daysleft > 3)
      printf ("You know that after that time your files will be mercilessly deleted!\n\n");
    else
      printf ("WE ARE ABOUT TO DELETE YOUR FILES!  COPY THEM SOON!!\n\n");
  } 
}
  
  
ask_volume (con)
     Connection *con;
{
  int code;
  
  printf ("Asking for a volume...\n");
  code = do_general (con, "mkvol", no_filter);
  if (ISERROROUT(code)) 
    handle_error(code);
  if (con->hasvolume) {
    printf ("\nYou now have a shiny new volume.  The most important\n");
    printf ("thing about it is that it expires in %d days!!!\n", con->daysleft);
    printf ("\nTHIS MEANS IN %d DAYS ALL FILES IN IT WILL BE ERASED... FOR GOOD!\n\n", con->daysleft);
    printf ("Before you can use it, on each login, you will have to run\n");
    printf ("this program.  It is stored on an AFS (Andrew File System)\n");
    printf ("server, which means that things like chmod don't work.\n");
    printf ("There is no documentation to help you --- ask OLC or SIPB.\n");
    printf ("By the way, if you need it, the full path to the volume is\n");
    printf ("    %s\n", con->mountpoint);
  }    
}

attach_volume (con)
     Connection *con;
{
  struct stat st;
  char mp[100];
  char cmd[200];

  printf ("\nAttaching your temporary files...\n");
  sprintf (mp, "%s", getenv("HOME"));
  if (lstat (mp, &st) == 0 || errno != ENOENT) {
    printf ("There already seems to be something on %s...", mp);
    sprintf (mp, "%s-temp", getenv("HOME"));
    if (lstat (mp, &st) == 0 || errno != ENOENT) {
      printf ("And %s is taken too!", mp);
      printf ("\nYour files are in %s\n", con->mountpoint);
      system ("aklog sipb.mit.edu");
    } else
      printf ("I'll put them on %s instead.\n", mp);
    return;
  }
  sprintf (cmd, "attach -q -e -t afs -m %s %s", mp, con->mountpoint);
  system (cmd);
  printf ("If that attach just worked, your files are available on\n");
  printf ("    %s\n", mp);
  printf ("If not, they're on\n");
  printf ("    %s\n", con->mountpoint);
}


delete_volume(con)
     Connection *con;
{
  int code;
  
  printf ("\nDeleting your temporary volume...\n");
  code = do_general(con, "rmvol", no_filter);
  if (code == RMVOLOUT)
    printf ("It's GONE !  Bye bye files!\n");
  else
    handle_error(code);
}
