blob: aca4d8792be63868ee1afbf674a62e681e636999 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/*
2 * MGtool-1.0
3 * File: toolcmds.c
4 * Maintainer: Kirk@MorgenGrauen
5 */
6
7/*------------------------------------------*/
8/* the original Xtool is copyrighted by Hyp */
9/*------------------------------------------*/
10
11#include "tool.h"
12
13/*----------------------------------------------------------------------
14 * command functions
15 */
16
17int Xcall(string str)
18{
19 object obj, callobj;
20 string file, callstr, callfun, callexpr, error, errlog;
21 int *ru1, *ru2, xtime;
22 mixed res;
23
24 SECURE2(TRUE);
25 USAGE2(str, "xcall <object>-><function>(<arguments>)");
26 TK("Xcall: str: "+(str?str:"(NULL)"));
27 if(sscanf(str, "%s->%s(%s", callstr, callfun, callexpr)!=3)
28 return FALSE;
29 if(!(callobj=XFindObj(callstr)))
30 return TRUE;
31 else
32 {
33#if 0
34 write_file(TOOL_LOG,
35 sprintf("%s (%s) xcall %s (env: %s)\n",ctime(time()),
36 getuid(cloner),str,object_name(environment(cloner))));
37#endif
38 file=LPC_FILE+".c";
39 if(file_size(file)>0)
40 rm(file);
41 if(obj=find_object(LPC_FILE))
42 Destruct(obj);
43 obj=0;
44 write_file(file,
45 "#include <properties.h>\n"+
46 "#include <thing/properties.h>\n"+
47 "#include <defines.h>\n"+
48 "#include <wizlist.h>\n"+
49 "#include <moving.h>\n"+
50 "#include \"/secure/wizlevels.h\"\n"+
51 (file_size(PRIVATE_HEADER)>=0?"#include \""+PRIVATE_HEADER+"\"\n":"")+
52 "mixed get(string str){return previous_object()->XFindObj(str);}\n"+
53 "mixed eval(object obj,mixed me,mixed here){return obj->"+callfun+"("+callexpr+";}\n");
54 errlog = ERR_FILE;
55 if(file_size(errlog)>0)
56 rm(errlog);
57 if(error=catch((LPC_FILE)->__nixgibts__()))
58 W("Error: "+error[1..]);
59 else
60 {
61 obj=find_object(LPC_FILE);
62 ru1=rusage();
bugfixd94d0932020-04-08 11:27:13 +020063 error=catch(res=({mixed})obj->eval(callobj, cloner, ENV(cloner)));
MG Mud User88f12472016-06-24 23:31:02 +020064 ru2=rusage();
65 if(error)
66 W("Error: "+error[1..]);
67 else
68 {
69 xtime=ru2[0]-ru1[0]+ru2[1]-ru1[1];
70 WDLN("Evaluation time: "+(xtime<0 ? 0 : xtime)+" ms");
71 PIPE_DELETE(pipe_of);
72 if(pipe_out&&pipe_of)
73 write_file(pipe_of,mixed_to_string(res, MAX_RECURSION)+"\n");
74 else
75 WLN("Result: "+mixed_to_string(res, MAX_RECURSION));
76 if(objectp(res))
77 m_add(variable, "result", res);
78 }
79 }
80 rm(file);
81 }
82 if(obj) Destruct(obj);
83 return TRUE;
84}
85
86int Xcallouts(string str)
87{
88 object obj;
89 mixed callouts, args;
90 string fun, tmp, file;
91 int delay, i, s;
92
93 SECURE2(TRUE);
94 TK("Xcallouts: str: "+(str?str:"(NULL)"));
95 if(!pipe_out)
96 {
97 USAGE1(str, "xcallo(uts) [search pattern]");
98 file=TMP_FILE;
99 if(file_size(file)>0)
100 rm(file);
101 if(!str)
102 str="^\\[~/";
103 else if(!regexp(({"dummy"}), str))
104 {
105 WDLN("Bad regular expression");
106 return TRUE;
107 }
108 }
109 else
110 {
111 USAGE1(str, "xcallo(uts)");
112 if(str&&str!="")
113 {
114 WDLN("More arguments than expected");
115 return TRUE;
116 }
117 }
118 callouts=call_out_info();
119 s=sizeof(callouts);
120 PIPE_DELETE(pipe_of);
121 for(i=0; i<s; i++)
122 {
123 if(callouts[i]&&pointerp(callouts[i]))
124 {
125 tmp=sprintf("%O %Os %O (%s)",callouts[i][0],callouts[i][2],
126 callouts[i][1],(sizeof(callouts[i])>3?
127 mixed_to_string(callouts[i][3],
128 MAX_RECURSION):"0"));
129 if(pipe_out&&pipe_of)
130 write_file(pipe_of,tmp+"\n");
131 else
132 if(sizeof(regexp(({tmp}), str)))
133 WLN(tmp);
134 }
135 }
136 return TRUE;
137}
138
139int Xcat(string str)
140{
141 string *tmp,file;
142 int s;
143
144 SECURE2(TRUE);
145 TK("Xcat: str: "+str);
146 if(!pipe_in)
147 {
148 USAGE2(str, "xcat <file>");
149 if(!(file=XFindFile(str)))
150 {
151 WDLN("Can't find file");
152 return TRUE;
153 }
154 }
155 else
156 {
157 if(str&&str!="-")
158 USAGE3("xcat -");
159
160 if (file_size(file=pipe_if)<0)
161 {
162 WDLN("Missing input to xcat");
163 return TRUE;
164 }
165 }
166 tmp=old_explode(read_file(file,0,PIPE_MAX),"\n");
167 if(pipe_in&&pipe_if==PIPE_FILE)
168 rm(PIPE_FILE);
169 if (pipe_out&&pipe_of)
170 write_file(pipe_of,implode(tmp,"\n")+"\n");
171 else
172 WLN(implode(tmp,"\n"));
173 return TRUE;
174}
175
176int Xcd(string str)
177{
178 object dest;
179 string path;
180
181 SECURE2(TRUE);
182 USAGE1(str, "xcd [object]");
183 TK("Xcd: str: "+(str?str:"(NULL)"));
184 if(!str)
185 {
bugfixd94d0932020-04-08 11:27:13 +0200186 if(!(path=({string})cloner->QueryProp("start_home")))
MG Mud User88f12472016-06-24 23:31:02 +0200187 path="/";
188 }
189 else if((dest=XFindObj(str,1)))
190 path="/"+implode(old_explode(object_name(dest),"/")[0..<2],"/");
191 else
192 path="";
193
194 TK("Xcd: path: "+(path?path:"(NULL)"));
195 if(!sizeof(path))
196 path=str;
197 PL->_cd(path);
198
199 return TRUE;
200}
201
202int Xclean(string str)
203{
204 object env;
205
206 SECURE2(TRUE);
207 USAGE1(str, "xcle(an) [object]");
208 TK("Xclean: str: "+(str?str:"(NULL)"));
209 if(!str)
210 env=ENV(cloner);
211 if(env||(env=XFindObj(str)))
212 {
213 PrintShort("Cleaning: ", env);
214 filter(filter(all_inventory(env), #'is_not_player),//'
215 "Destruct", ME);
216 }
217 return TRUE;
218}
219
220int Xclone(string str)
221{
222 object obj;
223 string file, errlog, error;
224
225 SECURE2(TRUE);
226 USAGE2(str, "xclo(ne) <filename>");
227 if(!(file=XFindFile(str))) return TRUE;
228 errlog=ERR_FILE;
229 if(file_size(errlog)>0) rm(errlog);
230 WLN("Clone: "+short_path(file));
231 if(!(error=catch(obj=clone_object(file))))
232 {
233 m_add(variable, "clone", obj);
234 if(!MoveObj(obj, ENV(cloner), TRUE))
235 WDLN("Cannot move object into this room");
bugfixd94d0932020-04-08 11:27:13 +0200236 else if(!({mixed})obj->QueryNoGet())
MG Mud User88f12472016-06-24 23:31:02 +0200237 {
238 if(!MoveObj(obj, cloner, TRUE))
239 WDLN("Cannot move object into your inventory");
240 }
241 }
242 else
243 W("Error: "+error[1..]);
244 return TRUE;
245}
246
247int Xuclone(string str)
248{
249 object obj;
250 string file, errlog, error;
251
252 SECURE2(TRUE);
253 USAGE2(str, "xuclo(ne) <filename>");
254 if(!(file=XFindFile(str))) return TRUE;
255 errlog=ERR_FILE;
256 if(file_size(errlog)>0) rm(errlog);
257 if(obj=find_object(file)) {
258 Destruct(obj);
259 WLN("Update and clone: "+short_path(file));
260 }
261 else
262 WLN("Clone: "+short_path(file));
263 if(!(error=catch(obj=clone_object(file))))
264 {
265 variable["clone"] = obj;
266 if(!MoveObj(obj, ENV(cloner), TRUE))
267 WDLN("Cannot move object into this room");
bugfixd94d0932020-04-08 11:27:13 +0200268 else if(!({mixed})obj->QueryNoGet())
MG Mud User88f12472016-06-24 23:31:02 +0200269 {
270 if(!MoveObj(obj, cloner, TRUE))
271 WDLN("Cannot move object into your inventory");
272 }
273 }
274 else
275 W("Error: "+error[1..]);
276 return TRUE;
277}
278
279int Xcmds(string str)
280{
281 object obj;
282 mixed *cmds;
283 int i, s;
284
285 SECURE2(TRUE);
286 USAGE1(str, "xcm(ds) [object]");
287 TK("Xcmds: str: "+(str?str:"(NULL)"));
288 if(!str)
289 obj=ENV(cloner);
290 else if(!(obj=XFindObj(str)))
291 {
292 WDLN("Can't find object");
293 return TRUE;
294 }
295 s=sizeof(cmds=query_actions(cloner,1|2|4|8|16));
296 PIPE_DELETE(pipe_of);
297 for(i=0; i<s; i+=5)
298 if(cmds[i+3]==obj)
299 if(pipe_out&&pipe_of)
300 write_file(pipe_of,ALEFT(cmds[i]+" ", 15, ".")+
301 (cmds[i+2] ? " * " : " . ")+cmds[i+4]+"()\n");
302 else
303 WLN(ALEFT(cmds[i]+" ", 15, ".")+
304 (cmds[i+2] ? " * " : " . ")+cmds[i+4]+"()");
305 return TRUE;
306}
307
308int Xdbg(string str)
309{
310 object obj;
311
312 SECURE2(TRUE);
313 USAGE2(str, "xdb(g) <object>");
314 TK("Xdbg: str: "+(str?str:"(NULL)"));
315 if((obj=XFindObj(str)))
316 {
317 debug_info(1, obj);
318 debug_info(0, obj);
319 }
320 return TRUE;
321}
322
323int Xdclean(string str)
324{
325 object env;
326
327 SECURE2(TRUE);
328 USAGE1(str, "xdc(lean) [object]");
329 TK("Xdclean: str: "+(str?str:"(NULL)"));
330 if(!str)
331 env=ENV(cloner);
332 if(env||(env=XFindObj(str)))
333 {
334 PrintShort("Deep cleaning: ", env);
335 filter(filter(all_inventory(env), #'is_not_player, ME),//'
336 "DeepClean", ME);
337 }
338 return TRUE;
339}
340
341int Xddes(string str)
342{
343 object obj;
344
345 SECURE2(TRUE);
346 USAGE2(str, "xdd(es) <object>");
347 TK("Xddes: str: "+(str?str:"(NULL)"));
348 if((obj=XFindObj(str)))
349 {
350 PrintShort("Deep destruct: ", obj);
351 filter(deep_inventory(obj), "Destruct", ME);
352 Destruct(obj);
353 }
354 return TRUE;
355}
356
357int Xdes(string str)
358{
359 object obj;
360
361 SECURE2(TRUE);
362 USAGE2(str, "xde(s) <object>");
363 TK("Xdes: str: "+(str?str:"(NULL)"));
364 if((obj=XFindObj(str)))
365 {
366 PrintShort("Destruct: ",obj);
367 Destruct(obj);
368 }
369 return TRUE;
370}
371
372int Xdlook(string str)
373{
374 object obj;
375
376 SECURE2(TRUE);
377 USAGE1(str, "xdl(ook) [object]");
378 TK("Xdlook: str: "+(str?str:"(NULL)"));
379 if(!str)
380 obj=cloner;
381 if(obj||(obj=XFindObj(str)))
382 {
383 PIPE_DELETE(pipe_of);
384 DeepPrintShort(obj,NULL,NULL,(pipe_out&&pipe_of)?pipe_of:"");
385 }
386 return TRUE;
387}
388
389int Xdo(string str)
390{
391 int i, n, s;
392 string *strs, cmd;
393
394 SECURE2(TRUE);
395 USAGE2(str, "xdo [<number1>#]<command1>[;[<number2>#]<command2>] ...");
396 if(!str||str==""||!(s=sizeof(strs=strip_explode(str, ";"))))
397 return FALSE;
398 for(i=0; i<s; i++)
399 {
400 if(strs[i])
401 {
402 switch(sscanf(strs[i], "%d#%s", n, cmd))
403 {
404 case 0:
405 if(!Command(strs[i])) return TRUE;
406 break;
407 case 1:
408 if(cmd&&(!Command(cmd))) return TRUE;
409 break;
410 case 2:
411 n= n<1 ? 1 : n;
412 if(cmd)
413 {
414 while(n--)
415 if(!Command(cmd)) return TRUE;
416 }
417 break;
418 }
419 }
420 }
421 return TRUE;
422}
423
424int Xdupdate(string str)
425{
426 int i, s;
427 object obj;
428 string file, *list;
429
430 SECURE2(TRUE);
431 USAGE2(str, "xdu(pdate) <filename>");
432 if(!(file=XFindFile(str)))
433 return TRUE;
434 if(file[<2..<1]==".c")
435 file=file[0..<3];
436 if(obj=XFindObj(file))
437 {
438 PrintShort("Deep updating: ", obj);
439 list=inherit_list(obj);
440 for(s=sizeof(list); i<s; i++)
441 {
442 if(obj=find_object(list[i]))
443 Destruct(obj);
444 }
445 }
446 return TRUE;
447}
448
449int Xecho(string str)
450{
451 TK("Xecho: str: "+(str?str:"(NULL)"));
452 WLN(str);
453 return TRUE;
454}
455
456int Xeval(string str)
457{
458 object obj;
459 string file, error;
460 int *ru1, *ru2, xtime;
461 mixed res;
462
463 SECURE2(TRUE);
464 USAGE2(str, "xev(al) <expression>");
465 file=LPC_FILE+".c";
466 if(file_size(file)>0)
467 rm(file);
468 if(obj=find_object(LPC_FILE))
469 Destruct(obj);
470#if 0
471 write_file(TOOL_LOG,
472 sprintf("%s (%s) xeval %s\n",
473 ctime(time()),getuid(cloner),str));
474#endif
475 write_file(file,
476 "#include <properties.h>\n"+
477 "#include <thing/properties.h>\n"+
478 "#include <defines.h>\n"+
479 "#include <wizlist.h>\n"+
480 "#include <moving.h>\n"+
481 "#include \"/secure/wizlevels.h\"\n"+
482 (file_size(PRIVATE_HEADER)>=0?"#include \""+PRIVATE_HEADER+"\"\n":"")+
Zesstra13fb5a02020-04-15 13:28:39 +0200483 "mixed get(string str){return previous_object()->XFindObj(str);}\n"+
484 "mixed eval(mixed me,mixed here){return "+str+";}");
MG Mud User88f12472016-06-24 23:31:02 +0200485 if(error=catch(obj=clone_object(file)))
486 W("Error: "+error[1..]);
487 else
488 {
489 ru1=rusage();
bugfixd94d0932020-04-08 11:27:13 +0200490 error=catch(res=({mixed})obj->eval(cloner, ENV(cloner)));
MG Mud User88f12472016-06-24 23:31:02 +0200491 ru2=rusage();
492 if(error)
493 W("Error: "+error[1..]);
494 else
495 {
496 xtime=ru2[0]-ru1[0]+ru2[1]-ru1[1];
497 WDLN("Evaluation time: "+(xtime<0 ? 0 : xtime)+" ms");
498 PIPE_DELETE(pipe_of);
499 if(pipe_out&&pipe_of)
500 write_file(pipe_of,mixed_to_string(res,MAX_RECURSION)+"\n");
501 else
502 WLN("Result: "+mixed_to_string(res, MAX_RECURSION));
503 if(objectp(res))
504 variable["result"] = res;
505 }
506 }
507 rm(file);
508 if(obj)
509 Destruct(obj);
510 return TRUE;
511}
512
513int Xforall(string str)
514{
515 int i, s, t, u;
516 string pat, cmd, arg, *strs, *files, fh, fr, fe, ft, ff;
517
518 SECURE2(TRUE);
519 USAGE2(str, "xfo(rall) <filepattern> <command>");
520 if(sscanf(str, "%s %s", pat, arg)!=2)
521 return FALSE;
522 files=long_get_dir(pat, FALSE);
523 if(!(s=sizeof(files)))
524 {
525 WDLN("No matching files found");
526 return TRUE;
527 }
528 strs=old_explode(files[0], "/");
529 fh="/";
530 if(t=sizeof(strs)-1)
531 fh+=implode(strs[0..t-1], "/");
532 for(i=0; i<s; i++)
533 {
534 ft=old_explode(files[i], "/")[t];
535 if((u=sizeof(strs=old_explode(ft, ".")))&&--u)
536 {
537 ff=implode(strs[0..u-1], ".");
538 fr=fh+"/"+ff;
539 fe=strs[u];
540 }
541 else
542 {
543 fe="";
544 ff=ft;
545 fr=files[i];
546 }
547 cmd=string_replace(arg, "!!", files[i]);
548 cmd=string_replace(cmd, "!e", fe);
549 cmd=string_replace(cmd, "!f", ff);
550 cmd=string_replace(cmd, "!h", fh);
551 cmd=string_replace(cmd, "!r", fr);
552 cmd=string_replace(cmd, "!t", ft);
553 if(!(Command(cmd)))
554 break;
555 }
556 return TRUE;
557}
558
559int Xgoto(string str)
560{
561 object obj, tmp;
562
563 SECURE2(TRUE);
564 USAGE1(str, "xgo(to) [object]");
565 if(!str) str="~/workroom";
566 if(!(obj=XFindObj(str)))
567 {
568 if(!(str=XFindFile(str)))
569 return TRUE;
570 if(catch(call_other(str, "???")))
571 return TRUE;
572 obj=find_object(str);
573 }
574 tmp=obj;
575 while(obj&&living(obj))
576 obj=ENV(obj);
577 cloner->move(obj ? obj : tmp, M_TPORT);
578 return TRUE;
579}
580
581int Xgrep(string str)
582{
583 int i, s, t, mode;
584 string *files, *ts;
585
586 SECURE2(TRUE);
587 TK("Xgrep: str: "+(str?str:"(NULL)"));
588 mode=0;
589 if(!pipe_in)
590 {
591 USAGE2(str, "xgr(ep) [-i] [-v] <regexp> <filepattern>");
592 if(!(ts=old_explode(str, " "))||!(s=sizeof(ts)))
593 return FALSE;
594 while(ts[0][0]=='-')
595 {
596 if(s<3)
597 {
598 WDLN("Too few arguments to xgrep");
599 return FALSE;
600 }
601 switch(ts[0])
602 {
603 case "-v":
604 mode|=XGREP_REVERT;
605 ts=ts[1..];
606 s--;
607 break;
608 case "-i":
609 mode|=XGREP_ICASE;
610 ts=ts[1..];
611 s--;
612 break;
613 case "-vi":
614 case "-iv":
615 mode|=XGREP_REVERT;
616 mode|=XGREP_ICASE;
617 ts=ts[1..];
618 s--;
619 break;
620 default:
621 WDLN("Unknown option "+ts[0]+" given to xgrep");
622 return FALSE;
623 }
624 }
625 str=implode(ts[0..s-2], " ");
626 }
627 else
628 {
629 if(!((ts=old_explode(str, " "))&&(s=sizeof(ts))))
630 USAGE3("xgr(ep) [-i] [-v] <regexp>");
631 while(ts[0][0]=='-')
632 {
633 if(s<2)
634 {
635 WDLN("Too few arguments to xgrep");
636 return FALSE;
637 }
638 switch(ts[0])
639 {
640 case "-v":
641 mode|=XGREP_REVERT;
642 ts=ts[1..];
643 s--;
644 break;
645 case "-i":
646 mode|=XGREP_ICASE;
647 ts=ts[1..];
648 s--;
649 break;
650 case "-iv":
651 case "-vi":
652 mode|=XGREP_REVERT;
653 mode|=XGREP_ICASE;
654 ts=ts[1..];
655 s--;
656 break;
657 default:
658 WDLN("Unknown option "+ts[0]+" given to xgrep");
659 return FALSE;
660 }
661 }
662 str=implode(ts[0..s-1], " ");
663 }
664
665 if(mode&XGREP_ICASE)
666 str=lower_case(str);
667 if(!(regexp(({"dummy"}), str)))
668 {
669 WDLN("Bad regular expression");
670 return TRUE;
671 }
672 if(!pipe_in)
673 {
674 if(file_size(TMP_FILE)>0)
675 rm(TMP_FILE);
676 if((t=sizeof(files=long_get_dir(XFile(ts[s-1]), FALSE)))&&
677 (file_size(files[0])>=0))
678 {
679 for(i=0; i<t; i++)
680 XGrepFile(str, files[i], mode);
681 if(pipe_out&&pipe_of)
682 {
683 PIPE_DELETE(pipe_of);
684 if(!pipe_ovr)
685 {
686 write_file(pipe_of,read_file(TMP_FILE,0,PIPE_MAX));
687 rm(TMP_FILE);
688 }
689 else
690 rename(TMP_FILE,pipe_of);
691 }
692 else
693 {
694 W(read_file(TMP_FILE,0,PIPE_MAX));
695 rm(TMP_FILE);
696 }
697 }
698 else
699 WDLN("Cannot read file(s)");
700 }
701 else
702 {
703 string *tmp;
704 if(file_size(pipe_if)<0)
705 {
706 WDLN("Missing input to xgrep");
707 return TRUE;
708 }
709 TK("Xgrep: str: "+str+" mode: "+mode);
710 s=sizeof(tmp=old_explode(read_file(pipe_if,0,PIPE_MAX),"\n"));
711 PIPE_DELETE(pipe_of);
712 for(i=0;i<s;i++)
713 {
714 // TK(tmp[i]+"<->"+str);
715 if(sizeof(regexp(({(mode&XGREP_ICASE?lower_case(tmp[i]):tmp[i])}),str)))
716 {
717 // TK("Xgrep: matched!");
718 if(!(mode&XGREP_REVERT))
719 if(pipe_out&&pipe_of)
720 write_file(pipe_of,tmp[i]+"\n");
721 else
722 WLN(tmp[i]);
723 }
724 else
725 if(mode&XGREP_REVERT)
726 if(pipe_out&&pipe_of)
727 write_file(pipe_of,tmp[i]+"\n");
728 else
729 WLN(tmp[i]);
730 }
731 }
732 return TRUE;
733}
734
735int Xhbeats(string str)
736{
737 object obj;
738 object *hbeatinfo;
739 string tmp, file;
740 int i, s;
741
742 SECURE2(TRUE);
743 TK("Xhbeats: str: "+(str?str:"(NULL)"));
744 if(!pipe_out)
745 {
746 USAGE1(str, "xhb(eats) [search pattern]");
747 if(!str)
748 str=RNAME(cloner);
749 else if(!regexp(({"dummy"}), str))
750 {
751 WDLN("Bad regular expression");
752 return TRUE;
753 }
754 }
755 else
756 {
757 USAGE1(str,"xhb(eats)");
758 if(str&&str!="")
759 {
760 WDLN("More arguments than expected");
761 return TRUE;
762 }
763 }
764 s=sizeof(hbeatinfo=heart_beat_info());
765 PIPE_DELETE(pipe_of);
766 for(i=0; i<s; i++)
767 if(hbeatinfo[i]&&objectp(hbeatinfo[i]))
768 {
769 tmp=ObjFile(hbeatinfo[i]);
770 if(sizeof(regexp(({tmp}), str)))
771 if(pipe_out&&pipe_of)
772 write_file(pipe_of, tmp+"\n");
773 else
774 WLN(tmp);
775 }
776 return TRUE;
777}
778
779int Xhead(string str)
780{
781 int lines;
782 string *tmp, file;
783
784 SECURE2(TRUE);
785 TK("Xhead: str: "+(str?str:"(NULL)"));
786 if(!pipe_in)
787 {
788 USAGE2(str, "xhead <-#> <file>");
789 if(sscanf(str,"-%d %s",lines,file)!=2)
790 return FALSE;
791 if(!(file=XFindFile(file)))
792 return FALSE;
793 }
794 else
795 {
796 USAGE2(str, "xhead <-#>");
797 if(sscanf(str,"-%d",lines)!=1)
798 return FALSE;
799 if (file_size(file=pipe_if)<0)
800 {
801 WDLN("Missing input to xhead");
802 return TRUE;
803 }
804 }
805 tmp=old_explode(read_file(file,0,PIPE_MAX),"\n")[0..lines-1];
806 if(pipe_in&&pipe_if==PIPE_FILE)
807 rm(PIPE_FILE);
808 if (pipe_out&&pipe_of)
809 {
810 PIPE_DELETE(pipe_of);
811 write_file(pipe_of,implode(tmp,"\n")+"\n");
812 }
813 else
814 WDLN(implode(tmp,"\n"));
815 return TRUE;
816}
817
818int Xhelp(string str)
819{
820 SECURE2(TRUE);
821 USAGE1(str, "xhe(lp)");
822 XMoreFile(TOOL_MANPAGE, FALSE);
823 return TRUE;
824}
825
826int Xids(string str)
827{
828 object obj;
829
830 SECURE2(TRUE);
831 USAGE2(str, "xid(s) <object>");
832 TK("Xids: str: "+(str?str:"(NULL)"));
833 if((obj=XFindObj(str)))
834 WLN("UID=\""+getuid(obj)+"\" / EUID=\""+geteuid(obj)+"\"");
835 return TRUE;
836}
837
838int Xinfo(string str)
839{
840 object obj;
841
842 SECURE2(TRUE);
843 USAGE2(str, "xinf(o) <object>");
844 TK("Xinfo: str: "+(str?str:"(NULL)"));
845 if((obj=XFindObj(str)))
846 {
847 if(is_player(obj))
848 {
849 WLN(PlayerWho(obj));
850 WLN(PlayerMail(obj, FALSE));
851 WLN(PlayerIP(obj, FALSE));
852 WLN(PlayerRace(obj, FALSE));
853 WLN(PlayerDomain(obj, FALSE));
854 WLN(PlayerStats(obj, FALSE));
855 WLN(PlayerSnoop(obj, FALSE));
856 }
857 else
858 WDLN("Sorry, this is not a player");
859 }
860 return TRUE;
861}
862
863int Xinherit(string str)
864{
865 int s;
866 object obj;
867 string *strs, *inlist;
868
869 SECURE2(TRUE);
870 USAGE2(str, "xinh(erit) <object> [function]");
871 TK("Xinherit: str: "+str);
872 if(!(strs=strip_explode(str, " ")))
873 return FALSE;
874 if(obj=XFindObj(strs[0]))
875 {
876 inlist=inherit_list(obj);
877 s=sizeof(inlist);
878 while(s--)
879 {
880 if(catch(call_other(inlist[s], "???")))
881 {
882 WDLN("Failed to load all inheritance objects");
883 return TRUE;
884 }
885 }
886 obj=find_object(inlist[0]);
887 PIPE_DELETE(pipe_of);
888 if(sizeof(strs)==1)
889 Inheritance(obj ,0 ,"");
890 else
891 Inheritance(obj, strs[1], "");
892 }
893 return TRUE;
894}
895
896int Xinventory(string str)
897{
898 int i, short;
899 object item;
900 mixed who;
901
902 SECURE2(TRUE);
903 USAGE1(str, "xi [-s] [player]");
904 TK("Xinventory: str: "+str);
905 short=0;
906 who=cloner;
907 if(str&&str!="")
908 {
909 if(str=="-s")
910 {
911 short=1;
912 who=cloner;
913 }
914 else if(sscanf(str,"-s %s",who))
915 {
916 short=1;
917 who=XFindObj(who);
918 }
919 else if(sscanf(str,"%s",who))
920 {
921 short=0;
922 who=XFindObj(who);
923 }
924 else
925 who=cloner;
926 }
927 if(!who)
928 return FALSE;
929 PIPE_DELETE(pipe_of);
930 if(!(pipe_out&&pipe_of))
bugfixd94d0932020-04-08 11:27:13 +0200931 WLN(({string})who->name(WESSEN)+" Inventory:"+(short?" (short)":""));
MG Mud User88f12472016-06-24 23:31:02 +0200932 if(!short)
933 if(pipe_out&&pipe_of)
934 FORALL(item, who) PrintShort(ARIGHT(++i+". ", 4, " "), item, pipe_of);
935 else
936 FORALL(item, who) PrintShort(ARIGHT(++i+". ", 4, " "), item);
937 else
938 if(pipe_out&&pipe_of)
939 FORALL(item, who) write_file(pipe_of,++i+". ["+object_name(item)+"]\n");
940 else
941 FORALL(item, who) WLN(++i+". ["+object_name(item)+"]");
942 return TRUE;
943}
944
945int Xlag(string str)
946{
947 int i;
948 float *lag;
949 object daemon;
950 string lags;
951
Zesstrabc791ab2017-01-30 23:06:48 +0100952 if(!(daemon=load_object(LAG_O_DAEMON)))
MG Mud User88f12472016-06-24 23:31:02 +0200953 lag=({-1.0,-1.0,-1.0});
954 else
bugfixd94d0932020-04-08 11:27:13 +0200955 lag=({float*})daemon->read_lag_data();
Zesstradb5c6522020-05-27 00:26:35 +0200956
957 lags =sprintf("Letzte 60 min: %.1f%%\n",lag[2]);
958 lags+=sprintf("Letzte 15 min: %.1f%%\n",lag[1]);
959 lags+=sprintf("Letzte Minute: %.1f%%\n",lag[0]);
960
MG Mud User88f12472016-06-24 23:31:02 +0200961 WLN(lags);
962 return TRUE;
963}
964
965int Xlight(string str)
966{
967 int s, addlight;
968
969 SECURE2(TRUE);
970 USAGE1(str, "xli(ght) [light]");
971 if(str)
972 {
973 if(!sscanf(str, "%d", addlight))
974 return FALSE;
975 xlight+=addlight;
976 cloner->AddIntLight(addlight);
977 }
978 WDLN("Current light levels: "+TOOL_NAME+"="+xlight+", room="+
bugfixd94d0932020-04-08 11:27:13 +0200979 ({int})ENV(cloner)->QueryIntLight());
MG Mud User88f12472016-06-24 23:31:02 +0200980 return TRUE;
981}
982
983int Xload(string str)
984{
985 int i, f;
986 object obj, *inv, vroom;
987 string file, errlog, error, *strs;
988
989 SECURE2(TRUE);
990 USAGE2(str, "xloa(d) <filename>");
991 if(!(file=XFindFile(str)))
992 return TRUE;
993 errlog=ERR_FILE;
994 if(file_size(errlog)>0)
995 rm(errlog);
996 if(obj=find_object(file))
997 {
998 if(catch(call_other(VOID, "???")))
999 {
1000 WDLN("Error: cannot find "+VOID+" to rescue players");
1001 return TRUE;
1002 }
1003 else
1004 vroom = find_object(VOID);
1005 if(inv=filter(all_inventory(obj), #'is_player, ME))//'
1006 for(i=0; i<sizeof(inv); i++)
1007 MoveObj(inv[i], vroom, TRUE);
1008 Destruct(obj);
1009 WLN("Update and load: "+file);
1010 }
1011 else
1012 WLN("Load: "+file);
1013 if(error=catch(call_other(file, "???")))
1014 {
1015 W("Error: "+error[1..]);
1016 if(vroom)
1017 tell_object(vroom, "*** Failed to load room. You are in the void!\n");
1018 }
1019 else if(inv)
1020 {
1021 obj=find_object(file);
1022 for(i=0; i<sizeof(inv); i++)
1023 if(inv[i])
1024 MoveObj(inv[i], obj, TRUE);
1025 }
1026 return TRUE;
1027}
1028
1029int Xlook(string str)
1030{
1031 object obj;
1032 string st;
1033 string file;
1034
1035 SECURE2(TRUE);
1036 USAGE1(str, "xloo(k) [object]");
1037 TK("Xlook: str: "+str);
1038 PIPE_DELETE(pipe_of);
1039 file = pipe_out&&pipe_of ? pipe_of : "";
1040 if(str&&str!="")
1041 {
1042 if((obj=XFindObj(str)))
1043 PrintObj(obj,file);
1044 }
1045 else
1046 {
1047 obj=ENV(cloner);
1048 PrintObj(obj,file);
1049 }
1050 return TRUE;
1051}
1052
1053int Xlpc(string str)
1054{
1055 object obj;
1056 string file, error;
1057 int *ru1, *ru2, time;
1058 mixed res;
1059
1060 SECURE2(TRUE);
1061 USAGE2(str, "xlp(c) <lpc code>");
1062 file=LPC_FILE+".c";
1063 if(file_size(file)>0)
1064 rm(file);
1065 if(obj=find_object(LPC_FILE))
1066 Destruct(obj);
1067 write_file(file,
1068 "#pragma no_warn_missing_return,strong_types,warn_deprecated,rtt_checks\n"
1069 "#include <properties.h>\n"
1070 "#include <thing/properties.h>\n"
1071 "#include <defines.h>\n"
1072 "#include <wizlist.h>\n"
1073 "#include <moving.h>\n"
1074 "#include \"/secure/wizlevels.h\"\n"
1075 +(file_size(PRIVATE_HEADER)>=0?"#include \""+PRIVATE_HEADER+"\"\n":"")+
1076 "object get(string str){return previous_object()->XFindObj(str);}\n"+
1077 "mixed eval(mixed me, mixed here){"+str+"}");
1078 if(error=catch(obj=clone_object(file)))
1079 W("Error: "+error[1..0]);
1080 else
1081 {
1082 ru1=rusage();
bugfixd94d0932020-04-08 11:27:13 +02001083 error=catch(res=({mixed})obj->eval(cloner, ENV(cloner)));
MG Mud User88f12472016-06-24 23:31:02 +02001084 ru2=rusage();
1085 if(error)
1086 W("Error: "+error[1..]);
1087 else
1088 {
1089 time=ru2[0]-ru1[0]+ru2[1]-ru1[1];
1090 WDLN("Evaluation time: "+(time<0 ? 0 : time)+" ms");
1091 WLN("Result: "+mixed_to_string(res, MAX_RECURSION));
1092 if(objectp(res))
1093 variable["result"] = res;
1094 }
1095 }
1096 rm(file);
1097 if(obj)
1098 Destruct(obj);
1099 return TRUE;
1100}
1101
1102int Xman(string str)
1103{
1104 string manpage;
1105 int i, found;
1106
1107 SECURE2(TRUE);
1108 USAGE2(str, "xma(n) <manpage>");
1109 W("Man: ");
1110 for(i=0, found=0; i<sizeof(manpath); i++)
1111 {
1112 manpage=manpath[i]+str;
1113 if(file_size(manpage)>=0)
1114 {
1115 WLN(manpage);
1116 XMoreFile(manpage, FALSE);
1117 found=1;
1118 break;
1119 }
1120 }
1121 if(!found)
1122 WLN("- no help available -");
1123 return TRUE;
1124}
1125
1126int Xmore(string str)
1127{
1128 string *args, file;
1129 int line;
1130
1131 SECURE2(TRUE);
1132 TK("Xmore: str: "+str);
1133 if (!pipe_in)
1134 {
1135 USAGE2(str, "xmor(e) <filename> [start]");
1136 switch(sizeof(args=strip_explode(str, " ")))
1137 {
1138 case 1:
1139 moreoffset=1;
1140 break;
1141 case 2:
1142 sscanf(args[1], "%d", line);
1143 moreoffset= line>0 ? line : 1;
1144 break;
1145 default:
1146 return FALSE;
1147 }
1148 if(file=XFindFile(args[0]))
1149 XMoreFile(file, TRUE);
1150 }
1151 else
1152 {
1153 if(file_size(pipe_if)<0)
1154 {
1155 WDLN("Missing input to xmore");
1156 return TRUE;
1157 }
1158 if (!str||str=="")
1159 line=1;
1160 else if (sscanf(str, "%d", line)!=1)
1161 USAGE3("xmor(e) [start]");
1162 moreoffset= line>0 ? line : 1;
1163 XMoreFile(pipe_if, TRUE);
1164 }
1165 return TRUE;
1166}
1167
1168int Xmove(string str)
1169{
1170 object obj1, obj2;
1171 string what, into;
1172
1173 SECURE2(TRUE);
1174 USAGE2(str, "xmov(e) <object> into <object>");
1175 if((sscanf(str, "%s into %s", what, into)==2)&&
1176 (obj1=XFindObj(what))&&(obj2=XFindObj(into)))
1177 MoveObj(obj1, obj2, FALSE);
1178 return TRUE;
1179}
1180
1181int Xmsg(string str)
1182{
1183 string tmp;
1184
1185 SECURE2(TRUE);
1186 TK("Xmsg: str: "+str);
1187 USAGE1(str, "xms(g) [to <object>|all]");
1188 if(!str||str=="")
1189 {
1190 WDLN("Send message into room");
1191 say("Message from "+CRNAME(cloner)+":\n");
1192 if(pipe_in&&pipe_if)
1193 say(read_file(pipe_if,0,PIPE_MAX));
1194 else
1195 {
1196 WDLN("End message with \".\" or \"**\"");
1197 input_to("XMsgSay");
1198 }
1199 return TRUE;
1200 }
1201 else if(sscanf(str, "to %s", tmp))
1202 {
1203 if(msgto=XFindObj(tmp))
1204 {
1205 PrintShort("Send message to: ", msgto);
1206 tell_object(msgto, "Message from "+CRNAME(cloner)+" to you:\n");
1207 if(pipe_in&&pipe_if)
1208 tell_object(msgto,read_file(pipe_if,0,PIPE_MAX));
1209 else
1210 {
1211 WDLN("End message with \".\" or \"**\"");
1212 input_to("XMsgTell");
1213 }
1214 }
1215 return TRUE;
1216 }
1217 else if(str=="all")
1218 {
1219 WDLN("Send message to all players");
1220 shout("Message from "+CRNAME(cloner)+" to all:\n");
1221 if(pipe_in&&pipe_if)
1222 shout(read_file(pipe_if,0,PIPE_MAX));
1223 else
1224 {
1225 WDLN("End message with \".\" or \"**\"");
1226 input_to("XMsgShout");
1227 }
1228 return TRUE;
1229 }
1230 return FALSE;
1231}
1232
1233int Xmtp(string str)
1234{
1235 int s;
1236 string *strs, opt, dir, file;
1237
1238 SECURE2(TRUE);
1239 USAGE2(str, "xmt(p) [options] <directory> <filename>");
1240 s=sizeof(strs=old_explode(str, " "));
1241 if(s<2)
1242 return FALSE;
1243 else if(s==2)
1244 opt="";
1245 else
1246 opt=implode(strs[0..s-3], " ");
bugfixd94d0932020-04-08 11:27:13 +02001247 if(!(dir="/"+({int})MASTER->valid_read(strs[s-2], geteuid(),
MG Mud User88f12472016-06-24 23:31:02 +02001248 "get_dir", ME))) {
1249 WDLN("No permission to open directory for reading");
1250 return TRUE;
1251 }
bugfixd94d0932020-04-08 11:27:13 +02001252 if(!(file="/"+({int})MASTER->valid_write(strs[s-1], geteuid(),
MG Mud User88f12472016-06-24 23:31:02 +02001253 "write_file", ME))) {
1254 WDLN("No permission to open script file for writing");
1255 return TRUE;
1256 }
1257 if(file_size(dir)!=-2 || file_size(file)==-2)
1258 return FALSE;
1259 XmtpScript(dir, file, opt);
1260 WDLN("Done");
1261 return TRUE;
1262}
1263
1264int Xproc(string str)
1265{
1266 int s;
1267 string *strs;
1268
1269 SECURE2(TRUE);
1270 USAGE1(str, "xproc [-c] [-l] [-m] [-u] [-v]");
1271
1272 if(file_size(TOOL_PATH+"/proc")!=-2)
1273 {
1274 WLN("Sorry, no /proc information available!");
1275 return TRUE;
1276 }
1277
1278 if(!str||str==""||!(s=sizeof(strs=old_explode(str, " "))))
1279 {
1280 WLN("Load averages:");
1281 cat(TOOL_PATH+"/proc/loadavg");
1282 return TRUE;
1283 }
1284
1285 while(s=sizeof(strs))
1286 {
1287 switch(strs[0])
1288 {
1289 case "-c":
1290 WLN("CPU info:");
1291 cat(TOOL_PATH+"/proc/cpuinfo");
1292 break;
1293 case "-l":
1294 WLN("Load averages:");
1295 cat(TOOL_PATH+"/proc/loadavg");
1296 break;
1297 case "-m":
1298 WLN("Memory usage:");
1299 cat(TOOL_PATH+"/proc/meminfo");
1300 break;
1301 case "-u":
1302 WLN("Uptime:");
1303 cat(TOOL_PATH+"/proc/uptime");
1304 break;
1305 case "-v":
1306 WLN("Version:");
1307 cat(TOOL_PATH+"/proc/version");
1308 break;
1309 default:
1310 WLN("Unknown option: "+strs[0]);
1311 }
1312 strs=strs[1..];
1313 }
1314 return TRUE;
1315}
1316
1317int Xprof(string str)
1318{
1319 string *funcs, inh, tmp;
1320 mixed *data, *d;
1321 mapping xpr;
1322 object obj;
1323 int i, rn;
1324
1325 SECURE2(TRUE);
1326 USAGE2(str, "xprof <<-c>|<-C> <file>>|<object>");
1327 if(str[0..2]=="-c "||str[0..2]=="-C ")
1328 {
1329 rn=(str[1]=='C');
1330 if(str=XFindFile(str[3..]))
1331 {
1332 inh=str=str[0..<3];
1333 if(obj=find_object(inh))
1334 Destruct(obj);
1335 if(catch(call_other(inh,"???")))
1336 return TRUE;
1337 obj=find_object(inh);
1338 if(rn)
1339 {
1340 inh+=".xprof.c";
1341 rm(inh);
1342 str+=".c";
1343 rename(str, inh);
1344 }
1345 else
1346 {
1347 str=XPROF_FILE;
1348 rm(str);
1349 }
1350 tmp="inherit \""+inh+"\";\n#include \""+XPROF_MACRO+"\"\n";
1351 funcs=m_indices(mkmapping(functionlist(obj, 0x08000001)))-({"__INIT"});
1352 for(i=sizeof(funcs); i--;)
1353 tmp+="F("+funcs[i]+",\""+funcs[i]+"\","+
1354 "(A0,A1,A2,A3,A4,A5,A6,A7,A8,A9))\n";
1355 write_file(str, tmp);
1356 WDLN("Done");
1357 }
1358 }
1359 else if(obj=XFindObj(str))
1360 {
bugfixd94d0932020-04-08 11:27:13 +02001361 if(xpr=({mixed})obj->__query_xprof_data__())
MG Mud User88f12472016-06-24 23:31:02 +02001362 {
1363 funcs=m_indices(xpr);
1364 data=m_values(xpr);
1365 rm(TMP_FILE);
1366 str="Evaluation cost per function:\nNAME "+
1367 " CALLS | TOT.EXCL. TOT.INCL. | REL.EXCL. REL.INCL.\n";
1368 for(i=sizeof(funcs); i--;)
1369 {
1370 if(d=data[i]) {
1371 funcs[i]=ALEFT(""+funcs[i]+" ",25,".")+ARIGHT(" "+d[0], 6,".")+" | "+
1372 ARIGHT(" "+d[1],10,".") +" "+ARIGHT(" "+d[3],10,".")+" | "+
1373 ARIGHT(" "+d[1]/d[0],9,".") +" "+ARIGHT(" "+d[3]/d[0],9,".");
1374 }
1375 }
1376 str+=implode(sort_array(funcs, "string_compare", ME),"\n")+"\n";
1377 write_file(TMP_FILE,str);
1378 str="\nElapsed time per function:\nNAME "+
1379 " CALLS | TOT.EXCL. TOT.INCL. | REL.EXCL. REL.INCL.\n";
1380 funcs=m_indices(xpr);
1381 for(i=sizeof(funcs); i--;)
1382 {
1383 if(d=data[i])
1384 {
1385 funcs[i]=ALEFT(""+funcs[i]+" ",25,".")+ARIGHT(" "+d[0], 6,".")+" | "+
1386 ARIGHT(" "+(d[2]+5)/10+"ms",10,".")+" "+
1387 ARIGHT(" "+(d[4]+5)/10+"ms",10,".")+" | "+
1388 ARIGHT(" "+d[2]/d[0]+"us",9,".")+" "+
1389 ARIGHT(" "+d[4]/d[0]+"us",9,".");
1390 }
1391 }
1392 str+=implode(sort_array(funcs, "string_compare", ME),"\n")+"\n";
1393 write_file(TMP_FILE,str);
1394 XMoreFile(TMP_FILE, FALSE);
1395 }
1396 else
1397 WDLN("No profiling information available");
1398 }
1399 return TRUE;
1400}
1401
1402int Xprops(string str)
1403{
1404 int i, s, flag;
1405 object obj;
1406 string *tmp;
1407
1408 SECURE2(TRUE);
1409 USAGE2(str, "xprop(s) [-f|-m] <object>");
1410 TK("Xprops: str: "+str);
1411 tmp=old_explode(str," ");
1412 switch(tmp[0])
1413 {
1414 case "-f":
1415 {
1416 flag = 1;
1417 tmp=tmp[1..];
1418 break;
1419 }
1420 case "-m":
1421 {
1422 flag = 2;
1423 tmp=tmp[1..];
1424 break;
1425 }
1426 }
1427 str=implode(tmp," ");
1428 if((obj=XFindObj(str)))
1429 DumpProperties(obj,flag);
1430 return TRUE;
1431}
1432
1433int Xquit(string str)
1434{
1435 SECURE2(TRUE);
1436 USAGE1(str, "xqu(it)");
1437 str=object_name(ENV(cloner));
1438 if(member(str, '#')<0)
1439 cloner->set_home(str);
1440 cloner->quit();
1441 return TRUE;
1442}
1443
1444int Xscan(string str)
1445{
1446 SECURE2(TRUE);
1447 USAGE1(str, "xsc(an)");
1448 W("Destructed variable(s): ");
1449 string* oldvars=m_indices(variable);
1450 VarCheck(FALSE);
1451 string* desvars=oldvars-m_indices(variable);
1452 desvars = map(desvars, function string (string k)
1453 {return "$"+k;} );
1454 W(CountUp(desvars));
1455 WLN("");
1456 return TRUE;
1457}
1458
1459int Xset(string str)
1460{
1461 int i;
1462 mixed obj;
1463 string name, tmp;
1464
1465 SECURE2(TRUE);
1466 USAGE1(str, "xse(t) [$<name>=<object>]");
1467 if(str) {
1468 if(member(({"$me","$m","$here","$h"}),str)!=-1)
1469 WDLN("Sorry, this is a reserved variable ["+str+"]");
1470 else if(sscanf(str, "$%s=%s", name, tmp))
1471 {
1472 if(obj=XFindObj(tmp))
1473 {
1474 variable[name] = obj;
1475 WLN(" $"+name+"="+ObjFile(obj));
1476 }
1477 }
1478 else
1479 return FALSE;
1480 }
1481 else
1482 {
1483 VarCheck(FALSE);
1484 WLN("Current settings:");
1485 foreach(string key, mixed val : variable)
1486 {
1487 if (val)
1488 WLN(" $"+key+"="+ObjFile(val));
1489 else
1490 m_delete(variable, key);
1491 }
1492 WLN(" $me="+ObjFile(cloner));
1493 WLN(" $here="+ObjFile(ENV(cloner)));
1494 }
1495 return TRUE;
1496}
1497
1498int Xsh(string str)
1499{
1500 SECURE2(TRUE);
1501 USAGE1(str, "xsh <filename>");
1502 if(scriptline)
1503 {
1504 WDLN("Cannot execute another script file until last execution has ended");
1505 return TRUE;
1506 }
1507 if(!(str=XFindFile(str)))
1508 return TRUE;
1509 str=read_file(str, 1, 1000);
1510 if(!(scriptline=old_explode(str, "\n")))
1511 {
1512 WDLN("Bad script file");
1513 return TRUE;
1514 }
1515 scriptsize=sizeof(scriptline);
1516 XExecFile(NULL);
1517 return TRUE;
1518}
1519
1520int Xsort(string str)
1521{
1522 string *tmp,file;
1523 int s,reverse;
1524
1525 SECURE2(TRUE);
1526 TK("Xsort: str: "+str);
1527 if(!pipe_in)
1528 {
1529 USAGE2(str, "xso(rt) [-r] [file]");
1530 if(!(tmp=old_explode(str, " "))||(s=sizeof(tmp))>2)
1531 return FALSE;
1532 if(tmp[0]=="-r")
1533 if(s==1)
1534 return FALSE;
1535 else
1536 {
1537 reverse=TRUE;
1538 tmp=tmp[1..];
1539 }
1540 else if(s>1)
1541 return FALSE;
1542 if(!(file=XFindFile(tmp[0])))
1543 {
1544 WDLN("Can't find file");
1545 return TRUE;
1546 }
1547 }
1548 else
1549 {
1550 if(str&&str!="")
1551 if(str=="-r")
1552 reverse=TRUE;
1553 else
1554 USAGE3("xso(rt) [-r]");
1555 if (file_size(file=pipe_if)<0)
1556 {
1557 WDLN("Missing input to xsort");
1558 return TRUE;
1559 }
1560 }
1561 tmp=old_explode(read_file(file,0,PIPE_MAX),"\n");
1562 if(pipe_in&&pipe_if==PIPE_FILE)
1563 rm(PIPE_FILE);
1564 tmp=sort_array(tmp,reverse?#'<:#'>);
1565 if (pipe_out&&pipe_of)
1566 write_file(pipe_of,implode(tmp,"\n")+"\n");
1567 else
1568 WDLN(implode(tmp,"\n"));
1569 return TRUE;
1570}
1571
1572int Xtail(string str)
1573{
1574 string *tmp,file,sign;
1575 int lines;
1576
1577 if (!str) {
1578 WDLN("Missing input to xtail");
1579 return TRUE;
1580 }
1581
1582 sign="-";
1583 lines=10;
1584 SECURE2(TRUE);
1585 TK("Xtail: str: "+str);
1586 if(!pipe_in)
1587 {
1588 if(sscanf(str,"-%d %s",lines,file)==2)
1589 sign="-";
1590 else if(sscanf(str,"+%d %s",lines,file)==2)
1591 sign="+";
1592 else
1593 file=str;
1594
1595 if(!(file=XFindFile(file)))
1596 {
1597 WDLN("Can't find file");
1598 return TRUE;
1599 }
1600 }
1601 else
1602 {
1603 if(sscanf(str,"-%d",lines)==1)
1604 sign="-";
1605 else if(sscanf(str,"+%d",lines)==1)
1606 sign="+";
1607 if (file_size(file=pipe_if)<0)
1608 {
1609 WDLN("Missing input to xtail");
1610 return TRUE;
1611 }
1612 }
1613
1614 if(sign=="-")
1615 {
1616 if(!lines)
1617 return TRUE;
1618 }
1619
1620 if(file_size(file)>50000)
1621 {
1622 WDLN("File too large");
1623 return TRUE;
1624 }
1625
1626 if(sign=="+")
1627 tmp=old_explode(read_file(file,0,PIPE_MAX),"\n")[lines..];
1628 else
1629 tmp=old_explode(read_file(file,0,PIPE_MAX),"\n")[<lines..];
1630 if(pipe_in&&pipe_if==PIPE_FILE)
1631 rm(PIPE_FILE);
1632 if (pipe_out&&pipe_of)
1633 write_file(pipe_of,implode(tmp,"\n")+"\n");
1634 else
1635 WLN(implode(tmp,"\n"));
1636 return TRUE;
1637}
1638
1639int Xtool(string str)
1640{
1641 int m;
1642 string tmp;
1643 object obj;
1644
1645 SECURE2(TRUE);
1646 TK("Xtool: str: "+str);
1647 USAGE1(str, "xto(ol) [update|first=<on|off>|protect=<on|off>|"+
1648 "invcheck=<on|off>|\n"+
1649 "\t\tvarcheck=<on|off>|scanchk=<on|off>|short=<on|off>|\n"+
1650 "\t\techo=<on|off>|more=<amount>|kill|news|save|load|reset]");
1651 if(str&&str!="")
1652 {
1653 if(sscanf(str, "more=%d", m))
1654 {
1655 if(m<5)
1656 WDLN("Sorry, amount of lines should be more then 5");
1657 else
1658 {
1659 WDLN("Setting amount of displayed lines to "+m);
1660 morelines=m;
1661 }
1662 }
1663 else
1664 switch(str)
1665 {
1666 case "update":
1667 if(obj=find_object(TOOL_PATH))
1668 Destruct(obj);
1669 if(catch(obj=clone_object(TOOL_PATH)))
1670 WLN("Updating "+TOOL_TITLE+" failed!");
1671 else
1672 obj->update_tool(AUTOLOAD_ARGS, cloner);
1673 return TRUE;
1674 break;
1675 case "first=on":
1676 MODE_ON(MODE_FIRST);
1677 move(cloner);
1678 WDLN("Automatic moving into pole position of inventory turned on");
1679 break;
1680 case "first=off":
1681 MODE_OFF(MODE_FIRST);
1682 WDLN("Automatic moving into pole position of inventory turned off");
1683 break;
1684 case "protect=on":
1685 MODE_ON(MODE_PROTECT);
1686 WDLN("Protection from forces and illegal moves turned on");
1687 break;
1688 case "protect=off":
1689 MODE_OFF(MODE_PROTECT);
1690 WDLN("Protection from forces and illegal moves turned off");
1691 break;
1692 case "invcheck=on":
1693 MODE_ON(MODE_INVCHECK);
1694 WDLN("Automatic checking for new objects in inventory turned on");
1695 break;
1696 case "invcheck=off":
1697 MODE_OFF(MODE_INVCHECK);
1698 WDLN("Automatic checking for new objects in inventory turned off");
1699 break;
1700 case "varcheck=on":
1701 MODE_ON(MODE_VARCHECK);
1702 VarCheck(TRUE);
1703 WDLN("Automatic variable checking turned on");
1704 break;
1705 case "varcheck=off":
1706 MODE_OFF(MODE_VARCHECK);
1707 WDLN("Automatic variable checking turned off");
1708 break;
1709 case "scanchk=on":
1710 MODE_ON(MODE_SCANCHK);
1711 WDLN("Scan check turned on");
1712 break;
1713 case "scanchk=off":
1714 MODE_OFF(MODE_SCANCHK);
1715 WDLN("Scan check turned off");
1716 break;
1717 case "echo=on":
1718 MODE_ON(MODE_ECHO);
1719 WDLN("Echoing of multiple command execution turned on");
1720 break;
1721 case "echo=off":
1722 MODE_OFF(MODE_ECHO);
1723 WDLN("Echoing of multiple command execution turned off");
1724 break;
1725 case "short=on":
1726 MODE_ON(MODE_SHORT);
1727 WDLN("Use of short descriptions turned on");
1728 break;
1729 case "short=off":
1730 MODE_OFF(MODE_SHORT);
1731 WDLN("Use of short descriptions turned off");
1732 break;
1733 case "kill":
1734 WDLN(TOOL_NAME+" selfdestructs");
1735 destruct(ME);
1736 break;
1737 case "news":
1738 XMoreFile(TOOL_NEWS, FALSE);
1739 break;
1740 case "reset":
1741 WDLN("Resetting "+TOOL_TITLE);
1742 ME->__INIT();
1743 break;
1744 case "load":
1745 if(file_size(SAVE_FILE+".o")>0)
1746 {
1747 WDLN("Loading "+TOOL_TITLE+" settings");
1748 restore_object(SAVE_FILE);
1749 }
1750 else
1751 WDLN("Sorry, cannot find file to load settings");
1752 break;
1753 case "save":
1754 WDLN("Saving "+TOOL_TITLE+" settings");
1755 save_object(SAVE_FILE);
1756 break;
1757 default:
1758 return FALSE;
1759 }
1760 }
1761 else
1762 {
1763 WLN(TOOL_TITLE+" settings:");
1764 tmp= (" first .... = "+(MODE(MODE_FIRST) ? "on\n" : "off\n"));
1765 tmp+=(" protect .. = "+(MODE(MODE_PROTECT) ? "on\n" : "off\n"));
1766 tmp+=(" invcheck . = "+(MODE(MODE_INVCHECK) ? "on\n" : "off\n"));
1767 tmp+=(" varcheck . = "+(MODE(MODE_VARCHECK) ? "on\n" : "off\n"));
1768 tmp+=(" scanchk .. = "+(MODE(MODE_SCANCHK) ? "on\n" : "off\n"));
1769 tmp+=(" echo ..... = "+(MODE(MODE_ECHO) ? "on\n" : "off\n"));
1770 tmp+=(" short .... = "+(MODE(MODE_SHORT) ? "on\n" : "off\n"));
1771 tmp+=(" more ..... = "+morelines);
1772 WLN(sprintf("%-80#s", tmp));
1773 }
1774 return TRUE;
1775}
1776
1777int Xtrace(string str)
1778{
1779 string file;
1780 object obj;
1781
1782 SECURE2(TRUE);
1783 USAGE1(str, "xtrac(e) <object>");
1784 if(!str||str=="")
1785 {
1786 trace(0);
1787 WDLN("Ending trace ["+short_path("/"+traceprefix(0))+"]");
1788 }
1789 else if(obj=XFindObj(str))
1790 {
1791 PrintShort("Tracing: ", obj);
1792 file=object_name(obj);
1793 file=file[1..<1];
1794 traceprefix(file);
1795 trace(TRACE_LEVEL);
1796 }
1797 return TRUE;
1798}
1799
1800int Xtrans(string str)
1801{
1802 object obj;
1803
1804 SECURE2(TRUE);
1805 USAGE2(str, "xtran(s) <object>");
1806 if((obj=XFindObj(str))&&ENV(obj))
1807 {
1808 tell_room(ENV(obj), CRNAME(obj)+" vanishes.\n");
1809 tell_room(ENV(cloner), CRNAME(obj)+
1810 " is teleported into this room by "+CRNAME(cloner)+".\n");
1811 MoveObj(obj, ENV(cloner), TRUE);
1812 tell_object(obj, "You've been teleported to "+CRNAME(cloner)+".\n");
1813 }
1814 else
1815 WDLN("Failed to teleport object");
1816 return TRUE;
1817}
1818
1819int Xupdate(string str)
1820{
1821 object obj;
1822 string file;
1823
1824 SECURE2(TRUE);
1825 USAGE2(str, "xup(date) <filename>");
1826 if(!(file=XFindFile(str)))
1827 return TRUE;
1828 if(file[<2.. <1]==".c")
1829 file=file[0.. <3];
1830 if((obj=XFindObj(file))&&(obj=find_object(pure_file_name(obj))))
1831 {
1832 PrintShort("Updating: ", obj);
1833 Destruct(obj);
1834 }
1835 else
1836 WDLN("Object not found");
1837 return TRUE;
1838}
1839
1840int Xuptime(string str)
1841{
1842 return TRUE;
1843}
1844
1845int Xwc(string str)
1846{
1847 string file;
1848 string tmp, *tmp2;
1849 int i, chars, words, lines, nchars, nwords, nlines;
1850
1851 SECURE2(TRUE);
1852 TK("Xwc: str: "+str);
1853 chars=words=lines=FALSE;
1854 if(!pipe_in)
1855 {
1856 USAGE2(str, "xwc [-cwl] <file>");
1857 if(str[0]=='-')
1858 {
1859 while((str=str[1..])[0]!=' '&&sizeof(str))
1860 switch(str[0])
1861 {
1862 case 'c':
1863 chars=TRUE;
1864 break;
1865 case 'w':
1866 words=TRUE;
1867 break;
1868 case 'l':
1869 lines=TRUE;
1870 break;
1871 default:
1872 return FALSE;
1873 }
1874 str=str[1..];
1875 }
1876 if(!(file=XFindFile(str)))
1877 {
1878 WDLN("Can't find file");
1879 return TRUE;
1880 }
1881 }
1882 else
1883 {
1884 USAGE1(str,"xwc [-cwl]");
1885 if(str)
1886 if(str[0]=='-')
1887 {
1888 while((str=str[1..])[0]!=' '&&sizeof(str))
1889 switch(str[0])
1890 {
1891 case 'c':
1892 chars=TRUE;
1893 break;
1894 case 'w':
1895 words=TRUE;
1896 break;
1897 case 'l':
1898 lines=TRUE;
1899 break;
1900 default:
1901 return FALSE;
1902 }
1903 }
1904 else
1905 return FALSE;
1906 if(file_size(file=pipe_if)<0)
1907 {
1908 WDLN("Missing input to xwc");
1909 return TRUE;
1910 }
1911 }
1912 if(!(chars|words|lines))
1913 chars=words=lines=TRUE;
1914 nlines=nwords=nchars=0;
1915 tmp=read_file(file,0,PIPE_MAX);
1916 tmp2=explode(tmp,"\n");
1917 if(lines)
1918 {
1919 nlines=sizeof(tmp2);
1920 if(tmp2[<1]==""&&nlines>1)
1921 nlines--;
1922 }
1923 if(words)
1924 for(i=sizeof(tmp2)-1;i>=0;i--)
1925 {
1926 TK(sprintf("%O",tmp2[i]));
1927 if(tmp2[i]!="")
1928 nwords+=sizeof(regexplode(tmp2[i],"[ ]")-({""," "," "}));
1929 TK(sprintf("%O",regexplode(tmp2[i],"[ ]")-({""," "," "})));
1930 TK("nwords: "+nwords);
1931 }
1932 if(chars)
1933 for(i=sizeof(tmp2)-1;i>=0;i--)
1934 nchars+=sizeof(tmp2[i])+1;
1935 tmp2=0;
1936 tmp="";
1937 if(lines)
1938 tmp+=sprintf("%7d",nlines)+" ";
1939 if(words)
1940 tmp+=sprintf("%7d",nwords)+" ";
1941 if(chars)
1942 tmp+=sprintf("%7d",nchars)+" ";
1943 if(file!=pipe_if)
1944 tmp+=file;
1945 WLN(tmp);
1946 return TRUE;
1947}
1948
1949int cmdavg_compare(string a, string b)
1950{
1951 int x,y;
1952 string dum;
1953 sscanf(a,"%s cmdavg: %d",dum,x);
1954 sscanf(b,"%s cmdavg: %d",dum,y);
1955 return x==y?0:(x>y?1:-1);
1956}
1957
1958int Xwho(string opt)
1959{
1960 string *strs,str,func;
1961
1962 SECURE2(TRUE);
1963 TK("Xwho: opt: \""+opt+"\"");
1964 USAGE1(opt, "xwh(o) [mail|ip|race|guild|domain|stats|snoop]");
1965 func="string_compare";
1966 if(!opt||opt=="")
1967 strs=map(users(), "PlayerWho", ME);
1968 else
1969 switch(opt)
1970 {
1971 case "mail":
1972 strs=map(users(), "PlayerMail", ME, TRUE);
1973 break;
1974 case "ip":
1975 strs=map(users(), "PlayerIP", ME, TRUE);
1976 break;
1977 case "race":
1978 case "guild":
1979 strs=map(users(), "PlayerRace", ME, TRUE);
1980 break;
1981 case "domain":
1982 strs=map(users(), "PlayerDomain", ME, TRUE);
1983 break;
1984 case "stat":
1985 case "stats":
1986 strs=map(users(), "PlayerStats", ME, TRUE);
1987 break;
1988 case "snoop":
1989 strs=map(users(), "PlayerSnoop", ME, TRUE);
1990 break;
1991 case "cmdavg":
1992 strs=map(users(), "PlayerCmdAvg", ME, TRUE);
1993 func="cmdavg_compare";
1994 break;
1995 default:
1996 return FALSE;
1997 }
1998 strs=sort_array(strs, func, ME);
1999 if(pipe_out&&pipe_of)
2000 write_file(pipe_of,implode(strs,"\n")+"\n");
2001 else
2002 WLN(implode(strs,"\n"));
2003 return TRUE;
2004}