/
lib/banish/
lib/d/coronos/
lib/d/coronos/w/alena/
lib/d/coronos/w/angel/
lib/d/coronos/w/angel/caves/
lib/d/coronos/w/angel/caves/monst/
lib/d/coronos/w/angel/city/chambers/
lib/d/coronos/w/angel/city/monst/
lib/d/coronos/w/angel/city/obj/
lib/d/coronos/w/angel/city/streets/
lib/d/coronos/w/angel/farms/plains/
lib/d/coronos/w/angel/monst/
lib/d/tempus/
lib/d/tempus/w/angel/
lib/d/tempus/w/kingbill/
lib/d/tempus/w/mirak/
lib/d/tempus/w/mirak/monst/
lib/d/tempus/w/mirak/obj/
lib/d/tempus/w/relgar/planes/baat/
lib/d/tempus/w/sarak/
lib/d/tempus/w/serepion/mon/
lib/d/tempus/w/valrejn/
lib/doc/
lib/doc/domains/
lib/doc/efun/
lib/include/fn_specs/
lib/info/
lib/inherit/base/
lib/log/
lib/log/mailbox/
lib/log/main/
lib/news/
lib/obj/party/
lib/objects/componen/
lib/open/
lib/open/party/
lib/open/paste/
lib/open/spells/
lib/open/valrejn/
lib/players/
lib/players/alena/
lib/players/alena/obj/
lib/players/alena/open/
lib/players/alena/private/
lib/players/angel/
lib/players/angel/obj/
lib/players/ash/
lib/players/biggs/
lib/players/biggs/food/
lib/players/biggs/gobkeep/
lib/players/biggs/mnstr/
lib/players/biggs/town/caves/
lib/players/biggs/town/tower/
lib/players/biggs/wpns/
lib/players/calris/
lib/players/deathurg/
lib/players/deathurg/open/
lib/players/deathurg/private/thief/
lib/players/dogberry/
lib/players/dogberry/library/
lib/players/dogberry/open/
lib/players/epsilon/
lib/players/epsilon/private/
lib/players/farewell/
lib/players/hippo/
lib/players/hippo/open/
lib/players/hippo/tools/
lib/players/jimpa/
lib/players/josh/
lib/players/josh/room/
lib/players/josh/room/mage/dungeon/
lib/players/josh/room/mage/dungeon/obj/
lib/players/josh/wep/
lib/players/kingbill/
lib/players/metatron/
lib/players/miette/
lib/players/mirak/
lib/players/mirak/open/
lib/players/parsilan/
lib/players/relgar/
lib/players/relgar/private/
lib/players/sarak/
lib/players/sarak/bugs/
lib/players/sarak/feelings/
lib/players/sarak/magical/
lib/players/sarak/minotaur/island/
lib/players/sarak/open/
lib/players/sarak/private/
lib/players/serepion/
lib/players/serepion/open/
lib/players/serepion/private/
lib/players/spike/
lib/players/spike/open/
lib/players/spike/private/
lib/players/spike/seaworld/
lib/players/valrejn/
lib/players/valrejn/open/
lib/players/valrejn/private/
lib/players/virus/
lib/players/wrath/
lib/players/wrath/arm/
lib/players/wrath/mon/
lib/players/wrath/room/
lib/players/wrath/room/entry/
lib/players/wrath/room/zolgath/
lib/players/wrath/weap/
lib/players/zil/
lib/room/
lib/room/city/arena/
lib/room/city/creator/
lib/room/city/garden/monst/
lib/room/city/library/
lib/room/city/library/open/books/
lib/room/city/shop/
lib/room/death/
lib/room/death/open/
lib/room/island/
lib/room/keeps/
lib/room/registry/
lib/room/ships/crew/
lib/room/ships/open/
lib/room/ships/open/types/bounty/
lib/room/ships/open/types/nebula/
lib/room/ships/open/types/phoenix/
lib/secure/udp_cmd_/
lib/skills/
lib/skills/fighter/
lib/skills/psionici/
lib/skills/thief/
lib/usr/
lib/usr/creators/
lib/usr/no_banis/
lib/usr/players/
/* TAR extractor for LPC.  This object is a crude tape archive extractor
   
   Its basic use is to allow wizards to extract a single tar file if you
   allow some sought of ftp daemon.  This will not allow the overwriting
   of files.  Access priviledges are based on this_player() as a call_out()
   is used (so this_interactive() == 0).  So access would be limited
   to open directories, and the wizards directory (ie if they use
   the standard access object).  This will also apply to the tar file.  
   
   		Zilanthius (c) 1994
 */

#include <mudlib.h>
inherit TREASURE;

#define BLOCK_SIZE 512

#define MAX_BUFFER 500    /* lines */



string root_dir;                /* current working directory */

string tar_file;                /* tar file */
int f_ptr;                      /* current positon in tar file */

string current_file;            /* current file being extracted */
int current_file_length;        /* length of buffer that is yet to be read */
int current_file_size;          /* file size */

string buffer;                  /* text buffer */

status fatal;                   /* exit if error has occured */
status in_use;                  /* currently extracting */
status buffer_eof;              /* buffer has read EOF */
status is_file;			/* file already exists */


static void buffer_to_file();



void reset(status arg) {
  if(arg) return;
  set_short("Tarx");
  set_name("tarx");
}


void init() {
  ::init();

  add_action("tarx", "tarx");
}



/* convert octal to integer */

int oct_to_int(int oct) {
  int i, base;

  for(base = 1, i = 0; oct; base *= 8) {
    i += (oct - (oct/10) * 10) * base;
    oct /= 10;
  }
  return i;
}


