final_realms_fluffos_v1/
final_realms_fluffos_v1/bin/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/ChangeLog.old/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/Win32/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/compat/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/compat/simuls/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/include/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/clone/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/command/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/data/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/etc/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/include/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/inherit/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/inherit/master/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/log/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/compiler/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/efuns/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/operators/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/u/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/tmp/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/windows/
final_realms_fluffos_v1/lib/baseobs/guilds/
final_realms_fluffos_v1/lib/baseobs/misc/
final_realms_fluffos_v1/lib/baseobs/races/shadows/
final_realms_fluffos_v1/lib/cmds/god/
final_realms_fluffos_v1/lib/cmds/handlers/
final_realms_fluffos_v1/lib/cmds/handlers/cmds/
final_realms_fluffos_v1/lib/d/heaven/
final_realms_fluffos_v1/lib/d/heaven/heaven/ave/
final_realms_fluffos_v1/lib/d/mudlib/
final_realms_fluffos_v1/lib/d/newbie/
final_realms_fluffos_v1/lib/d/newbie/docs/
final_realms_fluffos_v1/lib/d/newbie/drow/armour/
final_realms_fluffos_v1/lib/d/newbie/drow/items/
final_realms_fluffos_v1/lib/d/newbie/drow/mobs/
final_realms_fluffos_v1/lib/d/newbie/drow/oldmobs/
final_realms_fluffos_v1/lib/d/newbie/drow/weapons/
final_realms_fluffos_v1/lib/d/newbie/duergar/weapons/
final_realms_fluffos_v1/lib/d/newbie/dwarf/weapons/
final_realms_fluffos_v1/lib/d/newbie/elf/cafe/
final_realms_fluffos_v1/lib/d/newbie/elf/chars/equip/
final_realms_fluffos_v1/lib/d/newbie/elf/items/armours/
final_realms_fluffos_v1/lib/d/newbie/elf/items/obj/
final_realms_fluffos_v1/lib/d/newbie/elf/items/weapons/
final_realms_fluffos_v1/lib/d/newbie/elf/quick_fix/
final_realms_fluffos_v1/lib/d/newbie/gnome/armour/
final_realms_fluffos_v1/lib/d/newbie/gnome/buildings/
final_realms_fluffos_v1/lib/d/newbie/gnome/items/
final_realms_fluffos_v1/lib/d/newbie/gnome/npcs/clones/
final_realms_fluffos_v1/lib/d/newbie/gnome/rooms/northrooms/
final_realms_fluffos_v1/lib/d/newbie/gnome/weapons/
final_realms_fluffos_v1/lib/d/newbie/goblin/armour/
final_realms_fluffos_v1/lib/d/newbie/goblin/items/
final_realms_fluffos_v1/lib/d/newbie/grads/log/
final_realms_fluffos_v1/lib/d/newbie/grads/npcs/
final_realms_fluffos_v1/lib/d/newbie/grads/rooms/
final_realms_fluffos_v1/lib/d/newbie/grads/rooms/cave1/
final_realms_fluffos_v1/lib/d/newbie/grads/temp/
final_realms_fluffos_v1/lib/d/newbie/guests/weapons/
final_realms_fluffos_v1/lib/d/newbie/half-elf/items/
final_realms_fluffos_v1/lib/d/newbie/half-elf/newroomss/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/castle/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/drows/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/savannah/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/secret/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/town/
final_realms_fluffos_v1/lib/d/newbie/halfling/
final_realms_fluffos_v1/lib/d/newbie/halfling/misc/
final_realms_fluffos_v1/lib/d/newbie/halfling/rooms/cave/
final_realms_fluffos_v1/lib/d/newbie/human/
final_realms_fluffos_v1/lib/d/newbie/human/armour/
final_realms_fluffos_v1/lib/d/newbie/human/monsters/
final_realms_fluffos_v1/lib/d/newbie/human/obj/
final_realms_fluffos_v1/lib/d/newbie/human/weapons/
final_realms_fluffos_v1/lib/d/newbie/lizard/armour/
final_realms_fluffos_v1/lib/d/newbie/lizard/items/
final_realms_fluffos_v1/lib/d/newbie/lizard/underwater/
final_realms_fluffos_v1/lib/d/newbie/lizard/weapons/
final_realms_fluffos_v1/lib/d/newbie/logs/
final_realms_fluffos_v1/lib/d/newbie/new_halfelf/
final_realms_fluffos_v1/lib/d/newbie/new_halfelf/npcs/
final_realms_fluffos_v1/lib/d/newbie/newdrow/npcs/
final_realms_fluffos_v1/lib/d/newbie/newdrow/rooms/
final_realms_fluffos_v1/lib/d/newbie/newelf/
final_realms_fluffos_v1/lib/d/newbie/newelf/chars/
final_realms_fluffos_v1/lib/d/newbie/newelf/npcs/
final_realms_fluffos_v1/lib/d/newbie/newelf/npcs/recopied/
final_realms_fluffos_v1/lib/d/newbie/newelf/obj/
final_realms_fluffos_v1/lib/d/newbie/newelf/quest_docs./
final_realms_fluffos_v1/lib/d/newbie/newken/
final_realms_fluffos_v1/lib/d/newbie/newken/chars/
final_realms_fluffos_v1/lib/d/newbie/newken/misc/
final_realms_fluffos_v1/lib/d/newbie/newken/npcs/
final_realms_fluffos_v1/lib/d/newbie/newken/obj/
final_realms_fluffos_v1/lib/d/newbie/newliz/
final_realms_fluffos_v1/lib/d/newbie/newliz/cave/
final_realms_fluffos_v1/lib/d/newbie/newliz/npcs/
final_realms_fluffos_v1/lib/d/newbie/orc/items/misc/
final_realms_fluffos_v1/lib/d/newbie/orc/items/weapons/
final_realms_fluffos_v1/lib/d/newbie/orc/tower/
final_realms_fluffos_v1/lib/d/vehicle/
final_realms_fluffos_v1/lib/doc/
final_realms_fluffos_v1/lib/doc/driver/
final_realms_fluffos_v1/lib/doc/driver/concepts/
final_realms_fluffos_v1/lib/doc/driver/driver/
final_realms_fluffos_v1/lib/doc/driver/efuns/arrays/
final_realms_fluffos_v1/lib/doc/driver/efuns/bitstrings/
final_realms_fluffos_v1/lib/doc/driver/efuns/communication/
final_realms_fluffos_v1/lib/doc/driver/efuns/core/
final_realms_fluffos_v1/lib/doc/driver/efuns/debugging/
final_realms_fluffos_v1/lib/doc/driver/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/driver/efuns/interactive/
final_realms_fluffos_v1/lib/doc/driver/efuns/mappings/
final_realms_fluffos_v1/lib/doc/driver/efuns/objects/
final_realms_fluffos_v1/lib/doc/driver/efuns/security/
final_realms_fluffos_v1/lib/doc/driver/efuns/strings/
final_realms_fluffos_v1/lib/doc/driver/efuns/system/
final_realms_fluffos_v1/lib/doc/driver/efuns/types/
final_realms_fluffos_v1/lib/doc/driver/lpc/constructs/
final_realms_fluffos_v1/lib/doc/driver/lpc/types/
final_realms_fluffos_v1/lib/doc/driver/platforms/
final_realms_fluffos_v1/lib/doc/lpc/
final_realms_fluffos_v1/lib/doc/mail/
final_realms_fluffos_v1/lib/doc/man/
final_realms_fluffos_v1/lib/doc/man/html/
final_realms_fluffos_v1/lib/doc/man/html/applies/
final_realms_fluffos_v1/lib/doc/man/html/applies/parsing/
final_realms_fluffos_v1/lib/doc/man/html/driver/
final_realms_fluffos_v1/lib/doc/man/html/efuns/
final_realms_fluffos_v1/lib/doc/man/html/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/html/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/html/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/html/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/html/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/html/efuns/general/
final_realms_fluffos_v1/lib/doc/man/html/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/html/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/local/
final_realms_fluffos_v1/lib/doc/man/local/applies/
final_realms_fluffos_v1/lib/doc/man/local/applies/interactive/
final_realms_fluffos_v1/lib/doc/man/local/applies/master/
final_realms_fluffos_v1/lib/doc/man/local/concepts/
final_realms_fluffos_v1/lib/doc/man/local/defines/
final_realms_fluffos_v1/lib/doc/man/local/driver/
final_realms_fluffos_v1/lib/doc/man/local/efuns/
final_realms_fluffos_v1/lib/doc/man/local/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/local/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/local/efuns/calls/
final_realms_fluffos_v1/lib/doc/man/local/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/local/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/man/local/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/local/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/local/efuns/general/
final_realms_fluffos_v1/lib/doc/man/local/efuns/interactive/
final_realms_fluffos_v1/lib/doc/man/local/efuns/internals/
final_realms_fluffos_v1/lib/doc/man/local/efuns/mappings/
final_realms_fluffos_v1/lib/doc/man/local/efuns/mudlib/
final_realms_fluffos_v1/lib/doc/man/local/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/local/efuns/objects/
final_realms_fluffos_v1/lib/doc/man/local/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/local/efuns/sockets/
final_realms_fluffos_v1/lib/doc/man/local/efuns/strings/
final_realms_fluffos_v1/lib/doc/man/local/efuns/system/
final_realms_fluffos_v1/lib/doc/man/local/historical/
final_realms_fluffos_v1/lib/doc/man/local/lfun/QC/
final_realms_fluffos_v1/lib/doc/man/local/lfun/events/
final_realms_fluffos_v1/lib/doc/man/local/lfun/monster/
final_realms_fluffos_v1/lib/doc/man/local/lfun/properties/
final_realms_fluffos_v1/lib/doc/man/local/lpc/
final_realms_fluffos_v1/lib/doc/man/local/lpc/constructs/
final_realms_fluffos_v1/lib/doc/man/local/lpc/types/
final_realms_fluffos_v1/lib/doc/man/local/standards/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/basic/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/intermediate/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/interactive/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/parsing/
final_realms_fluffos_v1/lib/doc/man/mudos/concepts/
final_realms_fluffos_v1/lib/doc/man/mudos/driver/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/calls/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/general/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mappings/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mixed/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mudlib/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/mudos/lpc/constructs/
final_realms_fluffos_v1/lib/doc/man/mudos/lpc/types/
final_realms_fluffos_v1/lib/doc/races/
final_realms_fluffos_v1/lib/doc/races/old_race/
final_realms_fluffos_v1/lib/global/virtual/
final_realms_fluffos_v1/lib/global/wiz_backup/
final_realms_fluffos_v1/lib/net/config/
final_realms_fluffos_v1/lib/net/daemon/chars/
final_realms_fluffos_v1/lib/net/inherit/
final_realms_fluffos_v1/lib/net/intermud3/
final_realms_fluffos_v1/lib/net/intermud3/cmds/
final_realms_fluffos_v1/lib/net/intermud3/save/
final_realms_fluffos_v1/lib/net/intermud3/services/
final_realms_fluffos_v1/lib/net/obj/
final_realms_fluffos_v1/lib/net/old/
final_realms_fluffos_v1/lib/net/old/intermud/
final_realms_fluffos_v1/lib/net/old/intermud/adm/
final_realms_fluffos_v1/lib/net/old/intermud/services/
final_realms_fluffos_v1/lib/net/old/intermud/udp/
final_realms_fluffos_v1/lib/net/virtual/
final_realms_fluffos_v1/lib/obj/b_day/
final_realms_fluffos_v1/lib/obj/chars/
final_realms_fluffos_v1/lib/obj/handlers/lists/
final_realms_fluffos_v1/lib/obj/handlers/useless/
final_realms_fluffos_v1/lib/obj/monsters/
final_realms_fluffos_v1/lib/obj/roomgen/
final_realms_fluffos_v1/lib/obj/soul/
final_realms_fluffos_v1/lib/obj/vegetation/
final_realms_fluffos_v1/lib/obj/weapons/oldsys/
final_realms_fluffos_v1/lib/open/
final_realms_fluffos_v1/lib/players/g/
final_realms_fluffos_v1/lib/releasefiles/d/heaven/
final_realms_fluffos_v1/lib/releasefiles/d/mudlib/
final_realms_fluffos_v1/lib/releasefiles/d/newbie/
final_realms_fluffos_v1/lib/releasefiles/doc/
final_realms_fluffos_v1/lib/releasefiles/players/g/
final_realms_fluffos_v1/lib/releasefiles/save/
final_realms_fluffos_v1/lib/releasefiles/save/environ/
final_realms_fluffos_v1/lib/releasefiles/save/roomgen/
final_realms_fluffos_v1/lib/releasefiles/secure/
final_realms_fluffos_v1/lib/releasefiles/w/
final_realms_fluffos_v1/lib/releasefiles/w/god/
final_realms_fluffos_v1/lib/room/
final_realms_fluffos_v1/lib/save/
final_realms_fluffos_v1/lib/save/environ/
final_realms_fluffos_v1/lib/save/roomgen/
final_realms_fluffos_v1/lib/scripts/
final_realms_fluffos_v1/lib/secure/crerem/
final_realms_fluffos_v1/lib/secure/dom/
final_realms_fluffos_v1/lib/secure/log/
final_realms_fluffos_v1/lib/secure/misc/
final_realms_fluffos_v1/lib/std/adnd/
final_realms_fluffos_v1/lib/std/commands/shadows/
final_realms_fluffos_v1/lib/std/creator/
final_realms_fluffos_v1/lib/std/curses/
final_realms_fluffos_v1/lib/std/curses/old_sys/
final_realms_fluffos_v1/lib/std/curses/shadows/
final_realms_fluffos_v1/lib/std/dom/
final_realms_fluffos_v1/lib/std/effects/
final_realms_fluffos_v1/lib/std/effects/healing/
final_realms_fluffos_v1/lib/std/effects/other/
final_realms_fluffos_v1/lib/std/effects/poisons/
final_realms_fluffos_v1/lib/std/environ/
final_realms_fluffos_v1/lib/std/guilds/
final_realms_fluffos_v1/lib/std/guilds/priests/samples/
final_realms_fluffos_v1/lib/std/guilds/wizards/
final_realms_fluffos_v1/lib/std/living/baldy/
final_realms_fluffos_v1/lib/std/living/divstuff/
final_realms_fluffos_v1/lib/std/paran/
final_realms_fluffos_v1/lib/std/poisons/
final_realms_fluffos_v1/lib/std/poisons/shadows/
final_realms_fluffos_v1/lib/std/poisons/weapons/
final_realms_fluffos_v1/lib/std/race_groups/
final_realms_fluffos_v1/lib/std/room/
final_realms_fluffos_v1/lib/std/room/old/
final_realms_fluffos_v1/lib/std/rooms/
final_realms_fluffos_v1/lib/std/shadows/
final_realms_fluffos_v1/lib/std/shadows/test_shad/
final_realms_fluffos_v1/lib/std/socket/
final_realms_fluffos_v1/lib/std/spells/
final_realms_fluffos_v1/lib/std/vaults/
final_realms_fluffos_v1/lib/tmp/
final_realms_fluffos_v1/lib/w/
final_realms_fluffos_v1/lib/w/god/
final_realms_fluffos_v1/old/
final_realms_fluffos_v1/win32/
/*
 * This will talk to gophers and get the menu stuff back in a nice
 * format for you.
 *
 * You send it the field to look up, the host to goto and the port to
 * look at, the function to call back on you, and optionaly the
 * search text...
 */
