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/
/*
 * The wholely non useful inetd written by pinkfish@discworld.
 * Blue.
 */
#include "socket.h"

/*
 * inetd type means it all runs through ident's bound socket.
 * It does all sort of useful and hairy things this way.
 */
#define VALID_TYPE \
  ({ "mud", "tcp", "udp", "bin_tcp", "bin_udp", "inetd", "inetd_udp" })
#define INETD_TYPE 5
#define INETD_UDP_TYPE 5
#define CONFIG "/net/config/"
#define NAMESERVER "/net/nameserver"

#undef DEBUG
#define TC(STR)

/* This is indexed by file descriptor */
mapping services,
        to_go,
        my_valid,
        close_it;
int my_socket;

void load_config(string str);
void close_callback(int fd);

void create() {
  seteuid(getuid());
  services = ([ ]);
  to_go = ([ ]);
  my_valid = ([ ]);
  close_it = ([ ]);
  load_config(CONFIG+"inetd");
} /* create() */

/* Make sure our inetd server is running */
void connect_inetd() {
  if (my_socket) /* Already up */
    return ;
  my_socket = socket_create(STREAM, "inetd_read", "close_callback");
  if (my_socket < 0) {
    write_file("/log/INETD", "Failed to find service create socket "+
               socket_error(my_socket)+".\n");
    return ;
  }
  NAMESERVER->lookup_service("inetd", mud_name(), "finish_lookup");
} /* connect_inetd() */

void finish_lookup(string name, string host, int port) {
  int ret;

  if (!port) {
    log_file("INETD", "Failed to lookup service "+name+"\n");
    return ;
  }
  ret = socket_bind(my_socket, port);
  if (ret < 0) {
    socket_close(my_socket);
    my_socket = 0;
    write_file("/log/INETD", "Failed to bind socket for "+name+
               "-"+socket_error(my_socket)+".\n");
    return ;
  }
  ret = socket_listen(my_socket, "inetd_connect");
  if (ret < 0) {
    socket_close(my_socket);
    my_socket = 0;
    write_file("/log/INETD", "Failed to listen socket for "+name+
               "-"+socket_error(my_socket)+".\n");
    return ;
  }
} /* finish_lookup() */

void load_config(string name) {
  string data,
         str, file,
         *lines;
  int i, type;

  data = read_file(name);
  if (!data) return ;
  data = implode(explode(data, " ") - ({ "" }), " ");
  lines = explode(data, "\n");
  for (i=0;i<sizeof(lines);i++) {
    while (strlen(lines[i]) && lines[i][0] == ' ')
      lines[i] = lines[i][1..1000];
    if (!strlen(lines[i]) || lines[i][0] == '#') continue;
    TC("Checking line "+lines[i]+"\n");
    if (sscanf(lines[i], "%s %s %s", name, str, file) == 3) {
      if ((type = member_array(str, VALID_TYPE)) == -1)
        continue;
      if (type == INETD_TYPE) {
        my_valid[name] = file;
        connect_inetd();
      } else {
        TC("Looking up "+name+".\n");
        NAMESERVER->lookup_service(name, mud_name(), "found_service",
                                 ({ type, file }));
      }
    } else
      log_file("INETD","Invalid line in "+name+", "+lines[i]+"\n");
  }
} /* load_config() */

void found_service(string name, string host, int port, mixed args) {
  int fd, ret;

  TC(sprintf("found_service called with %O, %O, %O.\n", name, host, port));
/* Failed :( */
  if (!port) {
    write_file("/log/INETD", "Failed to find service "+name+".\n");
    return ;
  }
/* Ok...  we have a service...  so set ourselves up a look thingy */
  fd = socket_create(args[0], "read_callback", "close_callback");
  if (fd < 0) {
    write_file("/log/INETD", "Failed to create socket for "+name+
               "-"+socket_error(fd)+".\n");
    return ;
  }
  ret = socket_bind(fd, port);
  if (ret < 0) {
    socket_close(fd);
    write_file("/log/INETD", "Failed to bind socket for "+name+
               "-"+socket_error(fd)+".\n");
    return ;
  }
  if (args[0] != DATAGRAM) {
    ret = socket_listen(fd, "listen_callback");
    if (ret < 0) {
      socket_close(fd);
      write_file("/log/INETD", "Failed to listen socket for "+name+
               "-"+socket_error(fd)+".\n");
      return ;
    }
  }
/* Ok...  tis setup.  Bing! */
/* Do we need to remember what port we are on?  Nahhh... */
  services[fd] = args[1];
} /* found_service() */