/* fill text buffer */

static void fill_buffer() {
  if(!(buffer = read_file(tar_file,f_ptr,MAX_BUFFER))) {
    write("Error reading tar file.\n");
    fatal = 1;
    return;
  }
#ifdef OLD_EXPLODE
  if(sizeof(explode(buffer +"\n","\n")) - 1 != MAX_BUFFER) buffer_eof = 1;
#else
  if(sizeof(explode(buffer,"\n")) - 1 != MAX_BUFFER) buffer_eof = 1;
#endif
  f_ptr += MAX_BUFFER;
}
    

/* retrieve file, file size and start text from txt header */

status filter_modes(string str) { return str != ""; }

#define FILE_NAME 0
#define FILE_SIZE 4
#define FILE_MODE 7

static void interpret_header() {
  string mode_str, *file_modes, rest;
  string str1, str2, str3;
  int i, field, mode, flag;


  if(fatal || !buffer || buffer == "") return;
  
/* basic header format */

  if(sscanf(buffer,"%s ustar %s", mode_str, rest) != 2) {
    if(buffer_eof)
      write("Ok\n");
    else
      write("Error: Header incorrect format.\n");
    fatal = 1;
    return;
  }

/* get file mode, file size, file name */

#ifdef OLD_EXPLODE
  file_modes = explode(mode_str +" "," "); 
#else
  file_modes = explode(mode_str," "); 
#endif
  file_modes = filter_array(file_modes,"filter_modes",this_object());

  if(sizeof(file_modes) != 8) {
    write("Error: Incorrect mode string.\n");
    for(i = 0; i < sizeof(file_modes); i++) {
      write("\tMode"+ i +": "+ file_modes[i] +"\n");
    }
    fatal = 1;
    return;
  }


/* file name */

  current_file = file_modes[FILE_NAME];


/* file size */

  if(!sscanf(file_modes[FILE_SIZE],"%d",current_file_length)) {
    write("Error: Cannot retrieve file size.\n");
    fatal = 1;
  }
  current_file_length = oct_to_int(current_file_length);
  current_file_size = current_file_length;

#if 0

/* file mode */

  if(!sscanf(file_modes[FILE_MODE],"%d",mode)) {
    write("Error: Cannot retrieve file mode.\n");
    fatal = 1;
  }
  if(mode != 0 && mode != 5) {
    write("Error: Illegal file mode.\n");
    fatal = 1;
  }

#endif 

/* strip header */

  if(sscanf(buffer,"%s"+ current_file +"%s", str1, buffer) == 2) {
    buffer = current_file + buffer;
  }
  buffer = extract(buffer,BLOCK_SIZE);
}


static void tar_extract() {
  int max_loop;
  
  while(!fatal && buffer) {
    if(max_loop++ > 15) {
      write("Continuing Tarx....\n");
      call_out("tar_extract",1);
      return;
    }
    interpret_header();
    if(!fatal) {
      is_file = (file_size(root_dir + current_file) >= 0) ? 1 : 0;
      buffer_to_file();
    }
  }
  in_use = 0;
}
 

void buffer_to_file() {
  string txt, str;
  int i;
  
  if(!current_file_length || current_file[strlen(current_file)-1] == '/') {
    if(current_file[strlen(current_file)-1] == '/') {
      current_file = extract(current_file,0,strlen(current_file)-2);
    }
    if(file_size(root_dir + current_file) == -2
    || mkdir(root_dir + current_file)) {
      str = current_file;
      str += "                                                     ";
      str = extract(str,0,55) +" Directory\n";
      write(str);
      log_file("TARX", str);
    }
    else {
      fatal = 1;
      write("Error: Cannot create directory "+ root_dir + current_file +"\n");
    }
  }
  else {
    txt = extract(buffer,0,current_file_length-1);

    while (!fatal && strlen(txt) < current_file_length) {
      if(!is_file) write_file(root_dir + current_file,buffer);
      current_file_length -= strlen(buffer);
      fill_buffer();
      txt = extract(buffer,0,current_file_length-1);
    }
    if(!is_file) write_file(root_dir + current_file, txt);

    str = current_file;
    str += "                                                         ";
    str = extract(str,0,55) +" File ";
    if(is_file) {
      str += "exists\n";
    }
    else {
      i = 1 + current_file_size/BLOCK_SIZE;
      str += "\t"+ i;
      if(i <= 999) str += " ";
      if(i <= 99) str += " ";
      if(i <= 9) str += " ";
      str += " Blocks\n";
    }
    write(str);
    log_file("TARX", str);
    
    buffer = extract(buffer,current_file_length);
  }
}


/* action */

status tarx(string str) {
  string file;

  if(in_use) {
    notify_fail("Currently extracting "+ tar_file +"\n");
    return 0;
  }
  
  if(!str) {
    notify_fail("tarx <file>, extracts tar file into current directory\n");
    return 0;
  }
  tar_file = (string)this_player()->make_path(str);
  if(file_size(tar_file) <= 0) {
    notify_fail(str +" does not exist.\n");
    return 0;
  }
  write("Zilanthius' Tar Extractor (c) 1994\n\n");

  root_dir = (string)this_player()->query_path() +"/";
  if(root_dir[0] != '/') root_dir = "/"+ root_dir;
  write("Working Directory: "+ root_dir +"\n");
  f_ptr = 1;
  current_file_length = 0;
  current_file = 0;
  buffer = 0;
  in_use = 1;
  buffer_eof = 0;
  fill_buffer();
  call_out("tar_extract",1);
  return 1;
}