#include "gopher.h"
#include "socket.h"
#include "mudlib.h"

mapping in_progress,
        number_name;
#ifdef GOPHER_PORT
string our_path;
int our_socket;
string tack_on_mess;

void setup_gopher(int port, string path);
#endif
int *closes;
void finish_lookup(string host, string number);

void create() {
  in_progress = ([ ]);
  number_name = ([ ]);
  closes = ({ });
#ifdef GOPHER_PORT
  call_out("setup_gopher", 2, ({ GOPHER_PORT, GOPHER_PATH }));
#endif
} /* create() */

void do_connect(int type, string name, string host, string port, string func,
                string search_text) {
  if (!in_progress[host]) {
    in_progress[host] = ({ ({ name, port, previous_object(),
                              func, search_text, "", type }) });
    if (number_name[host])
      finish_lookup(host, number_name[host]);
    else
      resolve(host, "finish_lookup");
  } else
    in_progress[host] += ({ ({ name, port, previous_object(),
                               func, search_text, "", type }) });
} /* do_connect() */

string query_number_name(string number) { return number_name[number]; }

void do_resolve(string name, string func) {
  if (number_name[name]) {
    call_other(previous_object(), func, name, number_name[name]);
    return ;
  }
  if (!in_progress[name]) {
    in_progress[name] = ({ ({ previous_object(), func }) });
    resolve(name, "finish_lookup");
  } else
    in_progress[name] += ({ ({ previous_object(), func }) });
} /* do_resolve() */

