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