Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/std/util/cidr.c b/std/util/cidr.c
new file mode 100644
index 0000000..85a00e5
--- /dev/null
+++ b/std/util/cidr.c
@@ -0,0 +1,26 @@
+// MorgenGrauen MUDlib
+/** \file /std/util/cidr.c
+* Funktionen zur Interpretation und Umrechnung von IP-Adressen in CIDR-Notation.
+* \author Zesstra
+* \date 05.02.2010
+* \version $Id$
+*/
+/* Changelog:
+*/
+#pragma strong_types
+#pragma save_types
+#pragma no_clone
+#pragma no_shadow
+#pragma pedantic
+#pragma range_check
+
+// Never do this at home. ;-)
+// Der Hintergrund ist, dass der Master moeglichst wenig Code von ausserhalb
+// /secure/ erben/inkludieren sollte, ich aber nur an einer Stelle Aenderungen
+// vornehmen moechte...
+#define private public
+#include "/secure/master/cidr.c"
+#undef private
+
+//string IPv4_test(string addr) {return (IPv4_int2addr(IPv4_addr2int(addr)));}
+
diff --git a/std/util/ex.c b/std/util/ex.c
new file mode 100644
index 0000000..eae9e27
--- /dev/null
+++ b/std/util/ex.c
@@ -0,0 +1,293 @@
+// MorgenGrauen MUDlib
+//
+// util/ex.c -- ex compatible editor
+//
+// $Id: ex.c 9142 2015-02-04 22:17:29Z Zesstra $
+
+#pragma strong_types
+#pragma save_types
+#pragma pedantic
+#pragma range_check
+#pragma no_clone
+
+inherit "/std/util/input";
+
+private nosave mapping ctrl = ([]);
+private nosave mixed buf;
+
+#include <sys_debug.h>
+#undef ARGS
+#include <wizlevels.h>
+#include <player.h>
+
+#define MODE	0
+#  define CMD		0
+#  define INP		1
+#define TEXT	1
+#define LINE	2
+#define FUNC	3
+#define ARGS	4
+#define FLAG	5
+#  define NUM		1
+#define CHG	6
+
+#define YANK	"@YANK"
+
+int evaluate(string in);
+
+varargs int error(string msg, string arg)
+{
+  if(stringp(arg)) write(arg+": "+msg+"\n");
+  else write(msg+"\n");
+}
+
+string substitute(string s, string regex, string n, string extra)
+{
+  mixed del; int i;
+  if((i = sizeof(del = regexplode(s, regex))) < 2) return s;
+  if(member(extra, 'g') == -1) i = 1;
+  else i -= 2;
+  while(i>0) {
+    del[i] = n;
+    i -= 2;
+  }
+  return implode(del, "");
+}
+
+// saveText() -- save edited text
+//
+int saveText()
+{
+  string text;
+  text = implode(ctrl[buf][TEXT][1..], "\n")+"\n";
+  error(sprintf("%O, %d Zeilen, %d Zeichen", 
+	       buf ? buf : "", sizeof(ctrl[buf][TEXT])-1,
+	       sizeof(text)));
+  if(ctrl[buf][FUNC]) apply(ctrl[buf][FUNC], ctrl[buf][ARGS], text);
+  ctrl = m_copy_delete(ctrl, buf);
+  ctrl = m_copy_delete(ctrl, buf+"!");
+  buf = 0;
+  return 1;
+}
+
+// cmdPrompt() -- create command prompt
+//
+string cmdPrompt(int mode, mixed text, int line, int maxl)
+{
+  return ":";
+}
+
+// inputPrompt() -- create input prompt
+//
+string inputPrompt()
+{
+  if(ctrl[buf][FLAG] & NUM) return sprintf("[%02d] ", ctrl[buf][LINE]);
+  return "";
+}
+
+string AddNum(string s)
+{
+  string r;
+  r = inputPrompt()+s;
+  ctrl[buf][LINE]++;
+  return r;
+}
+
+void showLines(int from, int to)
+{
+  write(implode(map(ctrl[buf][TEXT][from..to], #'AddNum), "\n")+"\n");
+  ctrl[buf][LINE] = from;
+}
+
+// commandMode() -- handle commands
+//
+int commandMode(string in)
+{
+  int from, to, swap;
+  string cmd;
+
+  if(!in) return 0;
+  if(in[0..1] == "se") {
+    ctrl[buf][FLAG] ^= NUM;
+    return 0;
+  }
+    
+  if(sscanf(in, "%d,%d%s", from, to, cmd) != 3)
+    if(sscanf(in, "%d%s", from, cmd) != 2)
+      if(!stringp(in)) return error("Kein Editorkommando", in);
+      else { cmd = in; from = to = ctrl[buf][LINE]; }
+    else to = from;
+
+  if(from < 0) from = sizeof(ctrl[buf][TEXT])-1+from;
+  if(to < 1) to = sizeof(ctrl[buf][TEXT])-1+to;
+  if(to && to < from) return error("Erste Adresse groesser als die Zweite");
+  if(from) ctrl[buf][LINE] = from;
+  if(from > sizeof(ctrl[buf][TEXT])-1 ||
+     to > sizeof(ctrl[buf][TEXT])-1) 
+    return error("Nicht so viele Zeilen im Speicher");
+  if(!to) to = from;
+  switch(cmd[0])
+  {
+  case 'h':
+    write("ex: Kommandohilfe\n\n"
+	 "Alle Kommandos funktionieren nach folgendem Prinzip:\n"
+	 "Adresse Kommando Argumente\n"
+	 "Adressen werden gebildet durch: ZeileVon,ZeileBis\n"
+	 "(ZeileBis kann weggelassen werden, samt Komma)\n"
+	 "Kommandos:\n"
+	 "  q,x -- Editor verlassen\n"
+	 "  r   -- Datei einfuegen\n"
+	 "         r<datei>\n"
+	 "  a   -- Text hinter der aktuellen Zeile einfuegen\n"
+	 "  i   -- Text vor der aktuellen Zeile einfuegen\n"
+	 "  d   -- Zeilen loeschen\n"
+	 "  y   -- Zeilen zwischenspeichern\n"
+	 "  pu  -- Zwischengespeicherte Zeilen einfuegen\n"
+	 "  s   -- Substitution von Text in Zeilen\n"
+	 "         s/AlterText/NeuerText/\n"
+          "  p,l -- Zeilen anzeigen\n"
+	 "  z   -- Eine Seite anzeigen\n");
+    break;
+  case 'q':
+    if(ctrl[buf][CHG])
+      if(!(sizeof(cmd) > 1 && cmd[1]=='!'))
+        return error("Datei wurde geaendert! Abbrechen mit q!");
+      else ctrl[buf] = ctrl[buf+"!"];
+  case 'x':
+    if(saveText()) return 1;
+  case 'r':
+    if(!IS_WIZARD(this_player()))
+      return error("Kommando gesperrt", cmd[0..0]);
+    if(file_size(cmd[1..]) < 0) 
+      return error("Datei nicht gefunden", "\""+cmd[1..]+"\"");
+    ctrl[buf][TEXT] = ctrl[buf][TEXT][0..from] 
+		  + explode(read_file(cmd[1..]), "\n")
+	           + ctrl[buf][TEXT][(from == to ? to+1 : to)..];
+    ctrl[buf][CHG] = 1;
+    break;
+  case 'a':
+    ctrl[buf][MODE] = INP;
+    write("Texteingabe: (. beendet zum Kommandomodus, ** beendet ganz)\n");
+    input(#'inputPrompt, 0, #'evaluate); 
+    ctrl[buf][CHG] = 1;
+    return 1;
+  case 'i':
+    ctrl[buf][MODE] = INP;
+    ctrl[buf][LINE]--;
+    write("Texteingabe: (. beendet zum Kommandomodus, ** beendet ganz)\n");
+    input(#'inputPrompt, 0, #'evaluate);
+    ctrl[buf][CHG] = 1;
+    return 1;
+  case 'd':
+    ctrl[buf][TEXT][from..to] = ({});
+    ctrl[buf][CHG] = 1;
+    break;
+  case 'y':
+    ctrl[YANK] = ctrl[buf][TEXT][from..to];
+    if(to - from) error(to-from+1+" Zeilen gespeichert");
+    break;
+  case 's':
+  {
+    mixed reg, new, extra, scmd;
+    if(sizeof(scmd = old_explode(cmd[1..], cmd[1..1])) < 2)
+      return error("Substitution fehlgeschlagen");
+    reg = scmd[0]; new = scmd[1];
+    if(sizeof(scmd) > 2) extra = scmd[2];
+    else extra = "";
+    ctrl[buf][TEXT][from..to] = map(ctrl[buf][TEXT][from..to], 
+				      #'substitute, 
+                                          reg, new, extra);
+    showLines(from, to);
+    ctrl[buf][CHG] = 1;
+    break;
+  }
+  case 'z':
+    showLines(ctrl[buf][LINE], 
+	     ctrl[buf][LINE]+this_player()->QueryProp(P_SCREENSIZE));
+    ctrl[buf][LINE] += this_player()->QueryProp(P_SCREENSIZE);
+    break;
+  case 'p':
+    if(sizeof(cmd) > 1 && cmd[1] == 'u')
+    {
+      if(!pointerp(ctrl[YANK])) return error("Keine Zeilen im Speicher");
+      if(from >= ctrl[buf][LINE]) ctrl[buf][TEXT] += ctrl[YANK];
+      else
+        ctrl[buf][TEXT][0..from] + ctrl[YANK] + ctrl[buf][TEXT][from+1..];
+      ctrl[buf][LINE] += sizeof(ctrl[YANK]);
+      ctrl[YANK] = 0;
+      showLines(ctrl[buf][LINE], ctrl[buf][LINE]);
+      break;
+    }
+  case 'l':
+  default:
+    if(!from) 
+    {
+      error("Kein Editorkommando", sprintf("%c", cmd[0]));
+      return 0;
+    }
+    showLines(from, to);
+  }
+  input(#'cmdPrompt, 0, #'evaluate);
+  return 1;
+}
+
+// inputMode() -- handle input mode commands
+//
+int inputMode(string in)
+{
+  switch(in)
+  {
+  case ".": 
+    ctrl[buf][MODE] = CMD;
+    ctrl[buf][LINE]--;
+    input(#'cmdPrompt, 0, #'evaluate);
+    break;
+  case "**":
+    return saveText();
+  default:
+    if(!in) /* do nothing now */;
+    if(ctrl[buf][LINE] < sizeof(ctrl[buf][TEXT])-1)
+      ctrl[buf][TEXT] = ctrl[buf][TEXT][0..ctrl[buf][LINE]-1] + ({ in }) 
+	        + ctrl[buf][TEXT][ctrl[buf][LINE]..];
+    else ctrl[buf][TEXT] += ({ in });
+    ctrl[buf][LINE]++;
+    input(#'inputPrompt, 0, #'evaluate);
+    break;
+  }
+  return 1;
+}
+
+// evaluate() -- evaluate input (in) in context (ctrl[buf])
+//
+int evaluate(string in)
+{
+  switch(ctrl[buf][MODE])
+  {
+    case INP: return inputMode(in);
+    case CMD: return commandMode(in);
+    default : return 0;
+  }
+}
+
+void StartEX(string in, mixed c)
+{
+  if(!in || in == "j" || in == "J") ctrl[buf] = c;
+  else if(in && (in != "n"  || in != "N"))
+    return 0;
+  ctrl[buf+"!"] = ctrl[buf];
+  input(#'cmdPrompt, 0, #'evaluate);
+}
+
+varargs int ex(mixed text, closure func, mixed fargs, string buffer)
+{
+  int c, l;
+  mixed ct;
+  if(!text) text = "";
+  c = sizeof(text);
+  l = sizeof(text = explode(text, "\n")) - 1;
+  ct = ({ CMD, text, 0, func, fargs, 0, 0});
+  if(!ctrl[buffer]) StartEX(0, ct);
+  else input(sprintf("Es existiert bereits Text! Verwerfen? [j]"),
+	    0, #'StartEX, ct);
+  return 1;
+}
diff --git a/std/util/executer.c b/std/util/executer.c
new file mode 100644
index 0000000..4e0f707
--- /dev/null
+++ b/std/util/executer.c
@@ -0,0 +1,39 @@
+// MorgenGrauen MUDlib
+//
+// utils/executer.c - Helfer zum Ausfuehren vom Kram
+//
+// $Id: skills.c 6673 2008-01-05 20:57:43Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+protected mixed execute_anything(mixed fun, varargs mixed args)
+{
+  if ( closurep(fun) && objectp(query_closure_object(fun)) )
+    return apply(fun, args);
+
+  if (stringp(fun))
+    return call_other(this_object(), fun, args...);
+
+  if ( pointerp(fun) && sizeof(fun)==2 )
+  {
+    object ob;
+    if (sizeof(fun)>2)
+      raise_error(sprintf("execute_anything(): first argument may only "
+                         "have 2 elements if array.\n"));
+
+    if ( stringp(fun[0]) )
+      ob=find_object(fun[0]);
+    else
+      ob=fun[0];
+
+    if ( !objectp(ob) || !stringp(fun[1]) )
+      return 0;
+
+    return call_other(ob, fun[1], args...);
+  }
+  return 0;
+}
+
diff --git a/std/util/input.c b/std/util/input.c
new file mode 100644
index 0000000..e65bc84
--- /dev/null
+++ b/std/util/input.c
@@ -0,0 +1,31 @@
+// MorgenGrauen MUDlib
+//
+// util/input.c -- generic input handling
+//
+// $Id: input.c 8349 2013-02-04 21:15:28Z Zesstra $
+
+#include <input_to.h>
+
+#pragma strong_types
+#pragma save_types
+#pragma pedantic
+#pragma range_check
+#pragma no_clone
+
+varargs void input(mixed prompt, mixed pargs, mixed ctrl, mixed ctrlargs)
+{
+  mixed prompttext;
+  if(closurep(prompt))
+    prompttext = apply(prompt, pointerp(pargs) ? pargs : ({}));
+  else prompttext = prompt;
+  if (!stringp(prompttext)) prompttext="";
+  input_to("done", INPUT_PROMPT, prompttext, prompt, pargs, ctrl, ctrlargs);
+}
+
+void done(string in, mixed prompt, mixed pargs, mixed ctrl, mixed ctrlargs)
+{
+  if(closurep(ctrl) &&
+     apply(ctrl, ({ in }) + (pointerp(ctrlargs) ? ctrlargs : ({})))) 
+    return;
+  input(prompt, pargs, ctrl, ctrlargs);
+}
diff --git a/std/util/pager.c b/std/util/pager.c
new file mode 100644
index 0000000..9d71b85
--- /dev/null
+++ b/std/util/pager.c
@@ -0,0 +1,142 @@
+// MorgenGrauen MUDlib
+//
+// util/pager.c -- generic pager
+//
+// $Id: pager.c 8755 2014-04-26 13:13:40Z Zesstra $
+
+#pragma strong_types
+#pragma save_types
+#pragma pedantic
+#pragma range_check
+#pragma no_clone
+
+inherit "/std/util/input";
+
+#include <pager.h>
+#include <sys_debug.h>
+#include <wizlevels.h>
+
+string prompt(mixed pinfo, string add)
+{
+  return sprintf(MSG_PROMPT+"%s", stringp(add)?add:"");
+}
+
+string fread(mixed pinfo, int begin, int c)
+{
+  if(begin > pinfo[MAXL] || begin < 1) return 0;
+  if(pinfo[FILE]) return read_file(pinfo[TEXT], begin, c);
+  else
+  {
+    int start, end, l, x;
+
+    if(member(pinfo[JUNK], begin)) 
+    {
+      start = pinfo[JUNK][begin];
+      if(!(end = pinfo[JUNK][begin+c]))
+        end = sizeof(pinfo[TEXT]);
+      else end--;
+      return pinfo[TEXT][start..end];
+    }
+    return 0;
+  }
+}
+
+mixed call(closure ctrl, mixed ctrlargs)
+{
+  if (!ctrl||!closurep(ctrl)) return 0;
+  if(!pointerp(ctrlargs)) return funcall(ctrl);
+  return apply(ctrl, ctrlargs);
+}
+
+ 
+varargs int eval_command(mixed in, mixed pinfo)
+{
+  string cprompt, tmp;
+  cprompt = "";
+  if(in == "q" || in == "x")
+  {
+    if(closurep(pinfo[CTRL])) apply(pinfo[CTRL], pinfo[CARG]);
+    return 1;
+  }
+  else
+    if(!in || (stringp(in) && !sizeof(in))) pinfo[CURL] += pinfo[PAGE];
+    else if(in != -1) return 0;
+
+  if(pinfo[CURL] >= pinfo[MAXL]) 
+    return (call(pinfo[CTRL], pinfo[CARG]), 1); 
+  if(pinfo[CURL] <= 0) pinfo[CURL] = 1;
+  if(pinfo[CURL] == 1) cprompt = MSG_TOP;
+  if(pinfo[CURL] + pinfo[PAGE] >= pinfo[MAXL]) cprompt = MSG_BOTTOM;
+  if(!tmp = fread(pinfo, pinfo[CURL], pinfo[PAGE]))
+    return 0; /* (write(MSG_OOPS+"\n"), 0); */
+  if (query_once_interactive(this_object()))
+     tell_object(this_object(), tmp);
+  else write(tmp);
+  if(!(pinfo[FLAG] & E_PROMPT) &&
+     (pinfo[CURL] + pinfo[PAGE] >= pinfo[MAXL] || !pinfo[PAGE]))
+    return (call(pinfo[CTRL], pinfo[CARG]), 1);
+  if(!(pinfo[FLAG] & E_CAT) &&
+     (pinfo[MAXL] > pinfo[PAGE] || (pinfo[FLAG] & E_PROMPT)))
+    input(#'prompt, ({ pinfo, cprompt }), #'eval_command, ({ pinfo }));
+  return 1;
+}
+
+varargs public void More(string txt, int file,
+			 mixed ctrl, mixed ctrlargs,
+			 int flags)
+{
+  int j;
+  mixed tmp, pinfo;
+  if(!txt) return call(ctrl, ctrlargs);
+  //         TEXT, FILE, CURL, MAXL, REGX, PAGE, CTRL, CARG
+  pinfo = ({ txt, file, 1, 1, 20, 0, ctrl, ctrlargs, flags });
+
+  if (pinfo[FILE])
+  { 
+     if (file_size(pinfo[TEXT])<50000)
+     {
+       pinfo[TEXT]=read_file(pinfo[TEXT]);
+       if (!pinfo[TEXT])
+       { 
+         call(ctrl, ctrlargs);
+         return;
+       }  
+       pinfo[FILE]=0;
+     }
+     else if (file_size(pinfo[TEXT])>1048576)
+     {
+	tell_object(this_player()||this_object(),break_string(sprintf(
+               "Die Datei '%s' kann nicht angezeigt werden, da " 
+               "sie groesser als 1 MB ist. %s",pinfo[TEXT],
+               IS_LEARNER(this_player()||this_object())?"":"Bitte verstaendige "
+               "diesbezueglich umgehend einen Magier."),78));
+	call(ctrl,ctrlargs);
+        return;
+     }
+  }
+
+  if(!pinfo[FILE] && pinfo[TEXT][<1..<1] != "\n") pinfo[TEXT] += "\n";
+  pinfo += ({ ([1:0]) });
+  if(!pinfo[FILE]) 
+    while((j = strstr(pinfo[TEXT], "\n", j+1)) != -1)
+  	pinfo[JUNK][++pinfo[MAXL]] = j+1;
+  else
+    while(tmp = read_file(pinfo[TEXT], pinfo[MAXL], MAX_LINE_READ))
+      pinfo[MAXL] += sizeof(explode(tmp, "\n"))+1;
+  pinfo[PAGE] = PAGELENGTH;
+  if(!pinfo[PAGE]) pinfo[FLAG] |= E_CAT;
+  if ((this_interactive() && (j=(int)this_interactive()->QueryProp(P_MORE_FLAGS))) ||
+      (this_player() && interactive(this_player()) &&
+       (j=(int)this_player()->QueryProp(P_MORE_FLAGS))))
+    pinfo[FLAG] |= j;
+  
+  pinfo[CURL] = 1;
+  eval_command(-1, pinfo);
+  return;
+}
+
+
+
+
+
+
diff --git a/std/util/pl_iterator.c b/std/util/pl_iterator.c
new file mode 100644
index 0000000..555a75e
--- /dev/null
+++ b/std/util/pl_iterator.c
@@ -0,0 +1,53 @@
+// MorgenGrauen MUDlib
+/** \file /file.c
+* Kurzbeschreibung.
+* Langbeschreibung...
+* \author <Autor>
+* \date <date>
+* \version $Id$
+*/
+/* Changelog:
+*/
+#pragma strong_types, save_types, rtt_checks
+#pragma no_clone, no_shadow
+#pragma pedantic, range_check
+#pragma warn_deprecated
+
+private void check_all_player(mapping allplayer, closure check_cl,
+                             closure finish_cl, int res,
+                             varargs mixed extra)
+{
+  // offenbar fertig mit allen Spielern, Aufrufer informieren.
+  if (!sizeof(allplayer))
+  {
+    funcall(finish_cl, extra...);
+    return;
+  }
+
+  string dir=m_indices(allplayer)[0];
+  string *pls=allplayer[dir];
+  foreach(string pl: &pls)
+  {
+    if (get_eval_cost() < res)
+      break; // spaeter weitermachen
+    catch(funcall(check_cl, pl, extra...) ; publish);
+    pl = 0;
+  }
+  pls-=({0});
+  allplayer[dir] = pls;
+
+  if (!sizeof(allplayer[dir]))
+    m_delete(allplayer,dir);
+
+  call_out(#'check_all_player,2, allplayer, check_cl, finish_cl, res, extra...);
+}
+
+protected int start_player_check(closure check_cl, closure finish_cl, int res,
+                             varargs mixed extra)
+{
+  res ||= 1250000;
+  mapping allplayer=(mapping)master()->get_all_players();
+  call_out(#'check_all_player,2, allplayer, check_cl, finish_cl, res, extra...);
+  return 1;
+}
+
diff --git a/std/util/rand-glfsr.c b/std/util/rand-glfsr.c
new file mode 100644
index 0000000..8bd624c
--- /dev/null
+++ b/std/util/rand-glfsr.c
@@ -0,0 +1,155 @@
+/* Dieses File implementiert einen Pseudo-Zufallszahlengenerator mit einem
+ * Linear Feedback Shift Register in der Galois-Variante.
+ * Dieses PRNG ist schlechter und viel ineffizienter als der im Driver
+ * eingebaute.
+ * Die einzige sinnvolle Anwendung ist, wenn man aus irgendeinem Grund das
+ * seed selber waehlen muss, damit man die Sequenz von Pseudozufall immer
+ * wieder reproduzieren kann.
+ *
+ * Das Seed von der Blueprint wird vermutlich staendig veraendert (d.h.
+ * verlasst euch nicht drauf, dass es konstant bleibt), wollt ihr eine
+ * 'private' Instanz mit eurem Seed, clont das Objekt (aber verliert den Clone
+ * nicht).
+ *
+ * Es wird standardmaessig ein Polynom fuer eine Periodenlaenge von 2^32 - 1
+ * verwendet.
+ * 
+ * Im Netz finden sich Infos ueber LFSRs und Tabellen fuer maximum-length
+ * feedback polynomials (M-Sequence Feedback Taps), falls jemand braucht.
+ *
+*/
+#pragma strong_types,rtt_checks,pedantic
+
+#include <tls.h>
+
+// Default-Polynom ist das:
+// x^32 + x^31 + x^28 + x^27 + x^24 + x^23 + x^20 + x^19 + x^16 + x^15 + x^12
+//      + x^11 + x^8 + x^7 + x^5 + x^3 + 1
+// Taps: 32, 31, 28, 27, 24, 23, 20, 19, 16, 15, 12, 11, 8, 7, 5, 3
+// Binary: 110011001100110011001100110101000
+#define DEFAULTP 0x1999999a8
+// Andere gebraeuchliche:
+// x^32 + x^30 + x^26 + x^25 + 1,
+// Taps 32, 30, 26, 25
+// Binary: 101000110000000000000000000000000
+//#define DEFAULTP 0x146000000
+// x^16 + x^14 + x^13 + x^11 + 1
+// Taps 16, 14, 13, 11
+// Binary: 1011010000000000
+//#define DEFAULTP 0xB400
+
+private int polynom = DEFAULTP;
+private int state = 2553647223;
+//private int period;
+
+public varargs void init(int seed, int newp)
+{
+  if (!seed)
+    raise_error("Illegal seed 0\n");
+  // Es darf nur ein 32 bit breiter Seed verwendet werden. Die oberen 32 bit
+  // werden mit den unteren 32 bit XOR-rt (also, einmal die oberen 32 shiften
+  // und einmal die oberen 32 wegmaskieren.
+  seed = ((seed>>32) & 0xffffffff) ^ (seed & 0xffffffff);
+  //printf("Seed: %064b - 0x%x\n",seed,seed);
+  
+  if (!seed)
+    raise_error("Illegal reduced seed: 0\n");
+
+  state = seed;
+  polynom = newp || DEFAULTP;
+}
+
+public void InitWithUUID(string uuid)
+{
+  string md5hash = hash(TLS_HASH_MD5, uuid);
+  int seed;
+  // 8 Bytes aus dem Hash ermitteln
+  foreach(int b: 16)
+  {
+    // Jeweils zwei Zeichen herausschneiden und als Hexadezimalzahl
+    // interpretieren, was jeweils ein byte (8 bit) gibt. 
+    int tmp = to_int("0x"+md5hash[b*2..b*2+1]);
+    // diese werden dann in eine 64 bit breite Zahl zusammengefasst. Das
+    // gerade ermittelte Byte wird nach links geshiftet und mit dem, was da
+    // ggf. schon steht, XORred. Ist der int voll, faengt man wegen Modulo 64
+    // wieder rechts an.
+    //printf("S: %064b - %08b\n",seed,tmp);
+    seed = seed ^ (tmp << ((b*8)%64));
+    //printf("S: %064b - 0x%x\n",seed, seed);
+  }
+  //printf("Seed: 0x%x - %b\n",seed,seed);
+  init(seed);
+}
+
+public int nextbit()
+{
+  // Get LSB (i.e., the output bit).
+  int lsb = state & 1;
+  // Shift register by one bit
+  state >>= 1;
+  // Apply a toggle mask, which flips all the tap bits, _if_ the output bit is
+  // 1. The mask has 1 at bits corresponding to taps, 0 elsewhere. In other
+  // words, the polynom from above.
+  if (lsb)
+      state ^= polynom;
+  // debug check ;-)
+  if (!state)
+    raise_error("State must not be zero, but it is.\n");
+  //++period; 
+  //printf("State: %032b (Period: %d)\n",state,period);
+  return lsb;
+}
+
+public int nextbits(int count)
+{
+  int result;
+  if (count>64)
+    raise_error(sprintf("Count is %d, but must be <= 64.\n",count));
+  foreach(int i: count)
+    result = (result << 1) | nextbit();
+  return result;
+}
+
+public int nextbyte()
+{
+  return nextbits(8);
+}
+
+public int random(int n)
+{
+  int rnd = nextbits(32);
+  //generates a random number on [0,1)-real-interval 
+  float tmp = rnd * (1.0/4294967296.0);
+  // Skalieren auf [0,n)
+  return to_int(tmp * n);
+}
+
+// Just skip some bits and discard them.
+public void skipbits(int count)
+{
+  foreach(int i: count)
+    nextbit();
+}
+
+
+public void dumpstream(string file, int bytes)
+{
+  int *stream = allocate(bytes);
+  foreach(int i: bytes)
+  {
+    stream[i] = nextbits(8);
+  }
+  write_file(file, sprintf("%@c",stream));
+}
+
+public int Configure(int data)
+{
+  if (!data)
+    return state;
+  
+  if (!intp(data))
+    return 0;
+  state = data;
+  return 1;
+}
+
diff --git a/std/util/ringbuffer.c b/std/util/ringbuffer.c
new file mode 100644
index 0000000..19338e1
--- /dev/null
+++ b/std/util/ringbuffer.c
@@ -0,0 +1,210 @@
+// MorgenGrauen MUDlib
+/** \file /std/util/ringbuffer.c
+* Implmentiert einen Ringbuffer in LPC.
+* Ab und an hat man den Fall, dass man Ereignisse/Meldungen o.ae. hat, von
+* denen man immer genau die letzten x gespeichert und abrufbar vorhalten
+* moechte. Dieses File stellt eine Datenstruktur und dazugehoerige
+* Verwaltungsfunktionen zu Verfuegung, mit denen dies effizient moeglich ist.
+* Insbesondere umgehen diese das staendige Slicing von Arrays, mit denen
+* haeufig Ringpuffer gebaut werden. Hierbei wird das Schreiben in den Puffer
+* billiger, das Abrufen der Daten allerdings teurer. Wird der Puffer haeufiger
+* abgefragt als beschrieben, ist dies keine effiziente Loesung.
+* 
+* \author Zesstra
+* \date 22.05.2008
+* \version $Id$
+*/
+/* Changelog:
+*/
+#pragma strong_types
+#pragma save_types
+#pragma no_clone
+#pragma no_inherit
+#pragma no_shadow
+#pragma pedantic
+#pragma range_check
+
+#include <util/ringbuffer.h>
+
+/** Standardgroesse fuer Ringbuffer.
+  */
+#define MAXCOUNT 30
+
+
+/** Struktur, die einen Ringpuffer speichert.
+  Der Puffer selber ist im wesentlichen ein Array. Hinzu kommt noch ein
+  Zaehler, der den naechsten zu ueberschreibenden Wert indiziert sowie einen
+  Modus, der die Reihenfolge beim Abrufen beshreibt:
+  MODE_FIFO: First-in-First-out (default)
+  MODE_LIFO: Last-in-First-out
+  */
+struct std_ringbuffer {
+    mixed rbuffer;
+    int mode;
+    int next;
+};
+
+/** Erzeugt einen neuen Ringbuffer und liefert ihn zurueck.
+  Die Funktion erzeugt einen neuen, leeren Ringbuffer der Groesse \a size
+  und mit Ausgabemodus \a newmode und liefert die entsprechende
+  Ringbuffer-Struktur zurueck.
+  \attention Die zurueckgelieferte Datenstruktur bitte nicht per Hand
+  manipulieren.
+  \param[in] size Groesse des zu erzeugenden Ringbuffers. Default: 30
+  \param[in] newmode Ausgabemodus des Ringbuffers: \a MODE_FIFO oder
+  \a MODE_LIFO. Default: MODE_FIFO
+  \return Der erzeugte Ringbuffer (struct vom Typ std_ringbuffer).
+  \sa ResizeRingBuffer, RingBufferPut, RingBufferGet
+  */
+protected struct std_ringbuffer CreateRingBuffer(int size, int newmode) {
+  
+  struct std_ringbuffer buffer = (<std_ringbuffer>
+       rbuffer: allocate(size||MAXCOUNT, 0), 
+       mode: newmode || MODE_FIFO, 
+       next: 0 );
+
+  // Bei LIFO von oben anfangen.
+  if (newmode==MODE_LIFO)
+    buffer->next = sizeof(buffer->rbuffer);
+  
+  return buffer;
+}
+
+/** Schreibt einen neuen Wert in den Ringbuffer.
+  Diese Funktion schreibt einen neuen Wert in den Ringbuffer \a buffer und
+  loescht dabei ggf. den aeltesten Wert im Puffer.
+  \param[in,out] buffer zu aendernder Ringbuffer
+  \param[in] val hinzuzufuegender Wert
+  \sa CreateRingBuffer, ResizeRingBuffer, RingBufferGet
+  */
+protected void RingBufferPut(struct std_ringbuffer buffer, mixed val) {
+  int next = buffer->next;
+  // je nach Ausgabemodus von oben nach unten oder von unten nach oben die
+  // Werte reinschreiben.
+  switch(buffer->mode) {
+    case MODE_LIFO:
+      // next ist hier eigentlich ein 'last'. Dekrementieren und dann zum
+      // Indizieren benutzen.
+      buffer->rbuffer[--next] = val;
+      // wenn man gerade in Element 0 geschrieben hat, ist naechstes Element
+      // sizeof()-1, d.h. sizeof() als next vermerken.
+      next ||= sizeof(buffer->rbuffer);
+      break;
+    default:
+      // Wert schreiben und next inkrementieren.
+      buffer->rbuffer[next++] = val;
+      // wird sizeof() erreicht, ist das naechste Element 0. Etwas schneller
+      // waere ein Modulo mit der Buffergroesse direkt bei der Indizierung
+      // oben, aber dann kann es u.U. durch einen numerischen Overflow buggen.
+      if (next==sizeof(buffer->rbuffer))
+	next = 0;
+  }
+  buffer->next = next;
+}
+
+/** Liefert ein Array mit allen Werten des Ringbuffers \a buffer.
+  Das zurueckgelieferte Array enthaelt alle Daten des Ringbuffers in der
+  beim Erstellen des Puffers gewuenschten Reihenfolge (s. MODE_FIFO,
+  MODE_LIFO).
+  Ist der Puffer noch nicht vollstaendig gefuellt, enthalten die bisher noch
+  nie beschriebenen Elemente 0.
+  \param[in] buffer Ringpuffer, dessen Daten ausgeben werden sollen.
+  \return Array mit Daten des Puffers.
+  \sa CreateRingBuffer, RingBufferPut, ResizeRingBuffer
+  */
+protected mixed RingBufferGet(struct std_ringbuffer buffer) {
+  int size = sizeof(buffer->rbuffer);
+  int next = buffer->next;
+  mixed rbuffer = buffer->rbuffer;
+
+  switch(buffer->mode) {
+    case MODE_LIFO:
+      // der hintere Teil enthaelt die neueren Daten. Die kommen zuerst.
+      // Wenn next == sizeof(), dann kann das interne Array einfach kopiert
+      // werden.
+      if (next == size)
+	return copy(rbuffer);
+      else
+	return rbuffer[next .. size-1] + rbuffer[0 .. next-1];
+    default:
+      // der vordere Teil enthaelt die neueren Daten. Also zuerst den hinteren
+      // ausgeben, dann den vorderen.
+      // Wenn next 0, kann das interne Array einfach kopiert werden. Sonst
+      // muss es zusammengesetzt werden.
+      if (next)
+	return rbuffer[next .. size-1] + rbuffer[0 .. next-1];
+      else
+	return copy(rbuffer);
+  }
+  return 0;
+}
+
+/** Erzeugt einen neuen Ringbuffer der Groesse \a size und dem gleichen Modus
+ * wie \a buf, der dieselben Daten enthaelt wie \a buf.
+ * Diese Funktion erzeugt einen neuen Ringbuffer und kopiert alle Daten aus
+ * dem alten Puffer in den neuen um.
+ \param[in] buf alter Ringbuffer
+ \param[in] size gewuenschte neue Groesse
+ \return Liefert neuen Ringbuffer mit gewuenschten Groesse.
+ \sa CreateRingBuffer, RingBufferPut, RingBufferGet
+ \attention Wird der Ringbuffer verkleinert, kommt es zum Verlust der
+ aeltesten Daten, die nicht mehr in den neuen hineinpassen.
+ \todo Effizientere Implementation.
+ */
+protected struct std_ringbuffer ResizeRingBuffer(struct std_ringbuffer buf, 
+                                                 int size) {
+  // neuen Ringbuffer anlegen.
+  struct std_ringbuffer nbuf = CreateRingBuffer(size, buf->mode);
+  // und alle daten aus dem alten wieder reinstopfen.
+  // ja, das geht effizienter, hab ich gerade aber keinen Bock drauf. Die
+  // Funktion wird vermutlich eh sehr selten gerufen.
+  foreach(mixed val: RingBufferGet(buf))
+    RingBufferPut(nbuf, val);
+  // neuen Buffer zurueckgeben. Der alte bleibt unveraendert!
+  return nbuf;
+}
+
+/* halbfertige Implementation mit Arrays.
+#define RBUFFER   0
+#define MODE      1
+#define COUNTER   2
+
+protected mixed CreateRingBuffer(int size, int mode) {
+  mixed buffer = ({ allocate(size||MAXCOUNT, 0), 
+                    mode || MODE_FIFO, 
+	            0 });
+  if (mode==MODE_LIFO)
+    buffer[COUNTER] = sizeof(buffer[RBUFFER]);
+  return buffer;
+}
+
+protected void RingBufferPut(mixed buffer, mixed val) {
+  int counter = buffer[COUNTER];
+  switch(mode) {
+    case MODE_LIFO:
+      rbuffer[--counter] = val;
+      counter ||= sizeof(rbuffer);
+      break;
+    default:
+      rbuffer[(counter++)%sizeof(rbuffer)] = val;
+  }
+  buffer[COUNTER]=counter;
+}
+
+protected mixed RingBufferGet(mixed buffer) {
+  int size=sizeof(rbuffer);
+
+  switch(mode) {
+    case MODE_LIFO:
+      return rbuffer[counter..size] + rbuffer[0..counter-1];
+    default:
+      if (counter%size)
+	return rbuffer[(counter%size) .. size-1] 
+	       + rbuffer[0..(counter%size)-1];
+      else
+	return copy(rbuffer);
+  }
+}
+
+protected mixed test() {return rbuffer;}
+*/
diff --git a/std/util/testedit.c b/std/util/testedit.c
new file mode 100644
index 0000000..f31f6ed
--- /dev/null
+++ b/std/util/testedit.c
@@ -0,0 +1,25 @@
+// MorgenGrauen MUDlib
+//
+// util/testedit.c -- Tragbarer Editor
+//
+// $Id: testedit.c 6371 2007-07-17 22:46:50Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma pedantic
+#pragma range_check
+#pragma no_clone
+
+inherit "/std/thing";
+inherit "/std/util/ex";
+
+#include <properties.h>
+
+void create()
+{
+  ::create();
+  AddId("ex");
+  SetProp(P_NAME, "Editor");
+  SetProp(P_SHORT, "Ein Testeditor");
+  SetProp(P_LONG, "Testeditor: Kommando: ex\n");
+  AddCmd("ex", "ex");
+}