void finish_lookup(string host, string number) {
  int new_fd, ret;
  int i;

/* Make sure we only have one name for each host */
  if (!number_name[number])
    number_name[number] = host;
  number_name[host] = number;
/* We failed to lookup our host... :( */
  if (!number) {
    if (!in_progress[host]) {
      for (i=0;i<sizeof(in_progress[host]);i++)
        if (sizeof(in_progress[host][i]) == 2)
          call_other(in_progress[host][i][0], in_progress[host][i][1],
                     host, number);
        else
          call_other(in_progress[host][i][2], in_progress[host][i][3], 0);
    }
    return ;
  }
/* Ok, now we wanna connect up... */
  for (i=0;i<sizeof(in_progress[host]);i++) {
    if (sizeof(in_progress[host][i]) == 2) {
      call_other(in_progress[host][i][0], in_progress[host][i][1],
                 host, number);
      map_delete(in_progress, host);
      continue;
    }
    new_fd = socket_create(STREAM, "out_read_callback", "out_close_callback");
    if (new_fd < 0) {
      call_other(in_progress[host][i][2], in_progress[host][i][3], 0);
      return ;
    }
    ret = socket_connect(new_fd, number+" "+in_progress[host][i][1],
                         "out_read_callback", "out_write_callback");
    if (ret < 0) {
      call_other(in_progress[host][i][2], in_progress[host][i][3], 0,
                 in_progress[host][i][0..4]);
      map_delete(in_progress, host);
      return ;
    }
    remove_call_out("do_closes");
    call_out("do_closes", 120);
    closes += ({ new_fd });
    in_progress[new_fd] = in_progress[host][i];
/*
    if (in_progress[host][i][4])
      socket_write(new_fd, sprintf("%s\t%s\n", in_progress[host][i][0],
                                               in_progress[host][i][4]));
    else
      socket_write(new_fd, sprintf("%s\n", in_progress[host][i][0]));
 */
  }
  map_delete(in_progress, host);
} /* finish_lookup() */

