blob: abba89578c6c3a0765aed88abe5fb164efc88a9c [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// master.c -- master object
4//
5// $Id: master.c 9530 2016-03-17 19:59:01Z Zesstra $
Zesstra9dd50132019-11-28 21:42:14 +01006#pragma strict_types
7#pragma no_clone
8#pragma no_shadow
9#pragma no_inherit
10#pragma verbose_errors
11#pragma combine_strings
12//#pragma pedantic
MG Mud User88f12472016-06-24 23:31:02 +020013#pragma range_check
14#pragma warn_deprecated
15
16#include "/sys/files.h"
17#include "/sys/interactive_info.h"
18#include "/sys/driver_info.h"
19
MG Mud User88f12472016-06-24 23:31:02 +020020//for limited, set_limit(), etc. Abs. Pfad noetig, da noch kein Include-Hook
21#include "/sys/rtlimits.h"
22#include "/sys/debug_info.h"
MG Mud User88f12472016-06-24 23:31:02 +020023#include "/sys/configuration.h"
Zesstraa6068542019-09-30 23:21:45 +020024#include "/sys/driver_hook.h"
MG Mud User88f12472016-06-24 23:31:02 +020025#include "/sys/regexp.h"
26
Zesstra9dd50132019-11-28 21:42:14 +010027#include "/secure/master.h"
28#include "/secure/config.h"
MG Mud User88f12472016-06-24 23:31:02 +020029// Module des Master einfuegen. Per #include, damits geringfuegig schneller.
30// Da die Module ja nirgendwo sonst geerbt werden koennten, ist dies
31// ausnahmsweise OK. ;)
32#include "/secure/master/destruct.c"
Zesstra9dd50132019-11-28 21:42:14 +010033#include "/secure/master/userinfo.c"
34#include "/secure/master/file_access.c"
35#include "/secure/master/misc.c"
36#include "/secure/master/players_deny.c"
MG Mud User88f12472016-06-24 23:31:02 +020037#include "/secure/master/autoinclude.c"
Zesstra9dd50132019-11-28 21:42:14 +010038#include "/secure/master/network.c"
39#include "/secure/master/domain.c"
40#include "/secure/master/guild.c"
41
MG Mud User88f12472016-06-24 23:31:02 +020042
43// Fuer Logfile(-Rotation)
44#define RESETINT 3600 // jede Stunde
45#define LOGROTATE (24*2) // alle 48h
46#define LOGFILEAGE (RESETINT*LOGROTATE) // alle 2 tage wechseln
47#define LOGNUM 3 // Anzahl der Logfiles
48
49private nosave int logrotate_counter; //READ_FILE alle LOGROTATE Resets rotieren
50// Wird gerade versucht, die simul_efuns zu laden? Wenn ja, duerfen keine
51// sefuns gerufen werden.
52private nosave int loading_simul_efuns;
53// wird gerade ein Fehler bearbeitet? Dient zur Erkennung von Rekursionen in
54// der Fehlerbehandlung
55private nosave int handling_error;
56
57// #####################
58//######################## Start des Masters ############################
59// #####################
60
61// Initialisierung des Masters
62//arg==0: Mud startet gerade, arg==1: Master wurde reaktiviert,
63//arg==2: Master reaktiviert (Variablen weg), arg==3: Master wurde
64//neugeladen.
65protected void inaugurate_master(int arg) {
66
67 set_driver_hook(H_REGEXP_PACKAGE, RE_TRADITIONAL);
Bugfix05c09d72017-02-14 21:26:20 +010068
Zesstra86607bb2017-06-17 19:02:40 +020069 efun::configure_object(this_object(), OC_EUID, ROOTID);
Bugfix05c09d72017-02-14 21:26:20 +010070
71 // Bei Neustart wizinfo initialisieren und ggf. Ordner in /data erstellen.
72 if (!arg)
73 {
74 set_extra_wizinfo(0, allocate(BACKBONE_WIZINFO_SIZE));
75 CreateDataDirectories();
76 }
77
Zesstra9dd50132019-11-28 21:42:14 +010078 userinfo_init();
MG Mud User88f12472016-06-24 23:31:02 +020079 LoadPLDenylists();
80
81 // Was soll vor jede Datei geschrieben werden?
82 set_driver_hook(H_AUTO_INCLUDE, #'autoincludehook);
83
84 //div. Listen einlesen
85 ReloadBanishFile();
86 ReloadDeputyFile();
87 ReloadInsecureFile();
Bugfix05c09d72017-02-14 21:26:20 +010088
MG Mud User88f12472016-06-24 23:31:02 +020089 //simul_efun.c nach inaugurate_master() starten und initialisieren,
90 //(so richtig seh ich den Sinn hier momentan nicht ein...
91 //call_out("start_simul_efun",0);
92
93 // Reset festsetzen (1h)
94 set_next_reset(RESETINT);
95
96 // Driver konfigurieren
97 // Lagerkennung erst ne Minute spaeter, waehrend preload darfs momentan
98 // ruhig laggen (Zeit: vorlaeufig 1min)
Zesstra92bb2dd2019-11-28 21:45:19 +010099 call_out(#'configure_driver, 60, DC_LONG_EXEC_TIME, 200000);
Zesstra879e6e12019-09-27 16:23:49 +0200100
MG Mud User88f12472016-06-24 23:31:02 +0200101 // Hooks setzen
Zesstra879e6e12019-09-27 16:23:49 +0200102
103 // Standard-Encoding fuer Dateien
104 set_driver_hook(H_FILE_ENCODING, "UTF-8");
105 // Und Encoding fuer Dateinamen im Filesystem
106 configure_driver(DC_FILESYSTEM_ENCODING, "UTF-8");
Zesstraa1701ed2020-01-16 23:06:09 +0100107 // Standard-Encoding fuer Interactives
Zesstra0ebec872020-01-17 00:24:57 +0100108 configure_interactive(0, IC_ENCODING, "ASCII//TRANSLIT");
Zesstra879e6e12019-09-27 16:23:49 +0200109
MG Mud User88f12472016-06-24 23:31:02 +0200110 // Standardincludeverzeichnisse fuer #include <>
111 set_driver_hook(H_INCLUDE_DIRS, ({"/secure/","/sys/"}) );
Zesstra879e6e12019-09-27 16:23:49 +0200112
MG Mud User88f12472016-06-24 23:31:02 +0200113 //Nach dem Laden/Clonen create() im Objekt rufen
114 set_driver_hook(H_CREATE_CLONE, "create");
115 set_driver_hook(H_CREATE_OB, "create");
116 set_driver_hook(H_CREATE_SUPER, "create_super");
Zesstraddddbf72021-05-14 16:52:16 +0200117#if MUDHOST != __HOST_NAME__
118 // LWOs sollen vorerst nur in Homemuds getestet werden.
119 set_driver_hook(H_CREATE_LWOBJECT, "create_lw");
120 set_driver_hook(H_LWOBJECT_UIDS, #'lwo_uid_hook);
121#endif
MG Mud User88f12472016-06-24 23:31:02 +0200122
123 // Bei Reset reset() im Objekt aufrufen
124 set_driver_hook(H_RESET, "reset");
Zesstra879e6e12019-09-27 16:23:49 +0200125
MG Mud User88f12472016-06-24 23:31:02 +0200126 // Zum Aufraeumen clean_up() im Objekt aufrufen
127 set_driver_hook(H_CLEAN_UP, "clean_up");
128
129 // Jede Eingabe wird ueber modify_command gelenkt
130 set_driver_hook(H_MODIFY_COMMAND, "modify_command");
131 // Dieser Hook ist mandatory, aber wird nur benutzt, wenn via
132 // set_modify_command() aktiviert - was wir nicht (mehr) tun. Insofern ist
133 // das Relikt aus alten Zeiten.
134 //set_driver_hook(H_MODIFY_COMMAND_FNAME, "modify_command");
135
136 // Standard-Fehlermeldung
137 //set_driver_hook(H_NOTIFY_FAIL, "Wie bitte?\n");
138 set_driver_hook(H_NOTIFY_FAIL, function string (string cmd, object tp)
Zesstrad872d182019-11-28 20:13:02 +0100139 {if (tp && stringp(cmd=({string})tp->QueryProp(P_DEFAULT_NOTIFY_FAIL)))
MG Mud User88f12472016-06-24 23:31:02 +0200140 return(cmd);
141 return("Wie bitte?\n");});
142
143 // Was machen bei telnet_neg
144 set_driver_hook(H_TELNET_NEG,"telnet_neg");
MG Mud User88f12472016-06-24 23:31:02 +0200145
146 // Promptbehandlung: Defaultprompt setzen und dafuer sorgen, dass alle
147 // Promptausgaben durch print_prompt im Interactive laufen, damit das EOR
148 // angehaengt wird.
149 set_driver_hook(H_PRINT_PROMPT, "print_prompt");
150 set_driver_hook(H_DEFAULT_PROMPT, "> ");
151
152 // EUID und UID muessen neue Objekte auch noch kriegen, Hooks dafuer setzen
153 set_driver_hook(H_LOAD_UIDS, #'load_uid_hook);
154 set_driver_hook(H_CLONE_UIDS, #'clone_uid_hook);
155
156 // Meldung bei vollem Mud
157 set_driver_hook(H_NO_IPC_SLOT, "Momentan sind leider zuviele Spieler im "
158 +MUDNAME+" eingeloggt.\nBitte komm doch etwas spaeter nochmal "
159 "vorbei!\n");
160
161 // Nun der beruechtigte Move-Hook ...
162 // (bewegt objekt und ruft alle notwendigen inits auf)
163 // Hier wird H_MOVE_OBJECT0 benutzt, d.h. die lambda wird an das aktuelle
164 // Objekt vor Ausfuehrung gebunden, nicht an 'item', was move_objet()
165 // uebergeben wurde.
166 set_driver_hook(H_MOVE_OBJECT0,
167 unbound_lambda(({'item,'dest}),
168 ({#',, // item!=this_object?
169 ({#'?,({#'!=,'item,({#'this_object})}),
170 ({#'raise_error, // ->Fehler!
171 "Illegal to move other object than this_object()\n"}) }),
Zesstra1b809c72018-03-02 00:31:58 +0100172 ({#'=,'oldenv,({#'environment,'item}) }), // altes Env merken
MG Mud User88f12472016-06-24 23:31:02 +0200173 ({#'efun::set_environment,'item,'dest}), // item nach dest bewegen
174 ({#'?,
175 ({#'living,'item}), // living(item)?
176 ({#',,
177 ({#'efun::set_this_player,'item}), // set_this_player(item)
Zesstra1b809c72018-03-02 00:31:58 +0100178 ({#'call_other,'dest,"init",'oldenv}),// dest->init(oldenv)
MG Mud User88f12472016-06-24 23:31:02 +0200179 ({#'?!,
180 ({#'&&, // !objectp(item)||
181 ({#'objectp, 'item}), // env(item)!=dest?
182 ({#'==,({#'environment, 'item}),'dest})}),
183 ({#'return})})})}), // -> fertig
184 ({#'=,'others,({#'-,({#'all_inventory,'dest}),({#'({,'item})})}),
185#ifdef EMACS_NERV
186 }) // Emacs kann ({#'({ nicht parsen // others=all_inv(dest)-
187#endif // ({item})
Zesstra1b809c72018-03-02 00:31:58 +0100188 ({#'filter,'others,lambda(({'ob,'item,'lastenv}),
MG Mud User88f12472016-06-24 23:31:02 +0200189 ({#'?,
190 ({#'&&,
191 ({#'objectp,'item}), // objectp(item)&&
192 ({#'living,'ob}), // living(ob)&&
193 ({#'==,({#'environment,'item}),({#'environment,'ob})})}),
194 ({#',, // env(item)==env(ob)?
195 ({#'efun::set_this_player, 'ob}), // set_this_player(ob)
Zesstra1b809c72018-03-02 00:31:58 +0100196 ({#'call_other,'item, "init",'lastenv}) // item->init(lastenv)
197 })})),'item,'oldenv}),
MG Mud User88f12472016-06-24 23:31:02 +0200198 ({#'?,
199 ({#'living,'item}), // living(item)?
200 ({#',,
201 ({#'efun::set_this_player,'item}), // set_this_player(item)
Zesstra1b809c72018-03-02 00:31:58 +0100202 ({#'filter,'others,lambda(({'ob,'item,'lastenv}),
MG Mud User88f12472016-06-24 23:31:02 +0200203 ({#'?,
204 ({#'&&,
205 ({#'objectp,'item}), // objectp(item)&&
206 ({#'objectp,'ob}), // objectp(ob)&&
207 ({#'==,({#'environment,'item}),({#'environment,'ob})})
208 }), // env(item)==env(ob)?
Zesstra1b809c72018-03-02 00:31:58 +0100209 ({#'call_other,'ob,"init",'lastenv}) // ob->init(lastenv)
210 })),'item, 'oldenv})})}),
MG Mud User88f12472016-06-24 23:31:02 +0200211 ({#'?,
212 ({#'&&,
213 ({#'objectp,'item}), // objectp(item)&&
214 ({#'living,'dest}), // living(dest)&&
215 ({#'==,({#'environment,'item}),'dest})// env(item)==dest?
216 }),
217 ({#',,
218 ({#'efun::set_this_player,'dest}), // set_this_player(dest)
Zesstra1b809c72018-03-02 00:31:58 +0100219 ({#'call_other,'item,"init",'oldenv})})})}))); //item->init(oldenv)
MG Mud User88f12472016-06-24 23:31:02 +0200220 DEBUG("Master inaugurated");
221 return;
222}
223
224// epilog() gibt die Dateien zurueck, die vorgeladen werden muessen
225protected string *epilog(int eflag) {
226 string *files, *domains;
227 int i;
228
Zesstra86607bb2017-06-17 19:02:40 +0200229 efun::configure_object(this_object(), OC_EUID, ROOTID);
MG Mud User88f12472016-06-24 23:31:02 +0200230 ReloadBanishFile();
231 ReloadDeputyFile();
232 ReloadInsecureFile();
233
234 if (eflag) {
Zesstrad77ab422019-09-27 17:39:27 +0200235 debug_message(
236 "epilog(): -e angegeben -> Preloading unterdrueckt ...\n",
237 DMSG_STAMP);
MG Mud User88f12472016-06-24 23:31:02 +0200238 return 0;
239 }
240
Zesstrad77ab422019-09-27 17:39:27 +0200241 debug_message("Preloading gestartet.\n", DMSG_STAMP);
MG Mud User88f12472016-06-24 23:31:02 +0200242
243 //Files fuers Preloading und Regionen holen
244 files=explode_files("/std/preload_file") + explode_files("/d/preload_file");
245 domains=get_domains() + ({"erzmagier"}); // EM haben auch ein Preload File
246
247 for (i=sizeof(domains);i--;)
248 files+=explode_files("/d/"+domains[i]+"/preload_file");
Zesstrad77ab422019-09-27 17:39:27 +0200249
MG Mud User88f12472016-06-24 23:31:02 +0200250 return files;
251}
252
253// preload() wird fuer jeder Datei im Preload einmal durchlaufen
254protected void preload(string file) {
255 string err;
256 string name;
257 int *res, zeit;
258
259 // Kein richtiger Dateiname: fertig
260 if(!file || !file[0] || file[0] == ';' || file_size(file+".c") < 0) return;
261
262 // Kein Besitzer -> Meldung ausgeben, fertig
263 if (!(name=creator_file(file)))
264 {
Zesstrad77ab422019-09-27 17:39:27 +0200265 debug_message(
266 sprintf("preload: Kein Besitzer gefunden fuer Datei %s.\n",file),
267 DMSG_STDOUT|DMSG_STDERR);
MG Mud User88f12472016-06-24 23:31:02 +0200268 return;
269 }
270
Zesstra86607bb2017-06-17 19:02:40 +0200271 efun::configure_object(this_object(), OC_EUID, name);
MG Mud User88f12472016-06-24 23:31:02 +0200272
273 // Dann mal laden .. dabei Zeit messen
274 zeit = apply(#'+,rusage()[0..1]);
275
276 // Waehrend des Preloads sind 1.5MTicks leider nicht soviel, insb. wenn
277 // sowas wie der channeld jede menge Objekte laden muss, die wiederum erst
278 // das ganze Geraffel aus /std/ laden. Daher hier einfach mal fuers Preload
279 // die Grenze hoch.
280 err = catch(limited(#'load_object,({5000000}),file));
281
282 if (err != 0)
Zesstrad77ab422019-09-27 17:39:27 +0200283 debug_message(sprintf("\nFehler beim Laden von %s:\n%s\n",file,err),
284 DMSG_STDOUT|DMSG_STDERR);
MG Mud User88f12472016-06-24 23:31:02 +0200285 else
286 {
Zesstrad77ab422019-09-27 17:39:27 +0200287 // Datei, Besitzer und Ladezeit ausgeben
MG Mud User88f12472016-06-24 23:31:02 +0200288 zeit=apply(#'+,rusage()[0..1])-zeit;
Zesstrad77ab422019-09-27 17:39:27 +0200289 debug_message(sprintf("%-50s%-15s (%2d.%:02d s)\n",
290 file, name, zeit/1000,zeit%1000));
MG Mud User88f12472016-06-24 23:31:02 +0200291 }
292
293 // Noch EUID zuruecksetzen
Zesstra86607bb2017-06-17 19:02:40 +0200294 efun::configure_object(this_object(), OC_EUID, ROOTID);
MG Mud User88f12472016-06-24 23:31:02 +0200295
296 return;
297}
298
299//simul_efun.c laden oder die spare_simul_efun.c als Fallback
300//es ist moeglich, hier ein Array von strings zurueckzugeben. Die
301//nachfolgenden gelten als Backup-Objekte, falls eine sefun im Hauptobjekt
302//nicht gefunden wird.
303protected string *get_simul_efun() {
304 string err;
305
306 ++loading_simul_efuns;
307
bugfixd94d0932020-04-08 11:27:13 +0200308 if (!(err=catch(({void})SIMUL_EFUN_FILE->start_simul_efun())) ) {
MG Mud User88f12472016-06-24 23:31:02 +0200309 --loading_simul_efuns;
310 return ({SIMUL_EFUN_FILE});
311 }
Zesstrad77ab422019-09-27 17:39:27 +0200312
MG Mud User88f12472016-06-24 23:31:02 +0200313 debug_message("Failed to load simul efun " + SIMUL_EFUN_FILE +
Zesstrad77ab422019-09-27 17:39:27 +0200314 " " + err, DMSG_STDOUT | DMSG_LOGFILE | DMSG_STAMP);
MG Mud User88f12472016-06-24 23:31:02 +0200315
bugfixd94d0932020-04-08 11:27:13 +0200316 if (!(err=catch(({void})SPARE_SIMUL_EFUN_FILE->start_simul_efun())) ) {
MG Mud User88f12472016-06-24 23:31:02 +0200317 --loading_simul_efuns;
318 return ({SPARE_SIMUL_EFUN_FILE});
319 }
MG Mud User88f12472016-06-24 23:31:02 +0200320
Zesstrad77ab422019-09-27 17:39:27 +0200321 debug_message("Failed to load spare simul efun " + SPARE_SIMUL_EFUN_FILE +
322 " " + err, DMSG_STDOUT | DMSG_LOGFILE | DMSG_STAMP);
323
324
MG Mud User88f12472016-06-24 23:31:02 +0200325 efun::shutdown();
Zesstrad77ab422019-09-27 17:39:27 +0200326
MG Mud User88f12472016-06-24 23:31:02 +0200327 return 0;
328}
329
330protected mixed call_sefun(string sefun, varargs mixed args) {
331 if (!loading_simul_efuns)
332 return apply(symbol_function(sefun), args);
333 else {
334 switch(sefun) {
335 case "log_file":
336 case "secure_level":
337 case "secure_euid":
338 case "find_player":
339 case "find_netdead":
340 case "find_living":
341 case "process_call":
342 case "replace_personal":
343 case "file_time":
344 return 0;
345 case "dtime":
346 if (pointerp(args) && sizeof(args))
347 return strftime("%a %d. %b %Y, %H:%M:%S",args[0]);
348 else
349 return strftime("%a %d. %b %Y, %H:%M:%S");
350 case "uptime":
351 return to_string(time()-__BOOT_TIME__) + " Sekunden";
352 }
353 }
354 return 0;
355}
356
357
358// Preload manuell wiederholen; Keine GD-Funktion
359void redo_preload()
360{
361 string *to_preload;
362 int i,j;
363
364 to_preload=epilog(0);
365 j=sizeof(to_preload);
366 for (i=0;i<j;i++)
367 catch(preload(to_preload[i]));
368 return;
369}
370
371// ##################
372//########################## Standard-Lfuns #############################
373// ##################
374
375// Keine GD-Funktion, aber sinnvoll.
376public varargs int remove(int silent)
377{
378 write("Der Master will aber nicht zerstoert werden!\n");
379 return 0;
380}
381
382// Einige repetitiven Taetigkeiten kann der Reset erledigen
383protected void reset()
384{
385 int i, *date;
386 mixed *wl;
387
388 //Darf nicht von Hand aufgerufen werden!
389 if (TI||TP) return;
390
391 // Naechsten Reset setzen
392 set_next_reset(RESETINT);
393
394 // Userinfo aufraeumen
395 _cleanup_uinfo();
396
397 // Projekt-Cache loeschen
398 _cleanup_projects();
399
400 // Wenn Zeit abgelaufen, dann READ_FILE-Log rotieren
401 if (!logrotate_counter--)
402 {
403 i=time()/LOGFILEAGE;
404 date=get_dir(sprintf("%s.%d", READ_FILE,i%LOGNUM), GETDIR_DATES);
405 if (pointerp(date)&&sizeof(date)&&
406 (date[0]/LOGFILEAGE)==i) return;
407 if (file_size(READ_FILE)>0)
408 rename(READ_FILE, sprintf("%s.%d", READ_FILE,i%LOGNUM));
409 logrotate_counter=LOGROTATE;
410 }
411 // einmal am Tag die UIDAliase resetten. Hierzu wird der logrotate_counter
412 // missbraucht.
413 if (!(logrotate_counter%24)) {
414 ResetUIDAliase();
415#ifdef _PUREFTPD_
416 expire_ftp_user();
417#endif
418 }
419
420 // Wizlist altert
421 wl = wizlist_info();
422 for (i=sizeof(wl); i--; )
423 set_extra_wizinfo(wl[i][WL_NAME], wl[i][WL_EXTRA] * 99 / 100);
424
MG Mud User88f12472016-06-24 23:31:02 +0200425 return;
426}
427
428
429// #################
430//########################## ID-Management ##############################
431// #################
432
433// Magier-ID fuer Datei str (als Objekt oder als String) ermitteln
Zesstraddddbf72021-05-14 16:52:16 +0200434public string creator_file(mixed str)
435{
MG Mud User88f12472016-06-24 23:31:02 +0200436 string *strs,tmp;
437 int s;
438
Zesstraa43be352018-11-06 22:40:32 +0100439 // path_array nach strs
MG Mud User88f12472016-06-24 23:31:02 +0200440 // TODO: was ist mit clones?
441 if(objectp(str))
Zesstraccc58df2018-11-07 23:25:20 +0100442 strs=path_array(object_name(str));
MG Mud User88f12472016-06-24 23:31:02 +0200443 else if(stringp(str))
Zesstraccc58df2018-11-07 23:25:20 +0100444 strs=path_array(str);
MG Mud User88f12472016-06-24 23:31:02 +0200445 else return NOBODY;
446
447 // absolute Pfade interessieren hier gerade nicht.
448 strs -= ({""});
449
450 s=sizeof(strs);
451 if(s<2) return NOBODY;
452
453 switch(strs[0]) {
454 case DOMAINDIR:
455 // Fuer Nicht-Magier bzw. "Pseudo-"Magier die Regionskennung
456 if( s==2 || WIZLVLS[strs[2]] || !IS_LEARNER(strs[2]) )
457 return strs[1];
458
459 // in /d/erzmagier gibt es Magier-IDs
460 if (strs[1]=="erzmagier") return strs[2];
461
462 // Ansonsten d.region.magiername
463 return sprintf("d.%s.%s", strs[1], strs[2]);
464
465 case PROJECTDIR:
466 // In p.service gibt es ids mit uid
467 if (s>2 && strs[1]=="service") return "p.service."+strs[2];
468
469 // Ansonsten nur p.projekt (p.service ist auch hier drin)
470 return "p."+strs[1];
471
472 case WIZARDDIR:
473 if (s>2)
474 return strs[1];
475 if (s==2 && file_size(strs[0]+"/"+strs[1])==FSIZE_DIR)
476 return strs[1];
477 return NOBODY;
478
479 case SECUREDIR:
480 return ROOTID;
481
482 case GUILDDIR:
483 case SPELLBOOKDIR:
484 tmp=strs[1];
485 if (tmp[<2..<2]==".") tmp=tmp[0..<3];
486 if ((s=member(tmp,'.'))>0) tmp=tmp[s+1..];
487 return "GUILD."+tmp;
488
489 case LIBROOMDIR:
490 return ROOMID;
491
492 case STDDIR:
493 case LIBOBJDIR:
494 return BACKBONEID;
495
496 case DOCDIR:
497 return DOCID;
498
499 case MAILDIR:
500 return MAILID;
501 case NEWSDIR:
502 return NEWSID;
503
504 case LIBITEMDIR:
505 return ITEMID;
506
507 /* Fall-Through */
508 default:
509 return NOBODY;
510
511 }
512 return NOBODY; //should never be reached.
513}
514
515// UID und EUID an Objekt geben (oder eben nicht)
516// Keine GD-Funktion, aber von Hooks aufgerufen
Zesstraddddbf72021-05-14 16:52:16 +0200517protected mixed give_uid_to_object(string datei, object|lwobject po)
MG Mud User88f12472016-06-24 23:31:02 +0200518{
519 string creator,pouid;
520
521 // Parameter testen
Zesstraddddbf72021-05-14 16:52:16 +0200522 if (!datei || !po) return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200523
524 // Keine Objekte in /log, /open oder /data
525 if (strstr(datei, "/"LIBDATADIR"/") == 0
526 || strstr(datei, "/"LIBLOGDIR"/") == 0
527 || strstr(datei, "/"FTPDIR"/") == 0
528 )
529 return 1;
530
531 // Datei muss Besitzer haben
532 if (!(creator=creator_file(datei))) return 1;
533
534 // Hack, damit simul_efun geladen werden kann
535 if (creator==ROOTID && po==TO) return ROOTID;
536
537 // Keine euid, kein Laden ...
538 if (!(pouid=geteuid(po))) return 1; // Disallow if no euid in po
539
Zesstraf626b012020-01-05 20:43:03 +0100540 // Root soll keine Root-Objekte via den BACKBONEID-Mechanismus weiter
541 // unten generieren.
542 // Ausserdem nur UID setzen, keine eUID.
MG Mud User88f12472016-06-24 23:31:02 +0200543 if (pouid==ROOTID)
Zesstraddddbf72021-05-14 16:52:16 +0200544 return ({creator,NOBODY});
MG Mud User88f12472016-06-24 23:31:02 +0200545
Zesstraf626b012020-01-05 20:43:03 +0100546 // EUID mitsetzen, wenn PO und creator dieselbe UID sind.
547 // Wenn creator die BACKBONEID ist (im allg. liegt das Objekt dann in
548 // LIBOBJDIR), bekommt das Objekt nicht die BACKBONEID, sondern die UID des
549 // Erzeguers. Auch hier wird die eUID mitgesetzt.
MG Mud User88f12472016-06-24 23:31:02 +0200550 if (creator==pouid || creator==BACKBONEID)
551 return pouid;
552
553 return ({creator,NOBODY});
554}
555
Zesstraddddbf72021-05-14 16:52:16 +0200556// EUID und UID werden von give_uid_to_object() vergeben, diese sind in
557// inaugurate_master() als driver hooks angemeldet.
558
559protected mixed load_uid_hook(string datei) {
560 return(give_uid_to_object(datei, previous_object()));
561}
562
563protected mixed clone_uid_hook(object bluep, string new_name) {
564 return(give_uid_to_object(new_name, previous_object()));
565}
566
567protected mixed lwo_uid_hook(object bluep) {
568 return(give_uid_to_object(object_name(bluep), previous_object()));
569}
570
MG Mud User88f12472016-06-24 23:31:02 +0200571// Die System-IDs muessen bekannt sein
572string get_master_uid() { return ROOTID;}
573string get_bb_uid() { return BACKBONEID; }
MG Mud User88f12472016-06-24 23:31:02 +0200574
575// ##########################
576//###################### Sonstige GD-Funktionen #########################
577// ##########################
578
579// Spieler hat sich eingeloggt
580protected object connect()
581{
582 string err;
583 int errno;
584 object ob,bp;
585
586#if defined(SSLPORT) && __EFUN_DEFINED__(tls_available)
587 if (efun::interactive_info(this_player(), II_MUD_PORT) == SSLPORT) {
588 // reject connection of TLS is not available
589 if (!tls_available())
590 return 0;
591 // establish TLS
592 errno=tls_init_connection();
593 if (errno < 0) {
594 // Fehler im Vebindungsaufbau
595 printf("Can't establish a TLS/SSL encrypted connection: %s\n",
596 tls_error(errno));
597 return 0; // this will close the connection to the client.
598 }
599 }
600#endif
601
602 // Blueprint im Environment? Das geht nun wirklich nicht ...
603 if ((bp=find_object("/secure/login")) && environment(bp))
604 catch(destruct(bp);publish);
605
606 // Login-Shell clonen
607 err = catch(ob = clone_object("secure/login"); publish);
608
609 if (errno == 0 && err)
610 write("Fehler beim Laden von /secure/login.c\n"+err+"\n");
611
612 return ob;
613}
614
615// Was machen bei disconnect?
616protected void disconnect(object who, string remaining) {
Zesstrabfdcd9d2020-09-21 19:19:35 +0200617 ({void})who->NetDead();
618 return;
MG Mud User88f12472016-06-24 23:31:02 +0200619}
620
621// Es gibt kein File 'filename'. VC aktivieren so vorhanden ...
622protected object compile_object(string filename)
623{
624 object ret;
625 string *str;
626 string compiler;
627
628 if (!sizeof(filename)) return 0;
629 str=efun::explode(filename,"/");
630
631 if(sizeof(str)<2) return 0;
632 compiler=implode(str[0..<2],"/")+"/virtual_compiler";
633
634 if (find_object(compiler)
635 || file_size(compiler+".c")>0)
636 {
637 if(catch(
Zesstrad872d182019-11-28 20:13:02 +0100638 ret=({object})call_other(compiler,"compile_object",str[<1]); publish))
MG Mud User88f12472016-06-24 23:31:02 +0200639 return 0;
640 }
641 else
642 return(0);
643
644 if ( objectp(ret) && efun::explode(creator_file(filename), ".")[<1] !=
645 REAL_EUID(ret) ){
646 funcall( symbol_function('log_file/*'*/), "ARCH/VC_MISSBRAUCH",
647 sprintf( "%s: %s versucht per VC %s zu %s umzubenennen!\n",
648 funcall( symbol_function('dtime/*'*/), time() ),
649 (this_interactive() ? getuid(this_interactive()):
650 object_name(previous_object())), object_name(ret),
651 filename) );
652
653 return 0;
654 }
655 return ret;
656}
657
658// ############
659//############################ Shutdown #################################
660// ############
661
662// Spieler bei Shutdown entfernen
663protected void remove_player(object victim)
664{
bugfixd94d0932020-04-08 11:27:13 +0200665 catch(({int})victim->quit());
666 if (victim) catch(({int})victim->remove());
MG Mud User88f12472016-06-24 23:31:02 +0200667 if (victim) destruct(victim);
668 return;
669}
670
671// Langsamer Shutdown
672protected void slow_shut_down(int minutes)
673{
674 //sollte nur vom GD gerufen werden. Oder allenfalls Master selbst
675 filter(users(),#'tell_object,
676 "Der Gamedriver ruft: Der Speicher wird knapp ! Bereitet euch auf das Ende vor !\n");
bugfixd94d0932020-04-08 11:27:13 +0200677 ({int})"/obj/shut"->shut(minutes);
MG Mud User88f12472016-06-24 23:31:02 +0200678 return;
679}
680
681
682// In LD varargs void notify_shutdown(string crash_reason)
683protected varargs void notify_shutdown (string crash_reason) {
684
685 if (PO && PO != TO)
686 return;
687 if (crash_reason) {
688 //Uhoh... Verdammter Crash. :-( Zumindest mal mitloggen,
689 //was der Driver sagt...
690 write_file(CRASH_LOG,sprintf(
691 "\n%s: The driver crashed! Reason: %s\n",
692 ctime(time()),crash_reason));
693 }
694
695 filter(users(), #'tell_object,
696 "Game driver shouts: LDmud shutting down immediately.\n");
697 save_wiz_file();
698 return;
699}
700
701// ##################
702//########################## Berechtigungen #############################
703// ##################
704
705// Darf Verbindung durch name von obfrom nach ob gelegt werden?
706
707//int valid_exec(string name) {return 1;}
708
709int valid_exec(string name, object ob, object obfrom)
710{
711 // Ungueltige Parameter oder Aufruf durch process_string -> Abbruch
712 if (!objectp(ob) || !objectp(obfrom)
713 || !stringp(name) || !sizeof(name)
714 || funcall(symbol_function('process_call)) )
715 return 0;
716
717 // renew_player_object() darf ...
Zesstrae51f0602019-12-17 22:43:37 +0100718 if (name=="secure/master.c" || name=="/secure/master.c")
MG Mud User88f12472016-06-24 23:31:02 +0200719 return 1;
720
721 // Ansonsten darf sich nur die Shell selber aendern ...
722 if (previous_object() != obfrom) return 0;
723
724 // Die Login-Shell zu jedem Objekt ...
725 if (name=="/secure/login.c"
726 || name=="secure/login.c")
727 return 1;
728
729 // Magier per exec nur, wenn sie damit keine Fremde uid/euid bekommen
730 if (this_interactive() == obfrom && getuid(obfrom) == getuid(ob)
731 && geteuid(obfrom) == geteuid(ob))
732 return 1;
733
734 // Sonst darf niemand was
735 return 0;
736}
737
738
739// Darf me you snoopen?
740int valid_snoop(object me, object you) {
741 return getuid(PO) == ROOTID;
742}
743
744// Darf wiz wissen, ob er gesnoopt wird?
745int valid_query_snoop(object wiz) {
746 return getuid(PO) == ROOTID;
747}
748
749// Darf ob seine EUID auf neweuid setzen?
750int valid_seteuid(object ob, string neweuid)
751{
752 return (ob==this_object() ||
753 getuid(ob) == ROOTID ||
754 getuid(ob) == neweuid ||
755 creator_file(object_name(ob)) == neweuid);
756}
757
758// Darf getraced werden?
759int valid_trace(string what, mixed arg) {
760 return IS_ARCH(TI);
761}
762
763
764// valid_write() und
765// valid_read() befinden sich in file_access.c
766
767
768// Darf PO ob shadowen?
769int query_allow_shadow(object ob)
770{
771 // ROOT darf nicht geshadowed werden
772 if(getuid(ob) == ROOTID)
773 return 0;
774
775 // Access-Rights auch nicht
776 if (efun::explode(object_name(ob),"#")[0][<14..]=="/access_rights")
777 return 0;
778
779 // Ansonsten query_prevent_shadow fragen ...
Zesstrad872d182019-11-28 20:13:02 +0100780 return !({int})ob->query_prevent_shadow(PO);
MG Mud User88f12472016-06-24 23:31:02 +0200781}
782
783
784/* privilege_violation is called when objects try to do illegal things,
785 * or files being compiled request a privileged efun.
786 *
787 * return values:
788 * 1: The caller/file is allowed to use the privilege.
789 * 0: The caller was probably misleaded; try to fix the error.
790 * -1: A real privilege violation. Handle it as error.
791 */
Zesstraac4e6a82020-01-16 22:59:28 +0100792int privilege_violation(string op, mixed who, mixed arg1, mixed arg2,
793 mixed arg3)
MG Mud User88f12472016-06-24 23:31:02 +0200794{
795
Zesstraddddbf72021-05-14 16:52:16 +0200796 if (objectp(who) &&
MG Mud User88f12472016-06-24 23:31:02 +0200797 (who==this_object() || geteuid(who)==ROOTID))
Zesstraddddbf72021-05-14 16:52:16 +0200798 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200799
800 switch(op)
801 {
802 case "call_out_info":
803 return -1;
804 case "send_udp":
805 return 1;
806
807 case "nomask simul_efun":
808 // <who> ist in diesem Fall ein string (Filename) und damit von dem
809 // Check da oben nicht abgedeckt. Daher explizite Behandlung hier.
810 // Ausserdem hat der Pfad (zur Zeit noch) keinen fuehrenden '/'.
811 // Falls das jemand einschraenken will: der Kram fuer die simul_efuns
812 // muss das duerfen!
813 if (stringp(who)
814 && strstr(who,"secure/") == 0)
815 return 1;
816 return 0; // alle andere nicht.
817
818 case "get_extra_wizinfo":
819 // benutzt von /secure/memory.c und /secure/simul_efun.c
820 case "set_extra_wizinfo":
821 // wird benutzt von simul_efun.c, welche aber als ROOT-Objekt implizit
822 // erlaubt ist (s.o.)
823 return -1; // fuer allen nicht erlaubt.
824
825 case "rename_object":
826 if (object_name(who)=="/secure/impfetch" ||
827 BLUE_NAME(who)=="/secure/login")
828 return 1;
829 return(-1);
830
831 case "configure_driver":
832 return call_sefun("secure_level") >= ARCH_LVL;
833
834 case "limited":
835 // Spielershells duerfen sich zusaetzliche Ticks fuer den Aufruf von
836 // ::die() beschaffen, damit der Tod nicht wegen wenig Ticks buggt.
837 if (strstr(load_name(who), "/std/shells/") == 0
838 && get_type_info(arg1, 2) == who
839 && get_type_info(arg1, 3) == "/std/living/life"
MG Mud User88f12472016-06-24 23:31:02 +0200840 && arg2[LIMIT_EVAL] <= 10000000 ) {
841 return 1;
842 }
843 //DEBUG(sprintf("%O, %O, %O", who, arg1, arg2));
844 int *limits=efun::driver_info(DI_CURRENT_RUNTIME_LIMITS);
845 // LIMIT_EVAL darf verringert werden. Alle anderen Limits duerfen nicht
846 // geaendert werden. Achja, LIMIT_EVAL darf nicht 0 (LIMIT_UNLIMITED)
847 // sein. *g*
848 // LIMIT_COST darf entweder 0 oder -100 sein.
849 if (arg2[LIMIT_EVAL]>1000 && (arg2[LIMIT_EVAL] < get_eval_cost())-500
850 && arg2[LIMIT_ARRAY] == limits[LIMIT_ARRAY]
851 && arg2[LIMIT_MAPPING_KEYS] == limits[LIMIT_MAPPING_KEYS]
852 && arg2[LIMIT_MAPPING_SIZE] == limits[LIMIT_MAPPING_SIZE]
853 && arg2[LIMIT_BYTE] == limits[LIMIT_BYTE]
854 && arg2[LIMIT_FILE] == limits[LIMIT_FILE]
855 && arg2[LIMIT_CALLOUTS] == limits[LIMIT_CALLOUTS]
856 && (arg2[LIMIT_COST] == 0 || arg2[LIMIT_COST] == -100) )
857 return(1);
858 //sonst verweigern.
859 return(-1);
860
861 case "sqlite_pragma":
862 return 1;
Zesstraddddbf72021-05-14 16:52:16 +0200863
864 case "configure_lwobject":
865 // arg1: lwo to be configured, arg2: <what>, arg3: <data>
866 if (arg2 == LC_EUID) {
867 return who == arg1 // only the lwo itself for now (except of ROOT)
868 && getuid(arg1) == arg3; // and only to its own UID
869 }
870 return -1;
MG Mud User88f12472016-06-24 23:31:02 +0200871 case "attach_erq_demon":
872 case "bind_lambda":
873 case "configure_interactive":
874 case "configure_object":
875 case "execute_command":
876 case "erq":
877 case "input_to":
878 case "mysql":
879 case "net_connect":
880 case "pgsql":
881 case "set_driver_hook":
882 case "set_this_object":
883 case "shadow_add_action":
884 case "symbol_variable":
885 case "variable_list":
886 case "wizlist_info":
887 default:
888 return(-1);
889 }
890 return -1;
891}
892
893// ####################
894//######################## Fehlerbehandlung #############################
895// ####################
896
897// Behandlung von Fehler im Heart_Beat
898protected int heart_beat_error( object culprit, string error, string program,
899 string current_object, int line, int caught)
900{
901 if (!objectp(culprit)) return 0;
902 if (interactive(culprit))
903 {
904 tell_object(culprit,"Der GameDriver teilt Dir mit: "
905 "Dein Herzschlag hat ausgesetzt!\n");
906 if (IS_LEARNER(culprit))
907 tell_object(culprit,
908 sprintf("Fehler: %sProgamm: %s, CurrObj: %s, Zeile: %d, "
909 "the error was %scaught at higher level.\n",
910 error,program,current_object,line,
911 caught ? "" : "not"));
912 }
913
914 if (efun::object_info(culprit, OI_ONCE_INTERACTIVE))
915 call_out("restart_heart_beat", 5, culprit);
916 else
bugfixd94d0932020-04-08 11:27:13 +0200917 catch(({void})culprit->make_immortal(); publish);
MG Mud User88f12472016-06-24 23:31:02 +0200918 return 0;
919}
920
921// Ausgabe einer Meldung an Spieler mit Level >= minlevel. Wird genutzt, um
922// Magier ueber Fehler zu informieren, die nicht normal behandelt werden
923// (z.B. rekursive Fehler, d.h. Fehler in der Fehlerbehandlung)
924private void tell_players(string msg, int minlevel) {
925 msg = efun::sprintf("%=-78s","Master: " + msg); // umbrechen
926 efun::filter(efun::users(), function int (object pl)
927 {
928 if (query_wiz_level(pl) >= minlevel)
929 efun::tell_object(pl, msg);
930 return 0;
931 } );
932}
933
934/**
935 * \brief Error handling fuer Fehler beim Compilieren.
936 *
937 * log_error() wird vom GameDriver aufgerufen, wenn zur Compile-Zeit ein
938 * Fehler auftrat. Die Fehlermeldung wird unter /log/error geloggt.
939 * Falls this_interactive() ein Magier ist, bekommt er die Fehlermeldung
940 * direkt angezeigt.
941 * Sollte das Logfile 50kB ueberschreiten, wird es rotiert. Auf [Entwicklung]
942 * wird dann eine Fehlermeldung abgesetzt.
943 *
944 * @param file Die Datei, in der der Fehler auftrat.
945 * @param message Die Fehlermeldung.
946 * @param warn Warnung (warn!=0) oder Fehler (warn==0)?
947 * */
948
949protected void log_error(string file, string message, int warn) {
950 string lfile;
951 string cr;
952 mixed *lfile_size;
953
Zesstrad6121362021-05-13 13:40:33 +0200954 if (handling_error == efun::driver_info(DI_EVAL_NUMBER))
955 {
MG Mud User88f12472016-06-24 23:31:02 +0200956 // Fehler im Verlauf einer Fehlerbehandlung: Fehlerbehandlung minimieren,
957 // nur Meldung an eingeloggte Erzmagier.
958 tell_players("log_error(): Rekursiver Fehler in Fehlerbehandlung. "
959 "Bitte Debuglog beachten. Aktueller Fehler in " + file + ": "
960 + message, ARCH_LVL);
961 return;
962 }
Zesstrad6121362021-05-13 13:40:33 +0200963 handling_error = efun::driver_info(DI_EVAL_NUMBER);
MG Mud User88f12472016-06-24 23:31:02 +0200964
965 //Fehlerdaten an den Errord zur Speicherung weitergeben, falls wir sowas
966 //haben.
967#ifdef ERRORD
968 // Only call the errord if we are _not_ compiling the sefuns. It uses sefuns
969 // and it will cause a recursing call to get_simul_efuns() which is bound to
970 // fail.
971 if (!loading_simul_efuns) {
972 catch(limited(#'call_other,({200000}),ERRORD,"LogCompileProblem",
973 file,message,warn);publish );
974 }
975#endif // ERRORD
976
977 // Logfile bestimmen
978 cr=creator_file(file);
979 if (!cr) lfile="NOBODY.err";
980 else if (cr==ROOTID) lfile="ROOT";
981 else if (efun::member(cr,' ')!=-1) lfile="STD";
982 else lfile=cr;
983 //je nach Warnung oder Fehler Verzeichnis und Suffix bestimmen
984 if (warn) {
985 lfile="/log/warning/" + lfile + ".warn";
986 }
987 else {
988 lfile="/log/error/" + lfile + ".err";
989 }
990
991 // Bei Bedarf Rotieren des Logfiles
992 if ( !loading_simul_efuns
993 && sizeof(lfile_size = get_dir(lfile,2))
994 && lfile_size[0] >= MAX_ERRLOG_SIZE )
995 {
996 catch(rename(lfile, lfile + ".old"); publish); /* No panic if failure */
997 if (!loading_simul_efuns)
998 {
999 catch(send_channel_msg("Entwicklung","<MasteR>",
1000 "Logfile rotiert: "+lfile+"."));
1001 }
1002 }
1003
1004 efun::write_file(lfile,message);
1005
1006 // Magier bekommen die Fehlermeldung angezeigt
1007 if (IS_LEARNER(TI)) efun::tell_object(TI, message);
1008
1009 handling_error = 0;
1010}
1011
1012/* Gegenmassnahme gegen 'too long eval' im Handler vom runtime error:
1013 Aufsplitten des Handlers und Nutzung von limited() */
1014//keine GD-Funktion
1015private void handle_runtime_error(string err, string prg, string curobj,
Zesstraddddbf72021-05-14 16:52:16 +02001016 int line, mixed culprit, int caught, object|lwobject po, int issueid)
MG Mud User88f12472016-06-24 23:31:02 +02001017{
1018 string code;
1019 string debug_txt;
1020 object ob, titp;
1021
1022 //DEBUG(sprintf("Callerstack: (handle_runtime_error()): %O\n",
1023 // caller_stack(1)));
1024 // Fehlermeldung bauen
1025 if (!stringp(err)) err="<NULL>";
1026 if (!stringp(prg)) prg="<NULL>";
1027 if (!stringp(curobj)) curobj="<NULL>";
1028 debug_txt=efun::sprintf("Fehler: %O, Objekt: %s, Programm: %O, Zeile %O (%s), "
1029 "ID: %d",
1030 err[0..<2], curobj, (prg[0]!='<'?"/":"")+prg, line,
1031 (TI?efun::capitalize(efun::getuid(TI)):"<Unbekannt>"),
1032 issueid);
1033
1034 titp = TI || TP;
1035 // Fehlermeldung an Kanaele schicken, aber nur wenn der aktuelle Fehler
1036 // nicht waehrend des ladens der simulefuns auftrat, bei der Ausgabe der
1037 // Meldung ueber die Kaenaele wieder sefuns genutzt werden.
1038 if (!loading_simul_efuns) {
bugfixd94d0932020-04-08 11:27:13 +02001039 if (titp && (IS_LEARNER(titp) || (({int|string})titp->QueryProp(P_TESTPLAYER))))
MG Mud User88f12472016-06-24 23:31:02 +02001040 {
1041 catch(send_channel_msg("Entwicklung",
1042 capitalize(objectp(po) ? REAL_UID(po) : ""),
1043 debug_txt));
1044 }
1045 else
1046 {
1047 catch(send_channel_msg("Debug",
1048 capitalize(objectp(po) ? REAL_UID(po) : ""),
1049 debug_txt));
1050 }
1051 }
1052
1053 if (!titp) return;
1054
1055 // Fehlermeldung an Benutzer
1056 if (IS_LEARNER(titp))
1057 efun::tell_object(titp,
1058 efun::sprintf("%'-'78.78s\nfile: %s line: %d object: %s\n" +
1059 "%serror: %s%'-'78.78s\n","",prg,line,curobj,
1060 (prg&&(code=efun::read_file("/"+prg,line,1))?
1061 "\n"+code+"\n":""),err,""));
1062 else
1063 efun::tell_object(titp, "Du siehst einen Fehler im Raum-Zeit-Gefuege.\n");
1064}
1065
1066//Keine GD-Funktion, limitiert die Kosten fuer den handler
1067private void call_runtime_error(string err, string prg, string curobj,
Zesstraddddbf72021-05-14 16:52:16 +02001068 int line, mixed culprit, int caught, object|lwobject po)
MG Mud User88f12472016-06-24 23:31:02 +02001069{
Zesstrad6121362021-05-13 13:40:33 +02001070 if (handling_error == efun::driver_info(DI_EVAL_NUMBER))
MG Mud User88f12472016-06-24 23:31:02 +02001071 {
1072 // Fehler im Verlauf einer Fehlerbehandlung: Fehlerbehandlung minimieren,
1073 // nur Meldung an eingeloggte Regionsmagier.
1074 tell_players("call_runtime_error(): Rekursiver Fehler in "
1075 "Fehlerbehandlung. Bitte Debuglog beachten. Aktueller Fehler in "
1076 + curobj + ": " + err, LORD_LVL);
1077 return;
1078 }
Zesstrad6121362021-05-13 13:40:33 +02001079 handling_error = efun::driver_info(DI_EVAL_NUMBER);
MG Mud User88f12472016-06-24 23:31:02 +02001080
1081 //Fehlerdaten an den Errord zur Speicherung weitergeben, falls wir sowas
1082 //haben.
MG Mud User88f12472016-06-24 23:31:02 +02001083 int issueid;
Christian Georg Beckerd66c9602017-01-09 10:37:51 +02001084#ifdef ERRORD
MG Mud User88f12472016-06-24 23:31:02 +02001085 // Wenn die sefuns gerade geladen werden, erfolgt keine Weitergabe an den
1086 // ErrorD, da dabei wieder sefuns gerufen werden, was zu einer Rekursion
1087 // fuehrt.
1088 if (!loading_simul_efuns) {
1089 catch(issueid=efun::limited(#'call_other,({200000}),ERRORD,"LogError",
1090 err,prg,curobj,line,culprit,caught);publish);
1091 }
1092#endif // ERRORD
1093
1094 //eigenen Errorhandler laufzeitbegrenzt rufen
1095 efun::limited(#'handle_runtime_error, ({ 200000 }), err, prg, curobj,
1096 line,culprit,caught, po, issueid);
1097
1098 handling_error = 0;
1099}
1100
1101// Laufzeitfehlerbehandlung, hebt Evalcost-Beschraenkung auf und reicht weiter
1102// an call_runtime_error, die die Grenze wieder auf einen bestimmten Wert
1103// festlegt.
1104protected void runtime_error(string err ,string prg, string curobj, int line,
1105 mixed culprit, int caught) {
1106
1107 //DEBUG(sprintf("Callerstack: (runtime_error()): %O\nPO: %O\nPO(0): %O\n",
1108 // caller_stack(1),previous_object(),previous_object(0)));
1109
1110 limited(#'call_runtime_error, ({ LIMIT_UNLIMITED }),
1111 err,prg,curobj,line,culprit,caught,previous_object());
1112}
1113
1114//Warnungen mitloggen
1115protected void runtime_warning( string msg, string curobj, string prog, int line,
1116 int inside_catch)
1117{
1118 string code;
1119 string debug_txt;
1120 object titp;
1121
1122 //DEBUG(sprintf("Callerstack: in runtime_warning(): %O\nPO(0): %O\n",
1123 // caller_stack(1),previous_object(0)));
1124
1125 //Daten der Warnung an den Errord zur Speicherung weitergeben, falls wir
1126 //sowas haben.
1127 int issueid;
1128#ifdef ERRORD
1129 catch(issueid=limited(#'call_other,({200000}),ERRORD,"LogWarning",
1130 msg,prog,curobj,line,inside_catch); publish);
1131#endif // ERRORD
1132
1133 // Fehlermeldung bauen
1134 if (!stringp(msg)) msg="<NULL>";
1135 if (!stringp(prog)) prog="<NULL>";
1136 if (!stringp(curobj)) curobj="<NULL>";
1137 debug_txt=sprintf("Warnung: %O, Objekt: %s, Programm: %O, Zeile %O (%s) "
1138 "ID: %d",
1139 msg[0..<2], curobj, (prog[0]!='<'?"/":"")+prog, line,
1140 (TI?capitalize(getuid(TI)):"<Unbekannt>"),
1141 issueid);
1142
1143 //Fehlermeldungen an -warnungen schicken
1144 catch(send_channel_msg("Warnungen",
1145 capitalize(objectp(previous_object()) ?
1146 REAL_UID(previous_object()) : ""),
1147 debug_txt));
1148
1149 titp = TI || TP;
1150
1151 if (!titp) return;
1152
1153 // Fehlermeldung an Benutzer
1154 if (IS_LEARNER(titp))
1155 tell_object(titp,
1156 sprintf("%'-'78.78s\nfile: %s line: %d object: %s\n" +
1157 "%sWarnung: %s%'-'78.78s\n","",prog,line,curobj,
1158 (prog&&(code=read_file("/"+prog,line,1))?
1159 "\n"+code+"\n":""),msg,""));
1160 return;
1161}
1162
1163
1164// #####################
1165//######################## Einrichten des ED ############################
1166// #####################
1167
1168// Setup speichern
1169protected int save_ed_setup(object who, int code)
1170{
1171 string file;
1172
1173 if (!intp(code)) return 0;
1174 file = sprintf("/players/%s/.edrc",geteuid(who));
1175 rm(file);
1176 return write_file(file,(string)code);
1177}
1178
1179// Setup einladen
1180protected int retrieve_ed_setup(object who)
1181{
1182 string file;
1183
1184 file = sprintf("/players/%s/.edrc",getuid(who));
1185 if (file_size(file)<1) return 0;
1186 return (int)read_file(file);
1187}
1188
1189// Wo werden Dateien gespeichert?
1190string get_ed_buffer_save_file_name(string file)
1191{
1192 return sprintf("/players/%s/.dead_ed_files/%s",
1193 getuid(this_player()),efun::explode(file, "/")[<1]);
1194}
1195
1196// ################################
1197//################### Ungenutzte Pflichtfunktionen ######################
1198// ################################
1199
1200// Nichts zu tun beim Master-Neustart
1201protected void external_master_reload() { return; }
1202
1203// Keine externen Master-Flags
1204protected void flag(string str) { return; }
1205
1206// Wird benoetigt, falls ERQ angeschlossen ist
1207protected void stale_erq(closure callback) { return; }
1208
1209// Zerstoerten Master wiederbeleben ...
1210// nicht viel zu tun, wenn flag gesetzt ist. Wenn aber nicht, sind alle
1211// Variablen auf 0. Nach dieser Funktion wird wieder inaugurate_master()
1212// gerufen.
1213protected void reactivate_destructed_master(int flag) {
1214 if (flag) {
1215 //re-init
1216 //was machen? TODO
1217 }
1218 return;
1219}
1220
1221// Kein Quota-Demon (potentielles TODO)
1222//Handle quotas in times of memory shortage.
1223//is called during the final phase of a garbage collection, if the user
1224//reserve could not be re-allocated. Last (!) Chance to free (active) objects
1225//from the system and prevent call to slow_shut_down()!
1226protected void quota_demon() {
1227 //was kann man machen?
1228 //uebervolle Seherhaeuser leeren?
1229 return;
1230}
1231
MG Mud User88f12472016-06-24 23:31:02 +02001232// Keine Besonderen Objektnamen
1233string printf_obj_name(object ob) { return 0; }
1234
1235// ###################
1236//######################### Sonstiges/Hooks #############################
1237// ###################
1238
1239//TODO: save_wiz_file in shutdown() integrieren?
1240// Wizliste speichern: Zeile generieren
1241static string _save_wiz_file_loop(mixed *a)
1242{
1243 return sprintf("%s %d %d\n",a[WL_NAME],a[WL_COMMANDS],a[WL_EXTRA]);
1244}
1245
1246// Wizliste speichern
1247protected void save_wiz_file()
1248{
1249 rm("/WIZLIST");
1250 write_file("/WIZLIST",implode(
1251 map(wizlist_info(),#'_save_wiz_file_loop),""));
1252}
1253