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