void out_write_callback(int fd) {
  string str;

  if (in_progress[fd][4])
    socket_write(fd, (str = sprintf("%s\t%s\n", in_progress[fd][0],
                                             in_progress[fd][4])));
  else
    socket_write(fd, (str = sprintf("%s\n", in_progress[fd][0])));
} /* out_write_callback() */

void out_read_callback(int fd, string mess) {
  if (!in_progress[fd]) {
/* Hmmmmmm. */
    socket_close(fd);
    return ;
  }
  in_progress[fd][5] += replace_string(mess, "\r", "");
} /* out_read_callback() */

void out_close_callback(int fd) {
  string *bits, *bb;
  int i;
  mixed *ret;

  socket_close(fd);
  if (!in_progress[fd]) return ;
  if (in_progress[fd][0] == "")
    in_progress[fd][0] = "1";
  switch (in_progress[fd][6]) {
    case MENU :
    case SEARCH :
      bits = explode(in_progress[fd][5], "\n");
      ret = ({ });
      for (i=0;i<sizeof(bits);i++) {
        bb = explode(bits[i][1..10000], "\t");
        switch (bits[i][0]) {
          case '1' :
/* Menu...  */
            ret += ({ ({ MENU, bb }) });
            break;
          case '0' :
            ret += ({ ({ FILE, bb }) });
            break;
          case '7' :
            ret += ({ ({ SEARCH, bb }) });
            break;
        }
      }
      catch(call_other(in_progress[fd][2], in_progress[fd][3], ret,
                 in_progress[fd][0..4]));
      break;
    case FILE :
      in_progress[fd][5] = in_progress[fd][5][0..strlen(in_progress[fd][5])-3];
      catch(call_other(in_progress[fd][2], in_progress[fd][3],
                       in_progress[fd][5], in_progress[fd][0..4]));
      break;
  }
  map_delete(in_progress, fd);
  closes = closes - ({ fd });
} /* out_close_callback() */

