blob: a5d30b2687eef0e13eaa1910794358cbf610984f [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// $Id: magier_ext.c 9555 2016-05-03 20:42:46Z Zesstra $
2#pragma strict_types
3#pragma save_types
4//#pragma range_check
5#pragma no_clone
6#pragma pedantic
7
8#include <wizlevels.h>
9#include <logging.h>
10#include <magier.h>
11#include <snooping.h>
12#include <driver_info.h>
13#define NEED_PROTOTYPES
14#include <player/telnetneg.h>
15#include <player/base.h>
16#undef NEED_PROTOTYPES
17#include <properties.h>
18#include <files.h>
19#include <events.h>
20#include <player/comm.h>
21
22inherit "/std/shells/magier/parsing";
23inherit "/std/shells/magier/upd";
24inherit "/std/shells/magier/fileview";
25inherit "/std/shells/magier/objects";
26inherit "/std/shells/magier/fileedit";
27//inherit "/std/shells/magier/todo";
28inherit "/std/shells/magier/players";
29inherit "/std/shells/magier/admin";
30inherit "/std/shells/magier/moving";
31inherit "/std/shells/magier/comm";
32
33
34// #######
35//############################### SET #################################
36// #######
37
38
39//
40// _set(): Shell-Befehl 'set'
41// args: Kommandozeilenargumente
42//
43
44static int _set(mixed args)
45{
46 int pos;
47 string var;
48 mixed val;
49 mapping vars;
50
51 if(!args=_unparsed_args())
52 {
53 if(!sizeof(vars=QueryProp(P_VARIABLES)))
54 printf("Du hast noch keine Variablen definiert!\n");
55 else
56 {
57 printf("Du hast die folgenden Variablen definiert:\n");
58 walk_mapping(vars,((: printf(" %-20s = %s\n",$1,
59 pointerp($2)?implode($2,":"):$2) :)));
60
61 }
62 return 1;
63 }
64 pos = member(args,' ');
65 if(pos == -1)
66 if(sizeof(args))
67 {
68 m_delete(QueryProp(P_VARIABLES), args);
69 printf("Variable %s wurde geloescht.\n",args);
70 return 1;
71 }
72 else return USAGE("set <variable> <wert>");
73 var = args[0..pos-1];
74 val = (member(args[pos+1..],':')>-1?
75 explode(args[pos+1..], ":") :
76 args[pos+1..]);
77 vars=QueryProp(P_VARIABLES);
78 vars+= ([var : val]);
79 printf("Variable gesetzt: %s = %s\n",var,args[pos+1..]);
80 return 1;
81}
82
83// ############
84//############################# CD + PWD ###################################
85// ############
86
87static int _pwd()
88{
89 printf("Aktuelles Verzeichnis: %s\n",QueryProp(P_CURRENTDIR));
90 return 1;
91}
92
93static int _cd2(string cmdline)
94{
95 string dest,tmp;
96 int flags;
97 mixed *args;
98
99 args=parseargs(cmdline,&flags,CD_OPTS,1);
100 if (flags==-1) return 0;
101 if(flags&CD_B)
102 {
103 dest=QueryProp(P_LASTDIR);
104 }
105 if (sizeof(args)>1)
106 return notify_fail("Man kann sich (leider) nur in einem "
107 "Verzeichnis gleichzeitig befinden.\n"),0;
108 if(!dest)
109 {
110 if (!sizeof(args))
111 {
112 if (IS_WIZARD(this_object()))
113 dest="/players/"+getuid(this_object());
114 else
115 dest="/doc";
116 }
117 else
118 {
119 dest=args[0];
120 }
121 }
122
123 if (dest!="/")
124 {
125 args=file_list(({dest}),MODE_CD,0,"/");
126 args = filter(args, function int (mixed arr)
127 { return arr[FILESIZE] == FSIZE_DIR; } );
128
129 if (!sizeof(args))
130 return notify_fail("cd: "+dest+
131 ": Kein solches Verzeichnis gefunden.\n"),0;
132 if (sizeof(args)>1)
133 return notify_fail("cd: "+dest+": Maske ist nicht eindeutig.\n"),0;
134 dest=args[0][FULLNAME];
135 }
136 if (!IS_WIZARD(this_object())&&dest[0..3]!="/doc") dest="/doc";
137 SetProp(P_LASTDIR,QueryProp(P_CURRENTDIR));
138 printf("Aktuelles Verzeichnis ist jetzt: %s\n",SetProp(P_CURRENTDIR,dest));
139 tmp="";
140 if (((flags&CD_L)||
141 ((!m_contains(&tmp,QueryProp(P_VARIABLES),"CD_SHORT")||
142 tmp!="1")&&(!(flags&CD_S)))))
143 tell_object(this_object(),
144 read_file(dest+(dest[<1]=='/'?".readme":"/.readme"))||"");
145 return 1;
146}
147
148static int _cd(string cmdline)
149{
150 return _cd2(_unparsed_args());
151}
152
153static string _set_currentdir(string path)
154{
155 Set(P_CURRENTDIR, path);
156 this_object()->modify_prompt(); // Prompt mit neuem Pfad setzen, telnetneg
157 return path;
158}
159
160private string _query_currentdir()
161{
162 string c;
163 if(!c=Query(P_CURRENTDIR))
164 return Set(P_CURRENTDIR, "/players/"+getuid(this_object()),F_VALUE);
165 return c;
166}
167
168// ##########
169//############################ PROMPT #################################
170// ##########
171
172//
173// _prompt_subst: Mudnamen, Usernamen, Zeilenvorschub in Eingabeauf-
174// forderung einbauen
175// str: Uebergebener Kommandozeilenabschnitt
176//
177
178private string _prompt_subst(string str)
179{
180 switch(str)
181 {
182 case "\\h": return sizeof(MUDNAME)?MUDNAME:"Mud ohne Namen";
183 case "\\u": return capitalize(getuid(this_object()));
184 case "\\n": return "\n";
185 case "\\t": return "\t";
186 case "\\w": return "\w";
187 }
188 return str;
189}
190
191
192//
193// _prompt: Eingabeaufforderung setzen
194// arg: Kommandozeile
195//
196
197static int _prompt(string args)
198{
199 string *pargs;
200
201 args=(extern_call()?_unparsed_args():args);
202 if (!sizeof(args)) args="> ";
203 if (args[0]=='"') args=args[1..<2]; //");
204 if(!sizeof(pargs = regexplode(args, "\\\\[thuwn]")))
205 return USAGE("prompt \"<Eingabeaufforderungsdefinition>\"");
206 pargs=map(pargs,#'_prompt_subst);
207
208 SetProp(P_PROMPT,implode(pargs,""));
209 return 1;
210}
211
212static string _set_prompt(string prompt) {
213 Set(P_PROMPT, prompt, F_VALUE);
214 this_object()->modify_prompt(); // neuen Prompt setzen (telnetneg.c)
215 return prompt;
216}
217
218
219// ##############
220//############################ SHOWPRESAY ###############################
221// ##############
222
223static int _showpresay(string cmdline)
224{
225 int presay;
226 presay=QueryProp(P_CAN_FLAGS)&CAN_PRESAY;
227 cmdline=_unparsed_args(0);
228 if (!sizeof(cmdline))
229 {
230 printf("Dein Presay wird im Moment %sangezeigt.\n"
231 "%sschalten mit \'showpresay %s\'.\n",
232 presay?"":"nicht ",presay?"Aus":"Ein",
233 presay?"aus":"ein");
234 return 1;
235 }
236 if (cmdline=="ein"||cmdline=="an")
237 {
238 printf("Dein Presay wird jetzt angezeigt.\n");
239 SetProp(P_CAN_FLAGS,QueryProp(P_CAN_FLAGS)|CAN_PRESAY);
240 return 1;
241 }
242 if (cmdline=="aus")
243 {
244 printf("Dein Presay wird jetzt nicht mehr angezeigt.\n");
245 SetProp(P_CAN_FLAGS,QueryProp(P_CAN_FLAGS)&~CAN_PRESAY);
246 return 1;
247 }
248 return USAGE("showpresay [ein|an|aus]");
249}
250
251// ########
252//############################### EXEC ###############################
253// ########
254
255static int _exec(string filename)
256{
257 object ob;
258 if (!IS_LORD(this_object())) return 0;
259 if (this_player()!=this_interactive()) return 0;
260 if (this_player()!=this_object()) return 0;
261 if (!(filename=_unparsed_args())) return USAGE("exec <objektname>");
262 filename=(string)"secure/master"->_get_path(filename,getuid());
263 if (file_size(filename)<0&&(!to_filename(filename+".c"))||
264 file_size(to_filename(filename+".c"))<0)
265 {
266 printf("exec: %s: Datei nicht vorhanden oder ein Verzeichnis.\n",filename);
267 return 1;
268 }
269 if (catch(call_other(filename,"????")))
270 {
271 printf("exec: Fehler beim Laden von %s.\n",filename);
272 return 1;
273 }
274 if (!(ob=clone_object(filename))) return 0;
275 if (getuid(ob) != getuid(this_object()))
276 {
277 printf("exec: UID-Konflikt: %s <-> %s.\n",getuid(ob),
278 getuid(this_object()));
279 destruct(ob);
280 return 1;
281 }
282 log_file(SHELLLOG("EXEC"),
283 sprintf("%12.12s %40.40s %25.25s\n",
284 capitalize(getuid(this_object())),filename,dtime(time())[4..]));
285 disable_commands();
286 exec(ob,this_object());
287 if (interactive(this_object())||!interactive(ob))
288 {
289 enable_commands();
290 printf("Fehler bei EXEC: Uebertragung der Shell "
291 "nicht moeglich.\n");
292 return 1;
293 }
294 ob->start_player(capitalize(getuid(this_object())));
295 remove();
296 return 1;
297}
298// ############
299//############################# SNOOPING ###############################
300// ############
301
302private nosave string snoop_allowed;
303private nosave object snoopee;
304
305nomask int QueryAllowSnoop(object who)
306{
307 return (getuid(who) == snoop_allowed);
308}
309
310static int _sallow(string str)
311{
312 object ob;
313
314 if (!sizeof(str))
315 {
316 if (!snoop_allowed) return USAGE("sallow [<name>]\n");
317 str=snoop_allowed;
318 snoop_allowed=0;
319 printf("Du entziehst %s die Erlaubnis zum Snoopen.\n",capitalize(str));
320 ob=query_snoop(this_player());
321 if (!ob||(getuid(ob)!=str)) return 1;
322 tell_object(ob,break_string(sprintf("%s entzieht Dir die "
323 "Erlaubnis zum snoopen und zwingt Dich so dazu, mit "
324 "dem Snoopen aufzuhoeren.\n",capitalize(getuid()))));
325 snoop(ob);
326 return 1;
327 }
328 if (snoop_allowed) _sallow(""); // Erstmal abschalten
329 ob=find_player(lower_case(str));
330 str=capitalize(str);
331 if (!ob) return
332 printf("sallow: Spieler %s konnte nicht gefunden werden.\n",str),1;
333 if (query_wiz_grp(ob)>query_wiz_grp(this_player()))
334 return printf("sallow: %s hat einen hoeheren Rang als Du und kann "
335 "Dich daher ohnehin snoopen.\n",str),1;
336 snoop_allowed=getuid(ob);
337 return printf("sallow: Du erlaubst %s, Dich zu snoopen.\n",str),1;
338}
339
340static int _snoop(string cmdline)
341{
342 object ob;
343 int flags;
344 string *args;
345
346 if (!sizeof(cmdline=_unparsed_args())||
347 sizeof(args=parseargs(cmdline,&flags,SNOOP_OPTS,0))!=1||flags==-1)
348 {
349 if (!snoop(this_object())) return USAGE("snoop [-" SNOOP_OPTS
350 "] [<spieler>]\n");
351 if (snoopee)
352 printf("Du snoopst %s jetzt nicht mehr.\n",capitalize(getuid(snoopee)));
353 else
354 {
355 printf("Du hoerst auf zu snoopen.\n");
356 // evtl. irgendetwas loggen ... sollte eigentlich nicht passieren.
357 }
358 snoopee=(object)0;
359 return 1;
360 }
361 SetProp(P_SNOOPFLAGS,flags); // FUNKTIONIERT NUR, WENN magier.h und
362 // snooping.h abgeglichen sind
363 if (!(ob = find_player(args[0])))
364 return printf("snoop: Konnte keinen Spieler '%s' finden.\n",
365 capitalize(args[0])),1;
366 if (!snoop(this_player(),ob))
367 return printf("snoop: Der Versuch, %s zu snoopen, ist "
368 "fehlgeschlagen.\n%s",capitalize(args[0]),
369 ((~flags)&SNOOP_F)?"Eventuell funktioniert es mit dem "
370 "Flag '-f'.\n":""),1;
371 snoopee=ob;
372 return printf("Du snoopst jetzt %s.\n",capitalize(getuid(ob))),1;
373}
374
375
376// ##########
377//############################ MSCHAU #################################
378// ##########
379
380static int _mschau(string str)
381{
382 if (this_interactive()!=this_object()) return 0;
383 if (str=="ja"||str=="an"||str=="ein")
384 {
385 if ( QueryProp(P_WANTS_TO_LEARN) )
386 printf("Du hast den Magier-Modus doch schon eingeschaltet!\n");
387 else
388 {
389 printf("Du hast jetzt den Magier-Modus eingeschaltet.\n" );
390 SetProp(P_WANTS_TO_LEARN, 1);
391 }
392 return 1;
393 }
394 if (str=="nein"||str=="aus")
395 {
396 if (QueryProp(P_WANTS_TO_LEARN))
397 {
398 printf( "Du schaltest den Magier-Modus aus.\n");
399 set_heart_beat(1);
400 SetProp(P_WANTS_TO_LEARN,0);
401 }
402 else
403 printf("Du hast den Magier-Modus doch schon ausgeschaltet.\n");
404 return 1;
405 }
406 if (str=="+debug")
407 {
408 printf("Du nimmst jetzt Debugausgaben wahr.\n");
409 SetProp(P_WIZ_DEBUG,1);
410 return 1;
411 }
412 if (str=="-debug")
413 {
414 printf("Du nimmst jetzt keine Debugausgaben mehr wahr.\n");
415 SetProp(P_WIZ_DEBUG,0);
416 return 1;
417 }
418 return USAGE("mschau [an|ein|ja|aus|nein|+debug|-debug]\n");
419}
420
421// ###########
422//############################ PROTECT ################################
423// ###########
424
425static int _protect(string str)
426{
427
428 if (this_object()!=this_interactive()) return 0;
429 if (!sizeof(str))
430 return USAGE("protect <propertyname>\n");
431 Set(str, PROTECTED, F_MODE);
432 return printf("Deine Property %s ist jetzt %sgeschuetzt.\n",
433 str,(Query(str,F_MODE) & PROTECTED?"":"nicht mehr ")),1;
434}
435
436
437// ###############
438//########################## VIS + INVIS ##############################
439// ###############
440
441static int _hbstop;
442static int _age;
443
444static int _invis(string inform)
445{
446
447 if (QueryProp(P_INVIS))
448 return printf("Du bist doch schon unsichtbar!\n"),1;
449 tell_room(environment(),sprintf("%s %s.\n",capitalize(Name()),
450 QueryProp(P_MMSGOUT)),({ this_object() }));
451 if (inform=="e") {
452 // Logout-event ausloesen
453 EVENTD->TriggerEvent(EVT_LIB_LOGOUT, ([
454 E_OBJECT: this_object(),
455 E_PLNAME: getuid(this_object()),
456 E_ENVIRONMENT: environment() ]) );
457
458 call_notify_player_change(0);
459 }
460
461 SetProp(P_INVIS, QueryProp(P_AGE));
462 printf("Du bist jetzt unsichtbar.\n");
463 return 1;
464}
465
466static int _vis(string inform)
467{
468 if (!QueryProp(P_INVIS))
469 return printf("Du bist doch schon sichtbar.\n"),1;
470 tell_room(environment(),sprintf("%s %s.\n",capitalize(Name()),
471 QueryProp(P_MMSGIN)),({ this_object() }));
472 SetProp(P_INVIS, 0);
473 if (inform=="e") {
474 // Login-event ausloesen
475 EVENTD->TriggerEvent(EVT_LIB_LOGIN, ([
476 E_OBJECT: this_object(),
477 E_PLNAME: getuid(this_object()),
478 E_ENVIRONMENT: environment() ]) );
479
480 call_notify_player_change(1);
481 }
482 printf("Du bist jetzt sichtbar.\n");
483 return 1;
484}
485
486// ############
487//########################### LOCALCMD ###############################
488// ############
489
490
491static int _localcmd()
492{
493 int size,more;
494 string *verbs,result;
495
496 // Per Umweg ueber Mapping doppelte Werte einstampfen
497 size=sizeof(verbs=m_indices(mkmapping(query_actions(this_object()))));
498 verbs-=({""});
499 more=(size>sizeof(verbs));
500 if (!sizeof(verbs))
501 {
502 if (more)
503 printf("Die vorhandenen Befehle koennen nicht angezeigt werden, "
504 "da sie per 'add_action(\"funktion\",\"\",1)' definiert "
505 "wurden.\n");
506 else
507 printf("Dir stehen keine Befehle zur Verfuegung ... eigenartig!\n");
508 return 1;
509 }
510 verbs=sort_array(verbs,#'>);
511 result=break_string(sprintf("\'%s\'",implode(verbs,"' '")),78);
512 return printf("\n%'-'78.78s\nDie fuer Dich aktuell verfuegbaren "
513 "Befehle sind:\n\n%s\n%s%'-'78.78s\n","",result,
514 more?"Zudem wurden Befehle per 'add_action("
515 "\"funktion\",\"\",1)' definiert.\n":"",""),1;
516}
517
518// ###########
519//############################ TRAENKE ################################
520// ###########
521
522static int _traenke(string str)
523{
524 if(SetProp(P_TRANK_FINDEN, !QueryProp(P_TRANK_FINDEN)))
525 write("Du kannst jetzt Zaubertraenke finden.\n");
526 else
527 write("Du findest jetzt keine Zaubertraenke mehr.\n");
528 return 1;
529}
530
531static int norm_rusage() {
532 mixed* r;
533 r = rusage();
534 return r[0]/100 + r[1]/100;
535}
536
537// #############
538//############################ ASYNCHRON #################################
539// #############
540
541//
542// asynchron(): Asynchrone Abarbeitung eines Arrays
543// array: Zu bearbeitendes Array
544// cmd: Auszufuehrende Closure
545// data: Extraargumente
546// flags: Zusatzdaten (normalerweise Flags)
547// c: schon asynchron?
548//
549
550static varargs void asynchron(mixed* array, closure cmd, mixed data, mixed flags,int c)
551{
552 int i, j, k;
553 mixed ret_val;
554 string cmd_string;
555
556 k = norm_rusage()+5;
557 j = sizeof(array);
558 i=0;
559
560 switch (cmd_string=explode(sprintf("%O",cmd),"->")[1])
561 {
562 case "_make": cmd_string=(data&UPD_LOAD?"load":"upd");break;
563 case "cp_file": cmd_string =(data?"mv":"cp"); break;
564 case "grep_file": cmd_string = "grep"; break;
565 case "rm_file": cmd_string = "rm"; break;
566 default: break;
567 }
568
569 while(i < j && get_eval_cost() > 200000 && norm_rusage()<k)
570 // Sowohl Too-Long-Eval als auch Lag verhindern
571 {
572 ret_val=apply(cmd,array[i],data, flags);
573 if (closurep(ret_val))
574 {
575 if(c) tell_object(this_object(),
576 sprintf("%s: Verlasse Asynchronen Modus.\n",cmd_string));
577 funcall(ret_val,array[i..],data,flags);
578 return;
579 }
580 if (ret_val==RET_DELETE)
581 {
582 array[i+array[i][SUBDIRSIZE]+1..i+array[i][SUBDIRSIZE]]=
583 ({ (array[i][0..5]+({0})) });
584 }
585 if (ret_val==RET_JUMP) i+=array[i][SUBDIRSIZE];
586 i++;
587 }
588 if(sizeof(array = array[i..]))
589 {
590 if(!c) tell_object(this_object(),
591 sprintf("%s: Asynchroner Modus aktiviert!\n", cmd_string));
592 call_out(#'asynchron, 1, array, cmd, data,flags, 1);
593 }
594 else
595 {
596 if(c) tell_object(this_object(),
597 sprintf("%s: abgeschlossen.\n",cmd_string));
598 else if (query_verb()) tell_object(this_object(),
599 sprintf("%s: abgeschlossen.\n",query_verb()));
600 }
601 return;
602}
603
604//
605// ######################## Driver Status Infos ##########################
606//
607static int _driver_malloc(string str)
608{
609 if(!sizeof(str))
610 {
611 write(efun::driver_info(DI_STATUS_TEXT_MALLOC));
612 return 1;
613 }
614 if(str == "extstats")
615 {
616 write(efun::driver_info(DI_STATUS_TEXT_MALLOC_EXTENDED));
617 return 1;
618 }
619 return 0;
620}
621
622static int _driver_dumpallobj(string str)
623{
624 write("Dumping to /OBJ_DUMP ... ");
625 efun::dump_driver_info(DDI_OBJECTS);
626 efun::dump_driver_info(DDI_OBJECTS_DESTRUCTED);
627 write("done\n");
628 return 1;
629}
630
631static int _driver_opcdump(string str)
632{
633 efun::dump_driver_info(DDI_OPCODES);
634 return 1;
635}
636
637static int _driver_status(string str)
638{
639 int opt;
640
641 switch(str || "")
642 {
643 case "":
644 opt = DI_STATUS_TEXT_MEMORY;
645 break;
646
647 case "tables":
648 case " tables":
649 opt = DI_STATUS_TEXT_TABLES;
650 break;
651
652 case "swap":
653 case " swap":
654 opt = DI_STATUS_TEXT_SWAP;
655 break;
656
657 case "malloc":
658 case " malloc":
659 opt = DI_STATUS_TEXT_MALLOC;
660 break;
661
662 case "malloc extstats":
663 case " malloc extstats":
664 opt = DI_STATUS_TEXT_MALLOC_EXTENDED;
665 break;
666
667 default:
668 return 0;
669 }
670 write(efun::driver_info(opt));
671 return 1;
672}
673
674// ###################
675//########################## INITIALISIERUNG #############################
676// ###################
677
678//
679// _query_localcmds: Welche Kommandos werden in dieser Datei implementiert?
680//
681
682static mixed _query_localcmds()
683{
684 return ({
685 ({"set","_set",0,LEARNER_LVL}),
686 ({"pwd","_pwd",0,LEARNER_LVL}),
687 ({"cd","_cd",0,LEARNER_LVL}),
688 ({"prompt","_prompt",0,LEARNER_LVL}),
689 ({"showpresay","_showpresay",0,LEARNER_LVL}),
690 ({"exec","_exec",0,ARCH_LVL}),
691 ({"sallow","_sallow",0,LEARNER_LVL}),
692 ({"snoop","_snoop",0,WIZARD_LVL}),
693 ({"mschau","_mschau",0,LEARNER_LVL}),
694 ({"protect","_protect",0,WIZARD_LVL}),
695 ({"invis","_invis",0,LEARNER_LVL}),
696 ({"vis","_vis",0,LEARNER_LVL}),
697 ({"localcmd","_localcmd",0,LEARNER_LVL}),
698 ({"traenke","_traenke",0,DOMAINMEMBER_LVL}),
699 ({"malloc","_driver_malloc",0,LEARNER_LVL}),
700 ({"dumpallobj","_driver_dumpallobj",0,ARCH_LVL}),
701 ({"opcdump","_driver_opcdump",0,ARCH_LVL}),
702 ({"status","_driver_status",0,LEARNER_LVL}),
703 })
704 +fileview::_query_localcmds()
705 +upd::_query_localcmds()
706 +objects::_query_localcmds()
707 +fileedit::_query_localcmds()
708// +todo::_query_localcmds()
709 +players::_query_localcmds()
710 +admin::_query_localcmds()
711 +moving::_query_localcmds()
712 +comm::_query_localcmds();
713}
714
715//
716// initialize: Initialisierung der Shell
717//
718
719static void initialize()
720{
721 Set(P_PROMPT, SAVE, F_MODE_AS);
722 Set(P_VARIABLES,SAVE,F_MODE_AS);
723 Set("filesys",SAVE,F_MODE_AD); // P_FILESYS ist obsolet
724 Set("short_cwd",SAVE,F_MODE_AD); // P_SHORT_CWD auch
725 if(!mappingp(QueryProp(P_VARIABLES)))
726 SetProp(P_VARIABLES, ([]));
727 _prompt(QueryProp(P_PROMPT));
728// todo::initialize();
729 _cd2("");
730 return;
731}
732
733static void reconnect() { _cd(QueryProp(P_CURRENTDIR)); }