Vorbereitungen fuer leight-weight objects

UID-Vergabe durch den Master
Support durch seteuid()
Support in Fehlerbehandlung
Anpassungen simul_efuns

Change-Id: I37b49708440209b3ace693afc4613c1287c41064
diff --git a/secure/errord.c b/secure/errord.c
index 32977b1..457821f 100644
--- a/secure/errord.c
+++ b/secure/errord.c
@@ -434,8 +434,8 @@
 
     struct fullissue_s issue = (<fullissue_s>);
 
-    //UID bestimmen
-    issue->uid=({string})master()->creator_file(curobj);
+    //UID bestimmen, curobj is 0 for lwobjects, then the program is used.
+    issue->uid=({string})master()->creator_file(curobj || prg);
     //DEBUG(sprintf("LogError: UID: %s\n",uid));
 
     //Loadname (besser als BP, falls rename_object() benutzt wurde) bestimmen
@@ -590,8 +590,8 @@
 
     struct fullissue_s issue = (<fullissue_s>);
 
-    //UID bestimmen
-    issue->uid=({string})master()->creator_file(curobj);
+    //UID bestimmen, curobj is 0 for lwobjects, then the program is used.
+    issue->uid=({string})master()->creator_file(curobj || prg);
     //DEBUG(sprintf("LogWarning UID: %s\n",uid));
 
     //Loadname (besser als BP, falls rename_object() benutzt wurde) bestimmen
diff --git a/secure/master.c b/secure/master.c
index 131c951..abba895 100644
--- a/secure/master.c
+++ b/secure/master.c
@@ -114,6 +114,11 @@
   set_driver_hook(H_CREATE_CLONE,       "create");
   set_driver_hook(H_CREATE_OB,          "create");
   set_driver_hook(H_CREATE_SUPER,       "create_super");