void do_closes() {
  int i, *tmp;

  tmp = closes + ({ });
  for (i=0;i<sizeof(tmp);i++)
    out_close_callback(tmp[i]);
} /* do_closes() */

/* From here on down is the gopher server code. */
#ifdef GOPHER_PORT
void setup_gopher(mixed port, string path) {
  if (pointerp(port)) {
    path = port[1];
    port = port[0];
  }
  our_path = path;
  our_socket = socket_create(STREAM, "in_read_callback", "in_close_callback");
  if (our_socket < 0) {
    return ;
  }
  if (socket_bind(our_socket, port) < 0) {
    socket_close(our_socket);
    call_out("setup_gopher", 120, ({ port, path }));
    return ;
  }
  if (socket_listen(our_socket, "in_listen_callback") < 0) {
    return ;
  }
} /* setup_gopher() */

void in_listen_callback(int fd) {
  int new_fd;

  if ((new_fd = socket_accept(fd, "in_read_callback", "in_write_callback")) < 0) {
    return ;
  }
  call_out("in_close_callback", 120, new_fd);
} /* in_listen_callback() */

string create_menu(string path) {
  string *bing, ret, fn, rest, tmp, new_p, name;
  int i, len, type;

  bing = get_dir(our_path+path);
  ret = "";
  for (i=0;i<sizeof(bing);i++)
    if (file_size(our_path+path+bing[i]) == -2) {
      if (bing[i][0] != '.')
        ret += sprintf("%c%s\t%s\t%s\t%d\n", '1',
                       replace_string(bing[i], "_", " "),
                       "1"+path+bing[i]+"/", MACHINE_NAME, GOPHER_PORT);
    } else {
/* Allow c files to be . files. */
      if (sscanf(bing[i], "%s.c", tmp)) {
/* If its a file, we do terribly silly things. */
        fn = replace_string(our_path+path+tmp, "//", "/");
        if (fn->query_invisible()) continue;
        type = fn->query_type();
        if (!(rest = fn->query_rest()))
          rest = MACHINE_NAME+"\t"+GOPHER_PORT;
        if (!(new_p = fn->query_path())) {
          new_p = sprintf("%c:exec:%s", type, path+bing[i]);
          if (!(name = fn->query_arg()))
            new_p += ":";
          else
            new_p += ":"+name;
        }
        if (!(name = fn->query_name()))
          name = replace_string(tmp, "_", " ");
        ret += sprintf("%c%s\t%s\t%s\n", type, name, new_p, rest);
      } else if (bing[i][0] != '.')
        ret += sprintf("%c%s\t%s\t%s\t%d\n", '0',
                       replace_string(bing[i], "_", " "),
                       "0"+path+bing[i], MACHINE_NAME, GOPHER_PORT);
    }
  return ret;
} /* create_menu() */

