Weitgehender Neubau auf intermud-2.5.
Benutzt moderne LDMud-3.5-Sprachmittel wie structs.
diff --git a/secure/inetd.c b/secure/inetd.c
index d015602..a139de6 100644
--- a/secure/inetd.c
+++ b/secure/inetd.c
@@ -1,808 +1,51 @@
-/*
- * UDP port handling code. Version 0.7a
- * Written by Nostradamus for Zebedee.
- * Developed from an original concept by Alvin@Sushi.
- */
+#pragma strict_types, save_types, rtt_checks, pedantic
+#pragma no_clone, no_shadow, no_inherit
 
-#pragma strict_types
-#pragma no_clone
-#pragma no_shadow
-#pragma no_inherit
-#pragma verbose_errors
-//#pragma pedantic
-#pragma no_range_check
-#pragma no_warn_deprecated
+// inherit the basic inetd
+inherit __DIR__/_inetd.c
 
-/*
 #include <living/comm.h>
-#define ZDEBUG(x)        if (find_player("zesstra"))\
-            find_player("zesstra")->ReceiveMsg(x, \
-                MT_DEBUG|MSG_DONT_STORE,0,"IM: ",this_object())
-*/
-#define ZDEBUG(x)
 
-#include <udp.h>
-
-/* --- Configurable definitions. --- */
-
-/* CD muds will probably need these include file. */
-/* #include <std.h> */
-/* #include "/config/sys/local.h" */
-
-/* Public commands which will be accessible to any unlisted muds.
- * PING, QUERY and REPLY are included by default. */
-#define COMMANDS \
-({ "channel", "finger", "tell", "who", "mail", "www", "htmlwho", "locate" })
-
-//({ "channel", "finger", "ftp", "locate", "man", "tell", "who" })
-
-/* Define this to the object that receives incoming packets and passes
- * them to the inetd. Undefine for no _receive_udp() security.
- * NOTE: The string must be of the format that object_name() returns. */
-#define UDP_MASTER                __MASTER_OBJECT__
-
-/* How to set the euid for this object if using native mode.
- * Ensure that it can read the INETD_HOSTS file. */
-#define SET_EUID                seteuid(getuid())
-
-/* Define this if you are running another intermud package concurrently. */
-/* #define RECEIVE_UDP_COMPAT(sender, packet) \
-                UDP_MANAGER->incoming_udp(sender, packet)        // CD */
-
-/* Define this if you are running another intermud package concurrently and
- * have a compatability module for it. */
-/* #define SEND_UDP_COMPAT(mudname, data, expect_reply) \
-                "/secure/udp_compat"->_send_udp(mudname, data, expect_reply) */
-
-/* The maximum number of characters we can send in one packet.
- * You may need to reduce this, but 512 should be safe. */
-#define MAX_PACKET_LEN        1024
-
-/* You shouldn't need to change anything below. */
-
-#define USE_OLD_DELIMITER
-//#define DELIMITER_COMPAT
-#define USE_OLD_DATA_FORMAT
-
-#ifdef ZEBEDEE
-#include <defs.h>
-#endif
-
-#ifndef DATE
-#define DATE                ctime(time())[4..15]
-#endif
-
-/* --- End of Config. Do not alter anything below. --- */
-
-#define UNKNOWN                0
-#define UP                time()
-#define DOWN                (-time())
-
-#define NEW_DELIMITER        "\n"
-#ifdef USE_OLD_DELIMITER
-#define DELIMITER        "|"
-#else
-#define DELIMITER        "\n"
-#endif
-#define OLD_DELIMITER        "|"
-#define HOSTFILE_DEL        ":"
-#define HOSTFILE_DEL2        ","
-#define RETRY                "_RETRY"
-
-private nosave mapping hosts, pending_data, incoming_packets;
-private nosave mapping static_host_list;
-private nosave string *received_ids;
-private nosave int packet_id;
-
-void set_host_list();
-varargs string _send_udp(string mudname, mapping data, int expect_reply);
-
-#define DEBUG(msg)
-
-void my_create() {
-#ifndef COMPAT_FLAG
-    SET_EUID;
-#endif
-    packet_id = 0;
-    pending_data = ([ ]);
-    incoming_packets = ([ ]);
-    hosts = ([ ]);
-    received_ids = ({ });
-    set_host_list();
-    if (!this_player())
-        call_out("startup", 1, 0);
+// and implement mud-individual stuff that should be implemented as needed. If
+// the default is fine for your mud, keep it.
+protected void set_user()
+{
+  seteuid(getuid());
 }
 
-#ifdef CREATE_FUN
-CREATE_FUN() {
-#elif !defined(COMPAT_FLAG) || defined(ZEBEDEE)
-void create() {
-#else
-void reset(arg) {
-    if (arg)
-        return;
-#endif
-    my_create();
+protected void save_me()
+{
+  save_object(__DIR__"ARCH/inetd");
 }
 
-status check_system_field(mapping data, string field) {
-    return data[SYSTEM] && member(data[SYSTEM], field) != -1;
+protected int restore_me()
+{
+  return restore_object(__DIR__"ARCH/inetd");
 }
 
-mapping add_system_field(mapping data, string field) {
-    if (data[SYSTEM]) {
-        if (!check_system_field(data, field))
-            data[SYSTEM] += ({ field });
-    }
-    else
-        data[SYSTEM] = ({ field });
-    return data;
+protected void export_peer_list(mapping list)
+{
 }
 
-private mapping read_host_list(string file) {
-
-  mixed data = (read_file(file));
-  if (!data) {
-    log_file(INETD_LOG_FILE, "*Error in reading host file: "
-        + file +"\n\n");
-    return 0;
-  }
-
-  data = old_explode(data, "\n");
-  mapping new_hosts = m_allocate(sizeof(data),1);
-
-  foreach(string line: data) {
-    if (line == "" || line[0] == '#')
-      continue;
-    mixed fields = old_explode(line, HOSTFILE_DEL);
-    if (sizeof(fields) < 5) {
-      log_file(INETD_LOG_FILE, sprintf(
-            "*Parse error in hosts file: %s, Line: %s\n", file, line));
-      continue;
-    }
-
-    string name = lower_case(fields[HOST_NAME]);
-    if (member(new_hosts, name))
-      continue; // mud already in list
-
-    string *local_cmds = old_explode(fields[LOCAL_COMMANDS],HOSTFILE_DEL2);
-    if (member(local_cmds,"*") != -1)
-        local_cmds = local_cmds - ({ "*" }) + COMMANDS;
-    
-    new_hosts[name] = ({ capitalize(fields[HOST_NAME]),
-                     fields[HOST_IP],
-                     to_int(fields[HOST_UDP_PORT]),
-                     local_cmds,
-                     old_explode(fields[HOST_COMMANDS], HOSTFILE_DEL2),
-                     UNKNOWN
-                   });
-    /*
-     * Get existing host status from current active host lost as long as the
-     * IP and UDP ports are the same.
-     */
-    if (hosts[name] &&
-        hosts[name][HOST_IP] == new_hosts[name][HOST_IP] &&
-        hosts[name][HOST_UDP_PORT] == new_hosts[name][HOST_UDP_PORT])
-        new_hosts[name][HOST_STATUS] = hosts[name][HOST_STATUS];
-  }
-  return new_hosts;
+protected void debug_msg(string msg)
+{
+  object z=find_player("zesstra");
+  if (z)
+    z->ReceiveMsg(msg, MT_DEBUG, 0, "IM: ", this_object());
 }
 
-/*
- * Read the INETD_HOSTS file and set the "hosts" mapping from it.
- * Retain existing HOST_STATUS fields.
- * Reads INETD_HOSTSS and INETD_HOSTS.dump
- * Hosts from INETD_HOSTS are included in the static host list.
- */
-void set_host_list() {
-
-  // read the static host file and the last host file dump.
-  mapping static_hosts = read_host_list(HOST_FILE);
-  if (!static_hosts)
-      return; // retain the old list(s)
-
-  // remember the static hosts
-  static_host_list = m_reallocate(static_hosts,0);
-  
-  // read the last host file dump and add the static hosts. Then the static
-  // hosts have precedence over the ones from the dump.
-  hosts = (read_host_list(HOST_FILE".dump") || ([])) + static_hosts;
-
+public void receive(string host, string msg, int hostport)
+{
+  if (previous_object() == master())
+    process_fragment(host, msg, hostport);
 }
 
-mixed get_hosts() {return copy(hosts);}
-
-int  dump_hosts_list() {
-  
-  write_file(HOST_FILE+".dump", sprintf(
-    "#Hostlist dump from "MUDNAME", created %s\n", strftime()), 1);
-
-  foreach(string mudname, mixed tmp : hosts) {
-    // skip muds we did not hear from for 2 days.
-//    if (tmp[HOST_STATUS] + 172800 < time())
-//      continue;
-    write_file(HOST_FILE+".dump",
-        sprintf("%s:%s:%d:%s:%s\n",tmp[0],tmp[1],tmp[2],implode(tmp[3],","),
-          implode(tmp[4],",")));
-  }
-  return 1;
-}
-
-/*
- * Make a PING request to all muds in the "hosts" mapping to set
- * HOST_STATUS information.
- * But don't ping all muds at once, because that may overflow the callout
- * table during mud startup, when hundreds of objects make callouts.
- */
-void startup(string *muds) {
-
-    if (!pointerp(muds))
-      muds=m_indices(hosts);
-    if (!sizeof(muds))
-      return;
-    string *part;
-    if (sizeof(muds) > 9)
-      part=muds[0..9];
-    else
-      part=muds;
-    foreach(string mud: part) 
-      _send_udp(mud, ([ REQUEST: PING ]), 1);
-    muds -= part;
-    if (sizeof(muds))
-      call_out(#'startup, 4, muds);
-}
-
-/*
- * Remove a buffered packet from the "incoming_packets" mapping.
- */
-void remove_incoming(string id) {
-    m_delete(incoming_packets, id);
-}
-
-/*
- * Decode a string from a UDP packet.
- * Returns:   The actual value of the argument (either int or string)
- */
-mixed decode(string arg) {
-
-    if (sizeof(arg) && arg[0] == '$')
-        return arg[1..];
-#ifdef RESTRICTED_CASTS
-    if (to_string(to_int(arg)) == arg)
-        return to_int(arg);
-#else
-    if ((string)((int)arg) == arg)
-        return (int)arg;
-#endif
-    return arg;
-}
-
-/*
- * Decode a UDP packet.
- * Arguments: UDP packet as a string.
- * Returns:   The decoded information as a mapping, 1 for succes but no
- *            output (buffered packet), or 0 on error.
- */
-mixed decode_packet(string packet, string delimiter) {
-    string *data;
-    mapping ret;
-    string info, tmp;
-    mixed class;
-    int i, id, n;
-
-    /* If this packet has been split, handle buffering. */
-    if (packet[0..sizeof(PACKET)] == PACKET + ":") {
-        if (sscanf(packet, PACKET + ":%s:%d:%d/%d" + delimiter + "%s",
-        class, id, i, n, tmp) != 5)
-            return 0;
-        class = lower_case(class) + ":" + id;
-        if (pointerp(incoming_packets[class])) {
-            incoming_packets[class][i-1] = tmp;
-            if (member(incoming_packets[class], 0) == -1) {
-                ret =
-                decode_packet(implode(incoming_packets[class], ""), delimiter);
-                remove_incoming(class);
-                return ret;
-            }
-        } else {
-            incoming_packets[class] = allocate(n);
-            incoming_packets[class][i-1] = tmp;
-/* Is it possible to already have a timeout running here ?!? */
-            /* If no timeout is running then start one. */
-            if (!pending_data[class]) {
-                call_out("remove_incoming",
-                REPLY_TIME_OUT + REPLY_TIME_OUT * RETRIES, class);
-            } else {
-                DEBUG("\nINETD: *** Buffered packet Timeout already running! ***\n");
-            }
-        }
-        return 1;
-    }
-    ret = ([ ]);
-    for(i = 0, n = sizeof(data = old_explode(packet, delimiter)); i < n; i++) {
-        /* DATA fields can be denoted by a preceeding blank field. */
-        if (data[i] == "") {
-            tmp = DATA;
-            /* Test for illegal packet length (no DATA) */
-            if (++i >= n)
-                return 0;
-            info = data[i];
-        }
-        else if (sscanf(data[i], "%s:%s", tmp, info) != 2)
-            return 0;
-        switch((string)(class = decode(tmp))) {
-            case DATA:
-#ifdef USE_EXTRACT
-                return ret + ([ DATA: decode(implode(
-                    ({ info }) + extract(data, i+1), delimiter)) ]);
-#else
-                return ret + ([ DATA: decode(implode(
-                    ({ info }) + data[i+1..], delimiter)) ]);
-#endif
-            case SYSTEM:
-                ret[class] = old_explode(info, ":");
-                continue;
-            default:
-                ret[class] = decode(info);
-                continue;
-        }
-    }
-    return ret;
-}
-
-/* Check wether a UDP packet was valid.
- * Logs are made and "host" information is updated as appropriate.
- * Arguments: Decoded UDP packet (mapping)
- * Returns:   0 for valid packets, an error string otherwise.
- */
-string valid_request(mapping data) {
-    mixed host_data;
-    string *muds;
-    string req;
-    int i;
-    
-    if (!data[NAME] || !data[UDP_PORT])
-        return DATE + ": Illegal packet.\n";
-    if (host_data = hosts[lower_case(data[NAME])]) {
-        if (data[HOST] != host_data[HOST_IP]) {
-            if (data[NAME] == LOCAL_NAME)
-                return DATE + ": *** FAKE MUD ***\n";
-            log_file(INETD_LOG_FILE, DATE + ": Host change:\n" +
-            host_data[HOST_NAME] + ": " + host_data[HOST_IP] + " -> " +
-            data[HOST] + "\n\n");
-            host_data[HOST_IP] = data[HOST];
-        }
-        if (data[UDP_PORT] != host_data[HOST_UDP_PORT]) {
-            if (data[NAME] == LOCAL_NAME)
-                return DATE + ": *** FAKE MUD ***\n";
-            log_file(INETD_LOG_FILE, DATE + ": Port change:\n" +
-                host_data[HOST_NAME] + " (" + host_data[HOST_IP] + "): " +
-                host_data[HOST_UDP_PORT] + " -> " + data[UDP_PORT] + "\n\n");
-            host_data[HOST_UDP_PORT] = data[UDP_PORT];
-        }
-    } else {
-        if (lower_case(data[NAME]) == lower_case(LOCAL_NAME))
-            return DATE + ": *** FAKE MUD ***\n";
-        for(i = sizeof(muds = m_indices(hosts)); i--; ) {
-            host_data = hosts[muds[i]];
-            if (data[HOST] == host_data[HOST_IP] &&
-            data[UDP_PORT] == host_data[HOST_UDP_PORT]) {
-                log_file(INETD_LOG_FILE, DATE + ": Name change:\n" +
-                    host_data[HOST_NAME] + " (" + host_data[HOST_IP] +
-                    ") -> " + data[NAME] + "\n\n");
-                host_data[HOST_NAME] = data[NAME];
-                hosts[lower_case(data[NAME])] = host_data;
-                m_delete(hosts, muds[i]);
-                i = -2;
-                break;
-            }
-        }
-        if (i != -2) {
-            host_data = hosts[lower_case(data[NAME])] = ({
-                data[NAME],
-                data[HOST],
-                data[UDP_PORT],
-                COMMANDS,
-                ({ "*" }),
-                UP
-            });
-            log_file(INETD_LOG_FILE, DATE + ": New mud.\n" + data[NAME] + ":" +
-            data[HOST] + ":" + data[UDP_PORT] + "\n\n");
-        }
-    }
-    if (!(req = data[REQUEST]))
-        return DATE + ": System message.\n";
-    if (req != PING &&
-        req != QUERY &&
-        req != REPLY &&
-        member(host_data[LOCAL_COMMANDS], req) == -1)
-    {
-        /* This should probably send a system message too. */
-        _send_udp(host_data[HOST_NAME], ([
-            REQUEST: REPLY,
-            RECIPIENT: data[SENDER],
-            ID: data[ID],
-            DATA: "Invalid request @" + LOCAL_NAME + ": " +
-                capitalize(data[REQUEST]) + "\n"
-        ]) );
-        return DATE + ": Invalid request.\n";
-    }
-    return 0;
-}
-
-/*
- * Incoming UDP packets are sent to this function to be interpretted.
- * The packet is decoded, checked for validity, HOST_STATUS is updated
- * and the appropriate udp module called.
- * Arguments: Senders IP address (string)
- *            UDP packet (string)
- */
-void _receive_udp(string sender, string packet) {
-    mapping data;
-    string req, err, id;
-
-#ifdef UDP_MASTER
-    if (!previous_object() ||
-    object_name(previous_object()) != UDP_MASTER) {
-        log_file(INETD_LOG_FILE, DATE + ": Illegal call of _receive_udp() by " +
-        object_name(previous_object()) + "\n\n");
-        return;
-    }
-#endif
-
-    ZDEBUG(sprintf("%O -> %.500O\n",sender, packet));
-    if (
-#ifdef DELIMITER_COMPAT
-#ifdef USE_EXTRACT
-        (!(data = decode_packet(packet, NEW_DELIMITER))
-#else
-        (!(data = decode_packet(packet, NEW_DELIMITER))
-#endif
-        || (data[HOST] = sender) && (err = valid_request(data))) &&
-        (!(data = decode_packet(packet, OLD_DELIMITER)) ||
-        (data[HOST] = sender) && (err = valid_request(data)))
-#else
-#ifdef USE_EXTRACT
-        !(data = decode_packet(packet, DELIMITER))
-#else
-        !(data = decode_packet(packet, DELIMITER))
-#endif
-#endif
-    ) {
-        if (!data)
-#ifdef RECEIVE_UDP_COMPAT
-            RECEIVE_UDP_COMPAT(sender, packet);
-#else
-            log_file(INETD_LOG_FILE, DATE + ": Received invalid packet.\nSender: " +
-            sender + "\nPacket:\n" + packet + "\n\n");
-#endif
-        return;
-    }
-#ifdef DELIMITER_COMPAT
-    if (!mappingp(data))
-        return;
-    if (err)
-#else
-          if (!mappingp(data))
-                  return;
-    data[HOST] = sender;
-    if (err = valid_request(data))
-#endif
-    {
-        log_file(INETD_LOG_FILE, err + "Sender: " + sender + "\nPacket:\n" +
-        packet + "\n\n");
-        return;
-    }
-    hosts[lower_case(data[NAME])][HOST_STATUS] = UP;
-    if ((req = data[REQUEST]) == REPLY) {
-            mapping pending;
-
-        /* If we can't find the reply in the pending list then bin it. */
-        if (!(pending = pending_data[lower_case(data[NAME]) + ":" + data[ID]]))
-            return;
-        /* Set data[REQUEST] correctly, but still send to (req = REPLY) */
-        data[REQUEST] = pending[REQUEST];
-#ifdef INETD_DIAGNOSTICS
-        data[PACKET_LOSS] = pending[PACKET_LOSS];
-        data[RESPONSE_TIME] = time() - pending[RESPONSE_TIME] + 1;
-#endif
-#if 0
-/* channel replies may not include a recipient, and shouldn't have one set */
-        /* Restore the RECIPIENT in replies if none given and it is known. */
-        if (!data[RECIPIENT] && pending[SENDER])
-            data[RECIPIENT] = pending[SENDER];
-#endif
-        m_delete(pending_data, lower_case(data[NAME]) + ":" + data[ID]);
-    }
-    else if (data[ID]) {
-      id = lower_case(data[NAME]) + ":" + data[ID];
-      if (member(received_ids, id) == -1)
-      {
-        received_ids += ({ id });
-        call_out("remove_received_id",
-              REPLY_TIME_OUT + REPLY_TIME_OUT * (RETRIES + 1), id);
-      }
-      else
-            add_system_field(data, REPEAT);
-    }
-    if (err = catch(
-        call_other(UDP_CMD_DIR + req, "udp_" + req, deep_copy(data));publish))
-    {
-        _send_udp(data[NAME], ([
-            REQUEST: REPLY,
-            RECIPIENT: data[SENDER],
-            ID: data[ID],
-            DATA: capitalize(req)+ " request failed @" + LOCAL_NAME + ".\n"
-        ]) );
-        log_file(INETD_LOG_FILE, DATE + ": " + data[REQUEST] + " from " +
-        data[NAME] + " failed.\n" + err + packet + "\n\n");
-    }
-}
-
-int do_match(string mudname, string match_str) {
-    return mudname[0..sizeof(match_str)-1] == match_str;
-}
-
-#ifdef NO_CLOSURES
-
-status greater(mixed a, mixed b) {
-    return a > b;
-}
-
-string *expand_mud_name(string name) {
-    return sort_array(
-        filter(m_indices(hosts), "do_match", this_object(), name),
-        "greater",
-        this_object()
-    );
-}
-
-#else
-
-string *expand_mud_name(string name) {
-    return sort_array(
-        filter(m_indices(hosts), #'do_match, name),
-        #'>
-    );
-}
-
-#endif
-
-string encode(mixed arg) {
-    if (objectp(arg))
-        return object_name(arg);
-    if (stringp(arg) && sizeof(arg) &&
-        (arg[0] == '$' ||
-#ifdef RESTRICTED_CASTS
-    to_string(to_int(arg)) == (string)arg))
-#else
-    (string)to_int(arg) == (string)arg))
-#endif
-        return "$" + arg;
-    return to_string(arg);
-}
-
-string encode_packet(mapping data) {
-    int i;
-    mixed indices;
-    string header, body, t1, t2;
-    string *ret;
-    status data_flag;
-
-    for(ret = ({ }), i = sizeof(indices = m_indices(data)); i--; ) {
-        if (indices[i] == DATA) {
-            data_flag = 1;
-            continue;
-        }
-        header = encode(indices[i]);
-        body = encode(data[indices[i]]);
-        if (sscanf(header, "%s:%s", t1, t2) ||
-            sscanf(header + body, "%s" + DELIMITER + "%s", t1, t2)
-        )
-            return 0;
-        
-        ret += ({ header + ":" + body });
-    }
-    if (data_flag)
-#ifdef USE_OLD_DATA_FORMAT
-        ret += ({ DATA + ":" + encode(data[DATA]) });
-#else
-        ret += ({ "", encode(data[DATA]) });
-#endif
-    return implode(ret, DELIMITER);
-}
-
-// Funktion explode_
-// Die Funktion zerlegt den String packet in gleich lange Teilstrings
-// der Laenge len und gibt die Teilstrings als Array zurueck. Der letzte
-// Teilstring kann kuerzer sein als die anderen.
-string *explode_packet(string packet, int len) {
-
-  int ptr, m_ptr,size;
-  string *result;
-
-  // Variablen initialisieren
-  m_ptr=ptr=0;
-  size=sizeof(packet);
-  result=({});
-
-  // Um Arrayadditionen zu vermeiden wird vorher allokiert. Die Division 
-  // durch 0 ist nicht abgefangen, da bei len=0 was im Aufruf falch ist.
-  result=allocate((size/len+1));
-
-  while (ptr<size) {
-    result[m_ptr] = // Aktuellen Teilstring speichern
-#ifdef USE_EXTRACT
-            extract(packet,ptr,ptr+len-1);
-#else
-            packet[ptr..ptr+len-1]; 
-#endif
-    ptr+=len;// Neuen Pointer im String berechnen
-    m_ptr++; // Neuen Pointer im Mapping berechnen. Hier nutze ich eine
-             // Variable mehr als noetig, weil das billiger ist, als jedes
-             // mal ptr=m_ptr*len auszurechnen. Lieber zwei Additionen als 
-             // eine Multiplikation und eine Addtion.
-  }
-
-  // Wenn size/len aufgeht, ist das Result-Feld zu gross. Dann bleibt 
-  // ein Element leer, das wird hier gestrippt. Das ist billiger als
-  // jedesmal auszurechnen, ob size/len aufgeht.
-  return result-({0});
- 
-}
-
-varargs string _send_udp(string mudname, mapping data, int expect_reply) {
-    mixed host_data;
-    string *packet_arr;
-    string packet;
-    int i;
-
-    mudname = lower_case(mudname);
-    if (!(host_data = hosts[mudname])) {
-        string *names;
-
-        if (sizeof(names = expand_mud_name(mudname)) == 1)
-            host_data = hosts[mudname = names[0]];
-        else
-#ifdef SEND_UDP_COMPAT
-            return (string)SEND_UDP_COMPAT(mudname, data, expect_reply);
-#else
-        if (!sizeof(names))
-            return "Unbekannter Mudname: " + capitalize(mudname) + "\n";
-        else
-            return break_string("Mudname ("+capitalize(mudname)+
-            ") nicht eindeutig, es passen: "+implode(map(names,#'capitalize),", ")+
-            ".\n",78);
-#endif
-    }
-    
-    if (data[REQUEST] != PING &&
-        data[REQUEST] != QUERY &&
-        data[REQUEST] != REPLY &&
-        member(host_data[HOST_COMMANDS], "*") == -1 &&
-        member(host_data[HOST_COMMANDS], data[REQUEST]) == -1)
-        return capitalize(data[REQUEST]) + ": Command unavailable @" +
-                   host_data[HOST_NAME] + "\n";
-    
-    data[NAME] = LOCAL_NAME;
-    data[UDP_PORT] = LOCAL_UDP_PORT;
-    
-    if (expect_reply) {
-        /* Don't use zero. */
-        data[ID] = ++packet_id;
-        /* Don't need deep_copy() as we are changing the mapping size. */
-        pending_data[mudname + ":" + packet_id] =
-#ifdef INETD_DIAGNOSTICS
-        data + ([ NAME: host_data[HOST_NAME], RESPONSE_TIME: time() ]);
-#else
-        data + ([ NAME: host_data[HOST_NAME] ]);
-#endif
-    }
-    if (!(packet = encode_packet(data))) {
-        if (expect_reply)
-            pending_data = m_copy_delete(pending_data, mudname + ":" + packet_id);
-        log_file(INETD_LOG_FILE, DATE + ": Illegal packet sent by " +
-        object_name(previous_object()) + "\n\n");
-        return "inetd: Illegal packet.\n";
-    }
-    if (expect_reply)
-        call_out("reply_time_out", REPLY_TIME_OUT, mudname + ":" + packet_id);
-
-    if (sizeof(packet) <= MAX_PACKET_LEN)
-        packet_arr = ({ packet });
-    else {
-        string header;
-        int max;
-
-        /* Be careful with the ID.  data[ID] could have been set up by RETRY */
-        header =
-            PACKET + ":" + lower_case(LOCAL_NAME) + ":" +
-            ((expect_reply || data[REQUEST] != REPLY)&& data[ID] ?
-            data[ID] : ++packet_id) + ":";
-        
-        /* Allow 8 extra chars: 3 digits + "/" + 3 digits + DELIMITER */
-        packet_arr = explode_packet(packet,
-            MAX_PACKET_LEN - (sizeof(header) + 8));
-
-        for(i = max = sizeof(packet_arr); i--; )
-            packet_arr[i] =
-            header + (i+1) + "/" + max + DELIMITER + packet_arr[i];
-    }
-    
-    for(i = sizeof(packet_arr); i--; )
-    {
-      ZDEBUG(sprintf("%O <- %.500O\n",host_data[HOST_IP], packet_arr[i]));
-      if (!send_udp(
-        host_data[HOST_IP], host_data[HOST_UDP_PORT], packet_arr[i]))
-            return "inetd: Error in sending packet.\n";
-    }
-    return 0;
-}
-
-void reply_time_out(string id) {
-    mapping data;
-
-    if (data = pending_data[id]) {
-        object ob;
-
-#ifdef INETD_DIAGNOSTICS
-        data[PACKET_LOSS]++;
-#endif
-        if (data[RETRY] < RETRIES) {
-            mapping send;
-
-            data[RETRY]++;
-            /* We must use a copy so the NAME field in pending_data[id]
-             * isn't corrupted by _send_udp(). */
-            send = deep_copy(data);
-            send = m_copy_delete(send, RETRY);
-#ifdef INETD_DIAGNOSTICS
-            send = m_copy_delete(send, PACKET_LOSS);
-            send = m_copy_delete(send, RESPONSE_TIME);
-#endif
-            call_out("reply_time_out", REPLY_TIME_OUT, id);
-            _send_udp(data[NAME], send);
-            return;
-        }
-        data = m_copy_delete(data, RETRY);
-#ifdef INETD_DIAGNOSTICS
-        data = m_copy_delete(data, RESPONSE_TIME);
-#endif
-        catch(call_other(UDP_CMD_DIR + REPLY, "udp_" + REPLY,
-        add_system_field(data, TIME_OUT));publish);
-        /* It's just possible this was removed from the host list. */
-        if (hosts[lower_case(data[NAME])])
-            hosts[lower_case(data[NAME])][HOST_STATUS] = DOWN;
-        remove_incoming(lower_case(data[NAME]) + ":" + id);
-    }
-    pending_data = m_copy_delete(pending_data, id);
-}
-
-void remove_received_id(string id) {
-    received_ids -= ({ id });
-}
-
-varargs mixed query(string what, mixed extra1, mixed extra2) {
-    mixed data;
-
-    switch(what) {
-        case "commands":
-            return COMMANDS;
-        case "hosts":
-            return deep_copy(hosts);
-        case "pending":
-            return deep_copy(pending_data);
-        case "incoming":
-            return deep_copy(incoming_packets);
-        case "received":
-            return ({ }) + received_ids;
-        /* args: "valid_request", request, mudname */
-        case "valid_request":
-            if (data = hosts[extra2])
-                return member(data[HOST_COMMANDS], "*") != -1 ||
-                        member(data[HOST_COMMANDS], extra1) != -1;
-            return 0;
-    }
-    return(0);
+protected void create()
+{
+  configure_host((<host_s> name: "MG-Test-"+__HOST_NAME__,
+                  ip: "127.0.0.1",
+                  port: driver_info(DI_UDP_PORT),
+        ));
+  ::create();
 }