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