+#if MUDHOST != __HOST_NAME__
+  // LWOs sollen vorerst nur in Homemuds getestet werden.
+  set_driver_hook(H_CREATE_LWOBJECT,    "create_lw");
+  set_driver_hook(H_LWOBJECT_UIDS, #'lwo_uid_hook);
+#endif
 
   // Bei Reset reset() im Objekt aufrufen
   set_driver_hook(H_RESET,              "reset");
@@ -426,7 +431,8 @@
 //                         #################
 
 // Magier-ID fuer Datei str (als Objekt oder als String) ermitteln
-string creator_file(mixed str) {
+public string creator_file(mixed str)
+{
   string *strs,tmp;
   int s;
 
@@ -508,12 +514,12 @@
 
 // UID und EUID an Objekt geben (oder eben nicht)
 // Keine GD-Funktion, aber von Hooks aufgerufen
-protected mixed give_uid_to_object(string datei, object po)
+protected mixed give_uid_to_object(string datei, object|lwobject po)
 {
   string creator,pouid;
 
   // Parameter testen
-  if (!stringp(datei)||!objectp(po))  return 1;
+  if (!datei || !po)  return 1;
 
   // Keine Objekte in /log, /open oder /data
   if (strstr(datei, "/"LIBDATADIR"/") == 0
@@ -535,7 +541,7 @@
   // unten generieren.
   // Ausserdem nur UID setzen, keine eUID.
   if (pouid==ROOTID)
-    return ({creator,NOBODY}); // root does not create root objects!
+    return ({creator,NOBODY});
 
   // EUID mitsetzen, wenn PO und creator dieselbe UID sind.
   // Wenn creator die BACKBONEID ist (im allg. liegt das Objekt dann in
@@ -547,6 +553,21 @@
   return ({creator,NOBODY});
 }
 
+// EUID und UID werden von give_uid_to_object() vergeben, diese sind in
+// inaugurate_master() als driver hooks angemeldet.
+
+protected mixed load_uid_hook(string datei) {
+    return(give_uid_to_object(datei, previous_object()));
+}
+
+protected mixed clone_uid_hook(object bluep, string new_name) {
+    return(give_uid_to_object(new_name, previous_object()));
+}
+
+protected mixed lwo_uid_hook(object bluep) {
+    return(give_uid_to_object(object_name(bluep), previous_object()));
+}
+
 // Die System-IDs muessen bekannt sein
 string get_master_uid()          { return ROOTID;}
 string get_bb_uid()              { return BACKBONEID; }
@@ -772,9 +793,9 @@
                         mixed arg3)
 {
 
-  if (objectp(who) && 
+  if (objectp(who) &&
       (who==this_object() || geteuid(who)==ROOTID))
-    return 1; 
+    return 1;
 
   switch(op)
   {
@@ -816,7 +837,6 @@
       if (strstr(load_name(who), "/std/shells/") == 0
           && get_type_info(arg1, 2) == who
           && get_type_info(arg1, 3) == "/std/living/life"
-//          && get_type_info(arg1, 4) == "die"
           && arg2[LIMIT_EVAL] <= 10000000 ) {
           return 1;
       }
@@ -840,6 +860,14 @@
 
     case "sqlite_pragma":
       return 1;
+
+    case "configure_lwobject":
+      // arg1: lwo to be configured, arg2: <what>, arg3: <data>
+      if (arg2 == LC_EUID) {
+        return who == arg1 // only the lwo itself for now (except of ROOT)
+               && getuid(arg1) == arg3; // and only to its own UID
+      }
+      return -1;
     case "attach_erq_demon":
     case "bind_lambda": 
     case "configure_interactive":
@@ -985,7 +1013,7 @@
    Aufsplitten des Handlers und Nutzung von limited() */
 //keine GD-Funktion
 private void handle_runtime_error(string err, string prg, string curobj,
-    int line, mixed culprit, int caught, object po, int issueid)
+    int line, mixed culprit, int caught, object|lwobject po, int issueid)
 {
   string code;
   string debug_txt;
@@ -1037,7 +1065,7 @@
 
 //Keine GD-Funktion, limitiert die Kosten fuer den handler
 private void call_runtime_error(string err, string prg, string curobj,
-    int line, mixed culprit, int caught, object po)
+    int line, mixed culprit, int caught, object|lwobject po)
 {
   if (handling_error == efun::driver_info(DI_EVAL_NUMBER))
   {
@@ -1201,13 +1229,6 @@
     return;
 }
 
-// Keine Prepositionen in parse_command
-//string *parse_command_prepos_list() { return ({}); }
-
-// Wie lautet das Wort fuer 'alle' ?
-//string *parse_command_all_word() { return ({}); }
-
-
 // Keine Besonderen Objektnamen
 string printf_obj_name(object ob) { return 0; }
 
@@ -1230,14 +1251,3 @@
      map(wizlist_info(),#'_save_wiz_file_loop),""));
 }
 
-// EUID und UID werden von give_uid_to_object() vergeben, diese sind in
-// inaugurate_master() als driver hooks angemeldet.
-
-protected mixed load_uid_hook(string datei) {
-    return(give_uid_to_object(datei, previous_object()));
-}
-
-protected mixed clone_uid_hook(object blueprint, string new_name) {
-    return(give_uid_to_object(new_name, previous_object()));
-}
-
diff --git a/secure/master.h b/secure/master.h
index 7c8a137..1f98a2b 100644
--- a/secure/master.h
+++ b/secure/master.h
@@ -66,12 +66,13 @@
 #define WIZ_HELP_MAIL_DIR "/doc/infomails/"
 
 // aus master.c
-string        creator_file(mixed str);
-protected mixed give_uid_to_object(string datei,object po);
-protected void  save_wiz_file();
+public   string creator_file(mixed str);
+protected mixed give_uid_to_object(string datei, object|lwobject po);
 protected mixed load_uid_hook(string datei);
-protected mixed clone_uid_hook(object blueprint,string new_name);
+protected mixed clone_uid_hook(object bluep, string new_name);
+protected mixed lwo_uid_hook(object bluep);
 protected mixed call_sefun(string sefun, varargs mixed args);
+protected void  save_wiz_file();
 
 // aus domains.c
 int            domain_master(string user, string domain);
diff --git a/secure/simul_efun/comm.c b/secure/simul_efun/comm.c
index 4ef060f..28636e6 100644
--- a/secure/simul_efun/comm.c
+++ b/secure/simul_efun/comm.c
@@ -4,12 +4,11 @@
 // ReceiveMsg().
 varargs void send_room(object|string room, string msg, int msg_type,
                        string msg_action, string msg_prefix, object *exclude,
-                       object origin)
+                       object origin=previous_object())
 {
   if (stringp(room))
     room=load_object(room);
 
-  origin ||= previous_object();
   object *dest = exclude ? all_inventory(room) - exclude :
                            all_inventory(room);
 
diff --git a/secure/simul_efun/seteuid.c b/secure/simul_efun/seteuid.c
index 516a759..1318b8d 100644
--- a/secure/simul_efun/seteuid.c
+++ b/secure/simul_efun/seteuid.c
@@ -8,19 +8,38 @@
 
 int seteuid(string str)
 {
-    object ob = efun::previous_object();
-
-    if (!str)
+    object|lwobject ob = efun::previous_object();
+    if(objectp(ob))
     {
-        efun::configure_object(ob, OC_EUID, 0);
+        if (!str)
+        {
+            efun::configure_object(ob, OC_EUID, 0);
+            return 1;
+        }
+
+        if (efun::call_direct(__MASTER_OBJECT__, "valid_seteuid", ob, str) != 1)
+            return 0;
+
+        efun::configure_object(ob, OC_EUID, str);
         return 1;
     }
+    else if (lwobjectp(ob))
+    {
+        if (!str)
+        {
+            efun::configure_lwobject(ob, LC_EUID, 0);
+            return 1;
+        }
 
-    if (efun::call_direct(__MASTER_OBJECT__, "valid_seteuid", ob, str) != 1)
-        return 0;
+        if (efun::call_direct(__MASTER_OBJECT__, "privilege_violation", 
+                "configure_lwobject", ob, ob, LC_EUID, str) != 1)
+            return 0;
 
-    efun::configure_object(ob, OC_EUID, str);
-    return 1;
+        efun::configure_lwobject(ob, LC_EUID, str);
+        return 1;
+
+    }
+    return 0;
 }
 
 #endif
diff --git a/secure/simul_efun/simul_efun.c b/secure/simul_efun/simul_efun.c
index 680f4d5..1b4af5f 100644
--- a/secure/simul_efun/simul_efun.c
+++ b/secure/simul_efun/simul_efun.c
@@ -48,7 +48,7 @@
 nomask varargs int snoop(object snooper, object snoopee);
 varargs string country(mixed ip, string num);
 int query_wiz_grp(object|string wiz);
-public varargs object deep_present(mixed what, object ob);
+public object deep_present(string|object what, object ob=previous_object());
 nomask int secure_level();
 nomask string secure_euid();
 public nomask int process_call();
@@ -726,9 +726,10 @@
   else return(0);
 }
 
-private nomask string _process_string(string str,object po) {
-              set_this_object(po);
-              return(efun::process_string(str));
+private nomask string _process_string(string str, object|lwobject po)
+{
+    set_this_object(po);
+    return(efun::process_string(str));
 }
 
 private nomask int _illegal_ps_call(string s)
@@ -861,7 +862,7 @@
 
 
 // * Properties ggfs. mitspeichern
-mixed save_object(mixed name)
+mixed save_object(string|int name)
 {
   mapping properties;
   mapping save;
@@ -870,13 +871,19 @@
   string oldpath;
 
   // nur Strings und 0 zulassen
-  if ((!stringp(name) || !sizeof(name)) && 
-      (!intp(name) || name!=0)) {
+  if ((!stringp(name) || !sizeof(name)) &&
+      (!intp(name) || name!=0))
+  {
       set_this_object(previous_object());
       raise_error(sprintf(
          "Only non-empty strings and 0 may be used as filename in "
          "sefun::save_object()! Argument was %O\n",name));
   }
+  if(!objectp(previous_object()))
+  {
+    set_this_object(previous_object());
+    raise_error(sprintf("save_object() only calleable by objects!\n"));
+  }
 
   if (stringp(name)) {
     // abs. Pfad erzeugen. *seufz*
@@ -969,6 +976,11 @@
     raise_error("Bad arg 1 to restore_object(): expected non-empty "
                 "'string'.\n");
   }
+  if(!objectp(previous_object()))
+  {
+    set_this_object(previous_object());
+    raise_error(sprintf("restore_object() only calleable by objects!\n"));
+  }
 
   // Wenn name vermutlich ein Pfad (also nicht mit #x:y anfaengt)
   if (name[0] != '#')
@@ -1319,7 +1331,7 @@
 
 mixed call_out_info() {
   
-  object po = previous_object();
+  object|lwobject po = previous_object();
   mixed coi = efun::call_out_info();
 
   // ungefilterten Output nur fuer bestimmte Objekte, Objekte in /std oder
@@ -1348,13 +1360,12 @@
 // * Wir wollen nur EIN Argument ... ausserdem checks fuer den Netztotenraum
 varargs void move_object(mixed what, mixed where)
 {
-  object po,tmp;
-
-  po=previous_object();
+  // Wenn nur ein Argument angegeben wird, ist es das Ziel und wir nehmen
+  // previous_object() als zu bewegendes Objekt.
   if (!where)
   {
     where=what;
-    what=po;
+    what=previous_object();
   }
   if (((stringp(where) && where==NETDEAD_ROOM ) ||
        (objectp(where) && where==find_object(NETDEAD_ROOM))) &&
@@ -1373,7 +1384,7 @@
     }
     set_object_heart_beat(what,0);
   }
-  tmp=what;
+  object tmp=what;
   while (tmp=environment(tmp))
       // Ja. Man ruft die _set_xxx()-Funktionen eigentlich nicht direkt auf.
       // Aber das Lichtsystem ist schon *so* rechenintensiv und gerade der
@@ -1383,7 +1394,7 @@
       //
       // Tiamak
     tmp->_set_last_content_change();
-  funcall(bind_lambda(#'efun::move_object,po),what,where);
+  funcall(bind_lambda(#'efun::move_object,previous_object()),what,where);
   if (tmp=what)
     while (tmp=environment(tmp))
       tmp->_set_last_content_change();
@@ -1461,10 +1472,8 @@
       a[i][WL_ARRAY_TOTAL],a[i][WL_CALL_OUT]));
 }
 
-public varargs object deep_present(mixed what, object ob) {
-
-  if(!objectp(ob))
-    ob=previous_object();
+public object deep_present(string|object what, object ob=previous_object())
+{
   // Wenn ein Objekt gesucht wird: Alle Envs dieses Objekts ermitteln und
   // schauen, ob in diesen ob vorkommt. Dann ist what in ob enthalten.
   if(objectp(what)) {
@@ -1472,7 +1481,7 @@
     // wenn ob kein Environment hat, ist es offensichtlich nicht in what
     // enthalten.
     if (!pointerp(envs)) return 0;
-    if (member(envs, ob) != -1) return what;
+    if (ob in envs) return what;
   }
   // sonst wirds teurer, ueber alle Objekte im (deep) Inv laufen und per id()
   // testen. Dabei muss aber die gewuenschte Nr. ("flasche 3") abgeschnitten
@@ -1514,6 +1523,7 @@
   if(previous_object()==0 || !IS_ARCH(geteuid(previous_object())) 
       || !ARCH_SECURITY)
   {
+    // historical info, but amusing message. ;-)
     write("Call GC now and the mud will crash in 5-6 hours. DONT DO IT!\n");
     return;
   }
@@ -1775,22 +1785,17 @@
     return ret;
 }
 
-nomask varargs int query_next_reset(object ob) {
-
+nomask int query_next_reset(object ob=previous_object())
+{
     // Typpruefung: etwas anderes als Objekte oder 0 sollen Fehler sein.
     if (ob && !objectp(ob))
       raise_error(sprintf("Bad arg 1 to query_next_reset(): got %.20O, "
            "expected object.\n",ob));
 
-    // Defaultobjekt PO, wenn 0 uebergeben.
-    if ( !objectp(ob) )
-      ob = previous_object();
-
     return efun::object_info(ob, OI_NEXT_RESET_TIME);
 }
 
 
-
 // ### Ersatzaufloesung in Strings ###
 varargs string replace_personal(string str, <string|object>* obs, int caps) {
   string* parts = regexplode(str, "@WE[A-SU]*[0-9]");
diff --git a/secure/simul_efun/spare/comm.c b/secure/simul_efun/spare/comm.c
index 4ef060f..28636e6 100644
--- a/secure/simul_efun/spare/comm.c
+++ b/secure/simul_efun/spare/comm.c
@@ -4,12 +4,11 @@
 // ReceiveMsg().
 varargs void send_room(object|string room, string msg, int msg_type,
                        string msg_action, string msg_prefix, object *exclude,
-                       object origin)
+                       object origin=previous_object())
 {
   if (stringp(room))
     room=load_object(room);
 
-  origin ||= previous_object();
   object *dest = exclude ? all_inventory(room) - exclude :
                            all_inventory(room);
 
diff --git a/secure/simul_efun/spare/seteuid.c b/secure/simul_efun/spare/seteuid.c
index 516a759..1318b8d 100644
--- a/secure/simul_efun/spare/seteuid.c
+++ b/secure/simul_efun/spare/seteuid.c
@@ -8,19 +8,38 @@
 
 int seteuid(string str)
 {
-    object ob = efun::previous_object();
-
-    if (!str)
+    object|lwobject ob = efun::previous_object();
+    if(objectp(ob))
     {
-        efun::configure_object(ob, OC_EUID, 0);
+        if (!str)
+        {
+            efun::configure_object(ob, OC_EUID, 0);
+            return 1;
+        }
+
+        if (efun::call_direct(__MASTER_OBJECT__, "valid_seteuid", ob, str) != 1)
+            return 0;
+
+        efun::configure_object(ob, OC_EUID, str);
         return 1;
     }
+    else if (lwobjectp(ob))
+    {
+        if (!str)
+        {
+            efun::configure_lwobject(ob, LC_EUID, 0);
+            return 1;
+        }
 
-    if (efun::call_direct(__MASTER_OBJECT__, "valid_seteuid", ob, str) != 1)
-        return 0;
+        if (efun::call_direct(__MASTER_OBJECT__, "privilege_violation", 
+                "configure_lwobject", ob, ob, LC_EUID, str) != 1)
+            return 0;
 
-    efun::configure_object(ob, OC_EUID, str);
-    return 1;
+        efun::configure_lwobject(ob, LC_EUID, str);
+        return 1;
+
+    }
+    return 0;
 }
 
 #endif
diff --git a/secure/simul_efun/spare/simul_efun.c b/secure/simul_efun/spare/simul_efun.c
index 680f4d5..1b4af5f 100644
--- a/secure/simul_efun/spare/simul_efun.c
+++ b/secure/simul_efun/spare/simul_efun.c
@@ -48,7 +48,7 @@
 nomask varargs int snoop(object snooper, object snoopee);
 varargs string country(mixed ip, string num);
 int query_wiz_grp(object|string wiz);
-public varargs object deep_present(mixed what, object ob);
+public object deep_present(string|object what, object ob=previous_object());
 nomask int secure_level();
 nomask string secure_euid();
 public nomask int process_call();
@@ -726,9 +726,10 @@
   else return(0);
 }
 
-private nomask string _process_string(string str,object po) {
-              set_this_object(po);
-              return(efun::process_string(str));
+private nomask string _process_string(string str, object|lwobject po)
+{
+    set_this_object(po);
+    return(efun::process_string(str));
 }
 
 private nomask int _illegal_ps_call(string s)
@@ -861,7 +862,7 @@
 
 
 // * Properties ggfs. mitspeichern
-mixed save_object(mixed name)
+mixed save_object(string|int name)
 {
   mapping properties;
   mapping save;
@@ -870,13 +871,19 @@
   string oldpath;
 
   // nur Strings und 0 zulassen
-  if ((!stringp(name) || !sizeof(name)) && 
-      (!intp(name) || name!=0)) {
+  if ((!stringp(name) || !sizeof(name)) &&
+      (!intp(name) || name!=0))
+  {
       set_this_object(previous_object());
       raise_error(sprintf(
          "Only non-empty strings and 0 may be used as filename in "
          "sefun::save_object()! Argument was %O\n",name));
   }
+  if(!objectp(previous_object()))
+  {
+    set_this_object(previous_object());
+    raise_error(sprintf("save_object() only calleable by objects!\n"));
+  }
 
   if (stringp(name)) {
     // abs. Pfad erzeugen. *seufz*
@@ -969,6 +976,11 @@
     raise_error("Bad arg 1 to restore_object(): expected non-empty "
                 "'string'.\n");
   }
+  if(!objectp(previous_object()))
+  {
+    set_this_object(previous_object());
+    raise_error(sprintf("restore_object() only calleable by objects!\n"));
+  }
 
   // Wenn name vermutlich ein Pfad (also nicht mit #x:y anfaengt)
   if (name[0] != '#')
@@ -1319,7 +1331,7 @@
 
 mixed call_out_info() {
   
-  object po = previous_object();
+  object|lwobject po = previous_object();
   mixed coi = efun::call_out_info();
 
   // ungefilterten Output nur fuer bestimmte Objekte, Objekte in /std oder
@@ -1348,13 +1360,12 @@
 // * Wir wollen nur EIN Argument ... ausserdem checks fuer den Netztotenraum
 varargs void move_object(mixed what, mixed where)
 {
-  object po,tmp;
-
-  po=previous_object();
+  // Wenn nur ein Argument angegeben wird, ist es das Ziel und wir nehmen
+  // previous_object() als zu bewegendes Objekt.
   if (!where)
   {
     where=what;
-    what=po;
+    what=previous_object();
   }
   if (((stringp(where) && where==NETDEAD_ROOM ) ||
        (objectp(where) && where==find_object(NETDEAD_ROOM))) &&
@@ -1373,7 +1384,7 @@
     }
     set_object_heart_beat(what,0);
   }
-  tmp=what;
+  object tmp=what;
   while (tmp=environment(tmp))
       // Ja. Man ruft die _set_xxx()-Funktionen eigentlich nicht direkt auf.
       // Aber das Lichtsystem ist schon *so* rechenintensiv und gerade der
@@ -1383,7 +1394,7 @@
       //
       // Tiamak
     tmp->_set_last_content_change();
-  funcall(bind_lambda(#'efun::move_object,po),what,where);
+  funcall(bind_lambda(#'efun::move_object,previous_object()),what,where);
   if (tmp=what)
     while (tmp=environment(tmp))
       tmp->_set_last_content_change();
@@ -1461,10 +1472,8 @@
       a[i][WL_ARRAY_TOTAL],a[i][WL_CALL_OUT]));
 }
 
-public varargs object deep_present(mixed what, object ob) {
-
-  if(!objectp(ob))
-    ob=previous_object();
+public object deep_present(string|object what, object ob=previous_object())
+{
   // Wenn ein Objekt gesucht wird: Alle Envs dieses Objekts ermitteln und
   // schauen, ob in diesen ob vorkommt. Dann ist what in ob enthalten.
   if(objectp(what)) {
@@ -1472,7 +1481,7 @@
     // wenn ob kein Environment hat, ist es offensichtlich nicht in what
     // enthalten.
     if (!pointerp(envs)) return 0;
-    if (member(envs, ob) != -1) return what;
+    if (ob in envs) return what;
   }
   // sonst wirds teurer, ueber alle Objekte im (deep) Inv laufen und per id()
   // testen. Dabei muss aber die gewuenschte Nr. ("flasche 3") abgeschnitten
@@ -1514,6 +1523,7 @@
   if(previous_object()==0 || !IS_ARCH(geteuid(previous_object())) 
       || !ARCH_SECURITY)
   {
+    // historical info, but amusing message. ;-)
     write("Call GC now and the mud will crash in 5-6 hours. DONT DO IT!\n");
     return;
   }
@@ -1775,22 +1785,17 @@
     return ret;
 }
 
-nomask varargs int query_next_reset(object ob) {
-
+nomask int query_next_reset(object ob=previous_object())
+{
     // Typpruefung: etwas anderes als Objekte oder 0 sollen Fehler sein.
     if (ob && !objectp(ob))
       raise_error(sprintf("Bad arg 1 to query_next_reset(): got %.20O, "
            "expected object.\n",ob));
 
-    // Defaultobjekt PO, wenn 0 uebergeben.
-    if ( !objectp(ob) )
-      ob = previous_object();
-
     return efun::object_info(ob, OI_NEXT_RESET_TIME);
 }
 
 
-
 // ### Ersatzaufloesung in Strings ###
 varargs string replace_personal(string str, <string|object>* obs, int caps) {
   string* parts = regexplode(str, "@WE[A-SU]*[0-9]");