int check_path(string str) {
  if (sizeof(explode(str, "..")) > 1)
    return 0;
  return 1;
} /* check_path() */

void in_read_callback(int fd, string str) {
  int type;
  string path, *bits, arg, s1, s2;

  if (!in_progress[fd])
    in_progress[fd] = str;
  else
    in_progress[fd] += str;
  if (sscanf(str, "%s\n%s", s1, s2) != 2) {
/* We have to queue the damn thing... */
    return ;
  }
  str = in_progress[fd];
  map_delete(in_progress, fd);
  str = replace_string(str, "\n", "");
  str = replace_string(str, "\r", "");
  if (str == "" || str == "1") {
/* Root dir... */
    if (tack_on_mess) {
      socket_write(fd, create_menu("/")+tack_on_mess+".\n");
      tack_on_mess = 0;
    } else
      socket_write(fd, create_menu("/")+".\n");
/* I hope it does flushing... */
    socket_close(fd);
    return ;
  }
  if (sscanf(str, "%d:exec:%s", type, path) == 2) {
/* For use with the search facility */
    bits = explode(path, "\t");
    sscanf(bits[0], "%s:%s", bits[0], arg);
    bits[0] = our_path+bits[0];
    if (check_path(bits[0])) {/* Not allowed to have ..'s...  */
      bits[0] = replace_string(bits[0], "//", "/");
      if (type != 0 && tack_on_mess) {
        socket_write(fd, bits[0]->do_gopher(bits, arg, fd)+tack_on_mess+".\n");
        tack_on_mess = 0;
      } else
        socket_write(fd, bits[0]->do_gopher(bits, arg, fd)+".\n");
    } else {
      switch (type) {
        case 1 :
        case 7 :
          if (tack_on_mess) {
            socket_write(fd, "0Big nasty error\t0/error.error\t"+
                             "error.host\t70\n"+
                             "1Root menu\t\t"+MACHINE_NAME+"\t"+GOPHER_PORT+
                             "\n"+tack_on_mess+".\n");
            tack_on_mess = 0;
          } else
            socket_write(fd, "0Big nasty error\t0/error.error\t"+
                             "error.host\t70\n"+
                             "1Root menu\t\t"+MACHINE_NAME+"\t"+GOPHER_PORT+
                             "\n.\n");
          break;
        case 0 :
          socket_write(fd, "You have just encountered an error, "+
                           "lucky you.\n.\n");
          break;
      }
    }
    socket_close(fd);
    return ;
  }
  sscanf(str, "%d/%s", type, path);
  if (!path || !check_path(str)) {
    switch (type) {
      case 1 :
      case 7 :
        if (tack_on_mess) {
          socket_write(fd, "0Big nasty error\t0/error.error\terror.host\t70\n"+
                         "1Root menu\t\t"+MACHINE_NAME+"\t"+GOPHER_PORT+
                         "\n"+tack_on_mess+".\n");
          tack_on_mess = 0;
        } else
          socket_write(fd, "0Big nasty error\t0/error.error\terror.host\t70\n"+
                         "1Root menu\t\t"+MACHINE_NAME+"\t"+GOPHER_PORT+
                         "\n.\n");
        break;
      case 0 :
        socket_write(fd, "You have just encountered an error, "+
                         "lucky you.\n.\n");
        break;
    }
    socket_close(fd);
    return ;
  }
  path = "/"+path;
  switch (type) {
    case 0 :
/* Grab the file and give it to them. */
      str = read_file(our_path+path);
      if (!str) {
        str = "File requested was not found!  Oh no!  Find a hose clamp.\n";
      } else if (str[0] == '.') {
#ifdef NROFF_HAND
        NROFF_HAND->create_nroff(our_path+path, "/tmp/gopher");
        str = NROFF_HAND->cat_file("/tmp/gopher");
        rm("/tmp/gopher");
#endif
      }
      socket_write(fd, str+"\n.\n");
      break;
    case 1 :
      if (tack_on_mess) {
        socket_write(fd, create_menu(path)+tack_on_mess+".\n");
        tack_on_mess = 0;
      } else
        socket_write(fd, create_menu(path)+".\n");
      break;
  }
  socket_close(fd);
} /* in_read_callback() */

void in_close_callback(int fd) {
  socket_close(fd);
} /* in_close_callback() */
#endif /* GOPHER_PORT */

void set_tack_on_mess(string mess) { tack_on_mess = mess; }
string query_tack_on_mess() { return tack_on_mess; }