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