void read_callback(int fd, string str, string addr) {
  string file;

  file = services[fd];
  if (!file) {
    socket_close(fd);
    return ;
  }
  file->read_callback(fd, str, addr);
} /* read_callback() */

void write_callback(int fd) {
  int last, i;

  if (!to_go[fd])
    to_go[fd] = 1;
  if (!pointerp(to_go[fd])) {
    services[fd]->write_callback(fd);
    return ;
  }
  while (sizeof(to_go[fd]) && (last = socket_write(fd, to_go[fd][0])) >= 0)
    to_go[fd] = to_go[fd][1..100];
  if (!sizeof(to_go[fd])) {
    to_go[fd] = (last >= 0);
    if (to_go[fd]) {
      if (close_it[fd]) {
        close_callback(fd);
        map_delete(close_it, fd);
      } else
        services[fd]->write_callback(fd);
    }
  }
} /* write_callback() */

void write_fd(int fd, mixed mess) {
  int bing;

/* Security violation... */
  if (previous_object() != this_object() &&
      previous_object() != services[fd] &&
      file_name(previous_object()) != services[fd]) {
    event(users(), "inform", "Security violation in /net/inetd.c ("+
                   file_name(previous_object())+" : "+services[fd]+")",
                   "cheat");
    return ;
  }
  if (!pointerp(to_go[fd])) {
/*
 * If in here there is nothing in the queue already.  so we assume we can
 * send down the link.
 */
    to_go[fd] = ({ mess });
    bing = 1;
  } else
    to_go[fd] += ({ mess });
  if (bing)
    write_callback(fd);
} /* write_fd() */

/*
 * This sets the close_it flag or closes it immediately if there is
 * nothing to go and we have the correct flags.
 */
void close_fd(int fd) {
  int bing;

  if (previous_object() != this_object() &&
      previous_object() != services[fd] &&
      file_name(previous_object()) != services[fd]) {
    event(users(), "inform", "Security violation in /net/inetd.c ("+
                   file_name(previous_object())+" : "+services[fd]+")",
                   "cheat");
    return ;
  }
  bing = intp(to_go[fd]) && to_go[fd];
  if (bing) {
    close_callback(fd);
  } else
    close_it[fd] = 1;
} /* close_fd() */

void close_callback(int fd) {
  if (!services[fd])
    return ;
  if (catch(services[fd]->close_callback(fd))) {
    if (services[fd] == "waiting")
      my_valid[fd][1]->close_callback(fd);
    TC("Error "+fd+sprintf("%O\n", my_valid[fd]));
  }
  map_delete(services, fd);
  map_delete(my_valid, fd);
/* Just to make sure... */
  socket_close(fd);
} /* close_callback() */

void listen_callback(int fd) {
  int new_fd;

  if ((new_fd = socket_accept(fd, "read_callback", "write_callback")) < 0) {
    write_file("/log/INETD", "Failed to accept a connection "+
               "-"+socket_error(new_fd)+".\n");
    return ;
  }
  services[new_fd] = services[fd];
/* whats all this then? */
  call_out("close_callback", 5*60*60, new_fd);
  to_go[new_fd] = 1;
} /* listen_callback() */

void inetd_connect(int fd) {
  int new_fd;

  if ((new_fd = socket_accept(fd, "inetd_read", "inetd_write")) < 0) {
    write_file("/log/INETD", "Failed to accept a connection "+
               "-"+socket_error(new_fd)+".\n");
    return ;
  }
  services[new_fd] = "request";
  socket_write(new_fd, "SERVICE?\n");
  to_go[new_fd] = 1;
  call_out("close_callback", 5*60*60, new_fd);
} /* inetd_connect() */

void inetd_read(int fd, string mess) {
  string *bits;

  if (!services[fd]) {
    socket_close(fd);
    return ;
  }
  switch (services[fd]) {
    case "waiting" :
/* Should be asking us for a service... */
      if (!my_valid[fd]) {
        socket_close(fd);
        return ;
      }
      if (mess == "SERVICE?\n") {
/* They are... */
/*
 * The old one doesnt use a response code....  so...  We won't
 * either for now.
        services[fd] = "response";
 */
        if (my_valid[fd][2])
          socket_write(fd, my_valid[fd][0]+" "+my_valid[fd][2]+"\n");
        else
          socket_write(fd, my_valid[fd][0]+"\n");
        services[fd] = my_valid[fd][1];
        map_delete(my_valid, fd);
        services[fd]->connected(fd);
      }
      return ;
    case "response" :
      if (mess == "YES!\n") {
/* Ok!  Bings are us */
        if (!my_valid[fd]) {
          socket_close(fd);
          return ;
        }
        services[fd] = my_valid[fd][1];
        map_delete(my_valid, fd);
        services[fd]->connected(fd);
      } else {
        socket_close(fd);
        if (my_valid[fd])
          my_valid[fd][1]->failed("unknow service");
        map_delete(my_valid, fd);
        return ;
      }
      return ;
    case "request" :
      bits = explode(mess, "\n");
      if (sscanf(bits[0], "%s %s", bits[0], mess) == 2)
        bits = ({ bits[0], mess }) + bits[1..1000];
      bits = explode(bits[0], " ")+bits[1..1000];
      return ;
  }
} /* inetd_read() */

