Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/std/shells/magier/upd.c b/std/shells/magier/upd.c
new file mode 100644
index 0000000..f09ea9a
--- /dev/null
+++ b/std/shells/magier/upd.c
@@ -0,0 +1,563 @@
+// MorgenGrauen MUDlib
+//
+// upd.c
+//
+// $Id: upd.c 8850 2014-06-13 21:34:44Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <player.h>
+#undef NEED_PROTOTYPES
+#include <debug_info.h>
+#include <wizlevels.h>
+#include <moving.h>
+#include <properties.h>
+#include <logging.h>
+#include <thing/properties.h>
+
+varargs static int _make(string file, int flags, int recursive);
+
+static mixed _query_localcmds()
+{
+ return ({({"upd","_upd",0,LEARNER_LVL}),
+ ({"load","_load",0,LEARNER_LVL})});
+}
+
+//
+// _save(): Spieler in Rettungsraum retten
+// obj: Spielerobjekt(?)
+// inv_save: Rettungsraumname
+// Rueckgabe: 0 wenn kein Spielerobjekt
+// Spielerobjekt, falls doch
+//
+
+static mixed _save( object obj, object inv_saver )
+{
+ if ( query_once_interactive(obj) )
+ {
+ obj->move( inv_saver, NO_CHECK );
+ return obj;
+ }
+ return 0;
+}
+
+
+//
+// _reload(): Objekt laden
+// file: Filename. Muss in der Form /xx/xx/xx.c vorliegen
+// clone: > 0 -> Es soll geclont werden, enthaelt Objektnummer des
+// Vorgaengerobjektes
+// flags: Kommandozeilenoptionen
+// err: Leerstring als Referenz uebergeben. Enthaelt nach dem
+// Aufruf vom _reload() die Fehlermeldungen als String.
+// Rueckgabe: Das neu erzeugte Objekt bzw. das schon vorhandene Objekt
+// bzw. 0, wenn Fehler auftrat.
+//
+
+private object _reload(string file, int clone, int flags, string err)
+{
+ object obj;
+
+ if (!obj=find_object(file[0..<3]+(clone?("#"+clone):"")))
+ {
+ int pos,pos2;
+ string bt;
+
+ if(file_size(file)<0)
+ {
+ if (file_size(file)==-1)
+ err = sprintf("upd: %s: Datei existiert nicht.\n", file);
+ else // directory
+ err = sprintf("upd: %s: Verzeichnisse koennen nicht geladen "
+ "werden.\n",file);
+ return obj; // 0
+ }
+ pos = max(file_size(__DEBUG_LOG__),0);
+
+ if ((err = (clone?catch(obj = clone_object(file)):
+ catch(load_object(file)) )) && (flags & UPD_B))
+ {
+ if (( pos2=file_size(__DEBUG_LOG__)) > pos )
+ err+=sprintf("\nBacktrace:\n%s",
+ read_bytes(__DEBUG_LOG__,pos, pos2-pos ));
+ else
+ err+=sprintf("\nKEIN BACKTRACE VERFUEGBAR!\n");
+ }
+ if (!err&&!obj&&(!obj = find_object(file[0..<3])))
+ err += sprintf( "upd: %s: Blueprint nach dem Laden zerstoert.\n",file );
+ }
+ else
+ err=sprintf("upd: Objekt existiert schon: %O\n",obj);
+ return obj;
+}
+
+
+//
+// _update(): File updaten -> Blueprint destructen
+// file: Filename
+// dummy: simulieren? (1->wird nicht aktualisiert)
+// flags: Kommandozeilenoptionen
+// Rueckgabe: -1: Keine Vollzugriff
+// 0: Objekt ist nicht geladen
+// 1: Operation wird durchgefuehrt
+//
+
+private varargs int _update(string file, int dummy, int flags)
+{
+ object obj;
+ string err;
+ if (!dummy && !objectp(obj = find_object(file))) return 0;
+ if (!IS_ARCH(this_object()))
+ {
+ // Schreibrechte nur pruefen, wenn echt aktualisiert werden soll.
+ if(!dummy && !MAY_WRITE(file))
+ return (printf("upd: %s: Keine Schreibrechte!\n",file), -1);
+ if(!MAY_READ(file))
+ return (printf("upd: %s: Keine Leserechte!\n", file), -1);
+ }
+ if (dummy) return 1;
+
+ if ( flags & UPD_D )
+ {
+ object *inv;
+ if (sizeof(inv = deep_inventory(obj)))
+ {
+ printf("upd: %s: Entferne Objekte im Inventar\n", file );
+ if (!(flags&UPD_H))
+ {
+ if(err=catch(filter_objects( inv, "remove", 1 )))
+ printf("upd: %s: Fehlgeschlagen. Grund:\n%s\n",
+ file,err);
+ }
+ if (sizeof(inv = deep_inventory(obj)))
+ filter(inv, function void (object ob)
+ {destruct(ob);});
+ }
+ }
+ if (!(flags&UPD_H))
+ {
+ if(err = catch(obj->remove()))
+ printf("upd: %s: remove() fehlgeschlagen. Aufruf von " +
+ "destruct().\n",file);
+ }
+ if(objectp(obj)) destruct(obj);
+ return 1;
+}
+
+
+//
+// _instance_upd(): Alle Objekte nach Clones des Objekts durchsuchen
+// file: Filename des Objektes
+// flags: Kommandozeilenargumente
+// obj: Aktuelles Objekt
+// instances: Zahl der gefundenen Instanzen
+//
+
+private void _instance_upd(string file, int flags, mixed obj, int instances,
+ int firstcall)
+{
+ int i;
+ if (firstcall)
+ printf("upd: %s: %s Instanzen.\n",file,flags&UPD_A?"Aktualisiere":"Suche");
+
+ while (get_eval_cost()>220000 && i < sizeof(obj))
+ {
+ if (!objectp(obj[i]))
+ instances--;
+ else
+ {
+ if (flags&UPD_F&&!(flags&UPD_S))
+ printf( "upd: %O gefunden in %s\n", obj[i],
+ environment(obj[i])?object_name(environment(obj[i]))
+ : "keiner Umgebung" );
+ if (flags&UPD_A) _make(object_name(obj[i]), flags & ~(UPD_A|UPD_F),1 );
+ }
+ i++;
+ }
+ if (i < sizeof(obj))
+ call_out( #'_instance_upd/*'*/,2,file,flags,obj[i..],instances,0);
+ else
+ printf( "upd: %s: %d Instanzen %s\n", file, instances,
+ (flags & UPD_A) ? "aktualisiert" : "gefunden" );
+ return;
+}
+
+
+//
+// _do_make(): Alle geerbten Objekte bearbeiten (fuer -m/-v)
+// file: Name des Files
+// clone: 0, wenn blueprint, ansonsten Clonenummer
+// flags: Kommandozeilenparameter
+// dep: geschachteltes Array mit Meldungen (wg. Rekursion)
+// ready: Array der schon bearbeiteten Objekte (wg. Rekursion)
+// Rueckgabe: Array der Objektnamen, die bearbeitet wurden
+// (Array in Array in ...)
+//
+
+varargs private int _do_make( string file,int clone,int flags,mixed dep,
+ string *ready )
+{
+ object obj;
+ string err;
+ string *ilist;
+ mixed downdeps;
+ int ret;
+
+ if (!pointerp(ready)) ready = ({});
+ ready += ({ file });
+
+ if ( !(obj = _reload(file,clone,flags,&err)))
+ {
+ dep += ({ err });
+ return 0;
+ }
+
+ ilist = inherit_list(obj)-ready;
+
+ downdeps = ({});
+
+ while (sizeof(ilist))
+ {
+ ret = _do_make( ilist[0],0,flags, &downdeps, &ready )||ret;
+ ilist[0..0] = ({});
+ ilist -= ready;
+ }
+
+ if ( ret||file_time(file)>program_time(obj)||(flags &UPD_I))
+ if ( _make( file, flags & ~(UPD_M|UPD_I) ,1) < 0 )
+ dep = ({ "{" + explode(file,"/")[<1] + "}", downdeps });
+ else{
+ dep = ({ "[" + explode(file,"/")[<1] + "]", downdeps });
+ ret = 1;
+ }
+ else if (flags&UPD_V) dep += ({ explode(file,"/")[<1], downdeps });
+ return ret;
+}
+
+
+//
+// _make_dep(): Ausgabe des Ererbungsbaumes
+// Objekte im Array dep
+// prefix enthaelt Zeilenanfang (fuer Rekursion)
+// Rueckgabe: String mit dem Vererbungsbaum des Objektes
+//
+
+private string _make_dep( mixed dep, string prefix )
+{
+ string ret;
+ int i, size;
+
+ ret="";
+ size=sizeof(dep);
+ for (i=0; i<size;i++)
+ if (pointerp(dep[i]))
+ ret += _make_dep(dep[i],prefix + (i < (size-1) ? "| ":" "));
+ else
+ ret += prefix + "+-" + dep[i] + "\n";
+ return ret;
+}
+
+
+//
+// _illegal_closure(): ist closure in arg an objekt gebunden?
+// arg: closure(-array/mapping)
+// Rueckgabe: 0 wenn alles okay
+// 1 wenn closure geloescht werden muss
+//
+
+private int _illegal_closure( mixed arg )
+{
+ int i, j;
+ string *indices;
+
+ if ( closurep(arg) && !objectp(query_closure_object(arg)) )
+ return 1;
+
+ if ( pointerp(arg) ){
+ for ( i = sizeof(arg); i--; )
+ if ( _illegal_closure(arg[i]) )
+ return 1;
+ }
+ else if ( mappingp(arg) ){
+ indices = m_indices(arg);
+ for ( i = sizeof(indices); i--; )
+ for ( j = get_type_info( arg, 1 ); j--; )
+ if ( _illegal_closure(arg[indices[i], j]) )
+ return 1;
+ }
+ return 0;
+}
+
+//
+// _make(): Update file
+// file: Filename
+// flags: Kommandozeilenargumente
+//
+
+varargs static int _make(string file, int flags,int recursive)
+{
+ string msg, err, blue;
+ int inst;
+ object obj, inv_saver;
+ mixed tmp;
+
+ msg = "";
+
+ if (!file) return printf( "upd: Kein Filename uebergeben!\n" ), RET_FAIL;
+
+// Filename in Blue, Objektname in blue, Instanznummer in inst
+
+ if (sscanf(file,"%s#%d",blue,inst)==2) blue += ".c";
+ else blue = file + (file[<2..]==".c" ? "" : ".c");
+
+// Alle Instanzen durchsuchen im Falle von -a oder -f
+
+ if ((flags & UPD_LOAD)&&find_object(file))
+ return printf("load: %s: Objekt ist schon geladen.\n",file),RET_OK;
+
+ if ( flags & (UPD_F|UPD_A))
+ {
+ if (inst) return printf( "upd: %s: Eine Instanz kann keine " +
+ "Clones haben.\n",file ), RET_FAIL;
+ if ((tmp=_update(file, 1,flags))==-1)
+ return printf( "upd: %s: Kein Vollzugriff auf die " +
+ "Datei erlaubt.\n",file), RET_FAIL;
+ if (tmp==0) return RET_FAIL;
+
+ tmp=clones(blue[0..<3],2);
+ if (sizeof(tmp))
+ call_out( #'_instance_upd/*'*/, 0, file,flags,tmp,sizeof(tmp),1);
+ else
+ printf( "upd: %s: Keine Clones vorhanden!\n", blue[0..<3]);
+
+ if ( (flags & UPD_F) && !(flags &(UPD_R|UPD_L|UPD_LOAD))) return RET_OK;
+ // Nichts laden -> Auch kein Backup
+ }
+
+// Backupraum festlegen
+
+ if( blue==INV_SAVE ) {
+ printf("upd: Achtung: Raum zum Zwischenspeichern soll geladen werden?!\n");
+ }
+ if ( !(inv_saver=load_object(INV_SAVE)) )
+ {
+ printf("upd: %s: Raum zum Zwischenspeichern des " +
+ "Rauminhalts ist nicht ladbar.\n" +
+ " %s\n",file,INV_SAVE);
+ return RET_FAIL;
+ }
+
+// Wenn das Objekt existiert bzw. Deep aktualisiert werden soll
+
+ if ( (!(flags&UPD_LOAD))&&
+ ((obj = find_object(file)) || (flags & (UPD_M|UPD_I))))
+ {
+ object *inv, env, *pl_inv;
+ mapping pro;
+ int i;
+ mixed configdata;
+ int restore_config;
+
+ // Wenn Objekt existiert, dann Inhalt und ggf. Daten aus Configure() oder
+ // Props sichern:
+ if (obj)
+ {
+ // im Fall UPD_C erfolgt _kein_ Auslesen und _keine_ Restauration
+ // mittels Configure()
+ if ( ! (flags & UPD_C ) )
+ {
+ catch(restore_config=(mixed)call_resolved(&configdata,obj,
+ "Configure",0);
+ publish);
+ // Wenn UPD_CONF gesetzt wird, _muss_ das Objekt ein oeffentliches
+ // Configure() definieren, sonst erfolgt Abbruch.
+ if ((flags & UPD_CONF) && !restore_config)
+ {
+ printf("upd: %s: hat kein Configure(), Zerstoerung abgebrochen.\n",file);
+ return RET_FAIL;
+ }
+ }
+ if (!(flags&UPD_D)&&(flags&(UPD_L|UPD_R)))
+ {
+ if (i=sizeof(inv=(all_inventory(obj)-({0}))))
+ {
+ mixed items;
+ // Herausbekommen, ob hier Items existieren, die per AddItem
+ // erzeugt werden. Die duerfen nicht gesichert werden.
+ items=(mixed)obj->QueryProp(P_ITEMS); // mixed, da array of arrays
+ if (pointerp(items)&&sizeof(items))
+ {
+ items=transpose_array(items)[0];
+ while (i--)
+ if (member(items, inv[i])==-1)
+ inv[i]->move(inv_saver,NO_CHECK);
+ }
+ else // In diesem Objekt sind keine Items gesetzt.
+ while (i--) inv[i]->move(inv_saver,NO_CHECK);
+ }
+ }
+ else
+ {
+ inv=map( deep_inventory(obj), #'_save/*'*/, inv_saver )-({0});
+ }
+ env = environment(obj);
+ if ( flags & UPD_C )
+ {
+ pro = (mapping)(obj->QueryProperties());
+ }
+ }
+ else inv = ({});
+
+// Ererbte Objekte durchsuchen.
+ if ( flags & (UPD_M|UPD_I) )
+ {
+ mixed dep;
+ dep = ({});
+ _do_make( blue, inst, flags & ~(UPD_M|UPD_L|UPD_R|UPD_F|UPD_A), &dep );
+ printf( _make_dep( dep, "" ) + "\n" );
+ }
+
+// Tatsaechlichen Update durchfuehren
+
+ if ( _update(file, 0, flags)< 0) return RET_FAIL;
+ msg += (inst ? "zerstoert" : "aktualisiert");
+
+// Neu laden ??
+ if ( flags & (UPD_R|UPD_L) )
+ {
+ if ( obj = _reload( blue,inst,flags, &err ) )
+ msg += ", " + (inst ? "neu geclont" : "neu geladen");
+
+// Neu geladen: Properties wiederherstellen, Closures filtern
+ if (!err)
+ {
+ if (!obj) obj = find_object(file);
+ // Wenn gewuenscht, Props zurueckschreiben (hat Prioritaet vor
+ // Configure(), weil explizit vom Magier angefordert).
+ if ( pro && (flags & UPD_C) )
+ {
+ string *names;
+
+ names = m_indices(pro);
+
+ // Closures in (mittlerweile) zerstoerten Objekten
+ // rausfiltern, damit die (hoffentlich korrekten) Closures
+ // im neu geclonten Objekt erhalten bleiben
+ for ( i = sizeof(names); i--; )
+ if ( _illegal_closure(pro[names[i], F_VALUE]) ||
+ _illegal_closure(pro[names[i], F_QUERY_METHOD]) ||
+ _illegal_closure(pro[names[i], F_SET_METHOD]) )
+ m_delete( pro, names[i] );
+
+ obj->SetProperties(pro);
+ msg += ", Properties gesetzt";
+ }
+ // Wenn kein UPD_C, wird ggf. das Ergebnis von Configure() wieder
+ // uebergeben.
+ else if (restore_config)
+ {
+ int conf_res;
+ if (!catch(conf_res=(int)obj->Configure(configdata); publish)
+ && conf_res == 1)
+ {
+ msg += ", (re-)konfiguriert";
+ }
+ else
+ {
+ msg += ", (Re-)Konfiguration fehlgeschlagen";
+ if (flags & UPD_CONF)
+ printf("upd: Daten von %s konnten nicht rekonfiguriert werden: "
+ "%O\n", file, configdata);
+ }
+ }
+ if (env)
+ {
+ if ( obj->move( env, NO_CHECK ) <= 0 )
+ printf( "upd: /%O konnte nicht in /%O zurueckbewegt werden\n",
+ obj, env );
+ else
+ msg += ", bewegt";
+ }
+ if (i=sizeof(inv))
+ {
+ while(i--) if (inv[i]) inv[i]->move(obj, NO_CHECK );
+ msg += ", Inhalt zurueckbewegt";
+ }
+ }
+ else
+ return printf( "upd: %s: %s", file, err ), RET_FAIL;
+ }
+ }
+ else
+ if ( !_update(file, 0, flags) && (flags & (UPD_L|UPD_LOAD)) )
+ if ( !_reload( blue, inst, flags, &err ) )
+ return printf( "%s: %s: %s", (flags&UPD_LOAD?"load":"upd"),file, err ),
+ RET_FAIL;
+ else
+ msg += "geladen";
+
+ if ( sizeof(msg)&&!(flags&UPD_S&&recursive) )
+ printf("%s: %s: %s.\n",(flags&UPD_LOAD?"load":"upd"),file,msg);
+ return RET_OK;
+}
+
+//
+// _upd: Objekte laden, zerstoeren und aktualisieren
+//
+
+static int _upd(string cmdline)
+{
+ int flags;
+ mixed *args;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,UPD_OPTS,1);
+ if(flags==-1||!sizeof(args))
+ return USAGE("upd [-"+UPD_OPTS+"] <datei> [<datei> ..]");
+ if ((flags & UPD_C) && (flags & UPD_CONF))
+ {
+ printf("upd: -c und -C gleichzeitig werden nicht unterstuetzt.\n");
+ return 1;
+ }
+ args=file_list(args,MODE_UPD,0,"/");
+ if(!sizeof(args)) return printf("upd: Keine passende Datei gefunden!\n"),1;
+
+ args=map(args,(: $1[FULLNAME] :))-({0});
+
+ if(!sizeof(args))
+ {
+ printf("upd: Verzeichnisse koennen nicht aktualisiert werden!\n");
+ return 1;
+ }
+ asynchron(args,#'_make,flags,0,0);
+ return 1;
+}
+
+//
+// _load: Objekte laden
+//
+
+static int _load(string cmdline)
+{
+ int flags;
+ mixed *args;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,"",1);
+ if(flags==-1||!sizeof(args))
+ return USAGE("load <datei> [<datei> ..]");
+ args=file_list(args,MODE_UPD,0,"/");
+ if(!sizeof(args)) return printf("load: Keine passende Datei gefunden!\n"),1;
+ args=map(args,(: (($1[FILESIZE]!=-2||find_object($1[FULLNAME]))?
+ $1[FULLNAME]:0) :))-({0});
+
+ if(!sizeof(args))
+ return printf("load: Verzeichnisse koennen nicht geladen werden!\n"),1;
+ asynchron(args,#'_make,UPD_LOAD,0,0);
+ return 1;
+}