void inetd_write(int fd) {
  if (!services[fd]) {
    socket_close(fd);
    return ;
  }
  switch (services[fd]) {
    case "response" :
    case "waiting" :
    case "request" :
      to_go[fd] = 1;
      return ;
    default :
      write_callback(fd);
      return ;
  }
} /* inetd_write() */

/*
 * Sends a message off to the destination service, with closeing
 * and opening of sockets etc done all for you.
 * Maybe useful, dubious.
 */
void datagram_message(string name, string dest, string mess) {
  NAMESERVER->lookup_service(name, dest, "finish_datagram_open",
                             ({ previous_object(), name, mess }));
} /* datagram_message() */

/*
 * The last paramater bing is used for compatability with an older
 * version of inetd.  Please do not use this in any new daemons you
 * create.  I consider it somewhat of a hack.  This is also only
 * used in the INETD_TYPE case, not for streams or mud connections.
 */
void open_to_service(string name, int type, string dest, string bing) {
  if (type == DATAGRAM) {
/*
 * What we do here is resolv a named [port thingy and return that to
 * the calling object...
 */
    previous_object()->failed("unsupported type", dest, name, bing);
    return ;
  }
  if (type == INETD_TYPE) {
    NAMESERVER->lookup_service("inetd", dest, "finish_inet_open", 
                                ({ previous_object(), name, bing }));
    return ;
  }
/* Else.... */
  NAMESERVER->lookup_service(name, dest, "finish_open",
                             ({ previous_object(), type }));
} /* open_to_service() */

void finish_open(string name, string host, int port, mixed *args) {
  int new_fd, ret;

  if (!args[0])
    return ;
  if (!port) {
    args[0]->failed("lookup", host, name, args[1]);
    return ;
  }
  new_fd = socket_create(args[1], "read_callback", "close_callback");
  if (new_fd < 0) {
    args[0]->failed("socket_create", host, name, args[1], new_fd);
    return ;
  }
  ret = socket_connect(new_fd, host+" "+port, "read_callback",
                       "write_callback");
  if (ret < 0) {
    socket_close(new_fd);
    args[0]->failed("socket_connect", host, name, args[1], new_fd);
    return ;
  }
  call_out("close_callback", 5*60*60, new_fd);
  services[new_fd] = file_name(args[0]);
  to_go[new_fd] = 1;
  args[0]->connected(new_fd, host);
} /* finish_open() */

void finish_inet_open(string name, string host, int port, mixed *args) {
  int new_fd, ret;

  if (!args[0])
    return ;
  if (!port) {
    args[0]->failed("lookup", name, args[1], host);
    return ;
  }
  new_fd = socket_create(STREAM, "inetd_read", "close_callback");
  if (new_fd < 0) {
    args[0]->failed("socket_create", name, args[1], host, new_fd);
    return ;
  }
  ret = socket_connect(new_fd, host+" "+port, "inetd_read",
                       "inetd_write");
  if (ret < 0) {
    socket_close(new_fd);
    args[0]->failed("socket_connect", name, args[1], host, new_fd);
    return ;
  }
  call_out("close_callback", 5*60*60, new_fd);
  my_valid[new_fd] = ({ args[1], file_name(args[0]), args[2] });
  services[new_fd] = "waiting";
  TC("Opening "+new_fd+"\n");
} /* finish_inet_open() */

void finish_datagram_open(string name, string host, int port, mixed *args) {
  int s;

  TC(sprintf("Called datagram with: %O, %O, %O\n", name, host, port));
  if (!port) {
    if (args[0])
      args[0]->failed("lookup", name, args[1], host);
    return ;
  }
  s = socket_create(DATAGRAM, "blurble");
  if (s < 0) {
    if (args[0]) {
      args[0]->failed("socket_create", name, args[1], host);
    }
    return ;
  }
  if (socket_write(s, args[2], host+" "+port) < 0) {
/* Tarnation... */
    if (args[0])
      args[0]->failed("socket_write", name, args[1], host);
    TC("Failed.\n");
  }
  socket_close(s);
} /* finish_datagram_open() */