blob: c2d5366f35d13bec86c6697f934ddd02378f75c6 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// fileview.c
4//
5// $Id: fileview.c 9142 2015-02-04 22:17:29Z Zesstra $
Zesstraefad7be2018-11-06 23:18:30 +01006#pragma strict_types, rtt_checks
Zesstra0d64cca2020-03-09 21:03:56 +01007#pragma range_check
MG Mud User88f12472016-06-24 23:31:02 +02008#pragma no_clone
MG Mud User88f12472016-06-24 23:31:02 +02009
10#include <ansi.h>
11#include <player/base.h>
12#include <wizlevels.h>
13#include <shells.h>
14#include <daemon/mand.h>
15#include <udp.h>
Zesstraefad7be2018-11-06 23:18:30 +010016#include <files.h>
Zesstrac70bf582019-11-26 00:43:17 +010017#include <rtlimits.h>
Zesstraefad7be2018-11-06 23:18:30 +010018
MG Mud User88f12472016-06-24 23:31:02 +020019#define NEED_PROTOTYPES
20#include <magier.h>
21#include <thing/properties.h>
22#include <player.h>
23
24private nosave mapping colorstrings;
25private nosave mapping oldman_result;
26
27// ###################
28//######################### INITIALISIERUNG #############################
29// ###################
30
31mixed _query_localcmds()
32{
33 return ({({"ls","_ls",0,LEARNER_LVL}),
34 ({"more","_more",0,LEARNER_LVL}),
35 ({"cat","_cat",0,LEARNER_LVL}),
36 ({"head","_cat",0,LEARNER_LVL}),
37 ({"tail","_cat",0,LEARNER_LVL}),
38 ({"man","_man",0,LEARNER_LVL}),
39 ({"rman","_rman",0,LEARNER_LVL}),
40 ({"showprops","_showprops",0,WIZARD_LVL}),
41 ({"grep","_grep",0,LEARNER_LVL})});
42}
43
44
45// ######
46//################################ LS ###################################
47// ######
48
49//
50// _ls: Der ls-Befehl: Verzeichnisse und Dateien anzeigen
51// cmdline: Kommandozeile
52//
53
54//
55// Funktionen zum Sortieren und fuer filter_ldfied/map_ldfied
56//
57
58
59private string _get_color(string color)
60{
61 return COLORS[lower_case(color)];
62}
63
64
65private void SetColorstrings()
66{
67 string tmp,term;
68 mapping vars;
69 vars=QueryProp(P_VARIABLES);
70 colorstrings=m_allocate(0,2);
71 switch(term=QueryProp(P_TTY))
72 {
73 case "vt100":
74 case "ansi":
75 if(stringp(vars["LS_DIR"]))
76 tmp=implode(map(explode(vars["LS_DIR"],"+"),#'_get_color),
77 "");
78 else
79 tmp = (term == "ansi") ? ANSI_BLUE+ANSI_BOLD: ANSI_BOLD;
80 colorstrings[DIR] = tmp+"%s"+(term == "vt100"?"/":"")+ANSI_NORMAL;
81 if(term == "vt100") colorstrings[DIR, 1] = 1;
82 if(stringp(vars["LS_OBJ"]))
83 tmp=implode(map(explode(vars["LS_OBJ"],"+"),#'_get_color),
84 "");
85 else
86 tmp = (term == "ansi") ? ANSI_RED : ANSI_INVERS;
87 colorstrings[OBJ] = tmp+"%s"+ANSI_NORMAL;
88 if(stringp(vars["LS_VC"]))
89 tmp=implode(map(explode(vars["LS_VC"],"+"),#'_get_color),
90 "");
91 else
92 tmp = (term == "ansi") ? ANSI_PURPLE : ANSI_INVERS;
93 colorstrings[VC] = tmp+"%s"+ANSI_NORMAL;
94 break;
95 case "dumb":
96 colorstrings[DIR] = "%s/"; colorstrings[DIR, 1] = 1;
97 colorstrings[OBJ] = "%s*"; colorstrings[OBJ, 1] = 1;
98 colorstrings[VC] = "%s*"; colorstrings[VC , 1] = 1;
99 break;
100 default:
101 colorstrings[DIR] = "%s";
102 colorstrings[OBJ] = "%s";
103 colorstrings[VC] = "%s";
104 }
105 return;
106}
107
108
109private string _ls_output_short(mixed filedata,
110 int maxlen,int counter,int maxcount)
111{
112 string tmp;
113 tmp=filedata[BASENAME];
114 maxlen-=sizeof(tmp);
115 switch(filedata[FILESIZE])
116 {
Zesstraefad7be2018-11-06 23:18:30 +0100117 case FSIZE_DIR: tmp=sprintf(colorstrings[DIR],tmp);
MG Mud User88f12472016-06-24 23:31:02 +0200118 maxlen-=colorstrings[DIR,1]; break;
Zesstraefad7be2018-11-06 23:18:30 +0100119 case FSIZE_NOFILE: tmp=sprintf(colorstrings[VC],tmp);
MG Mud User88f12472016-06-24 23:31:02 +0200120 maxlen-=colorstrings[VC,1]; break;
121 default: if (find_object(filedata[FULLNAME]))
122 {
123 maxlen-=colorstrings[OBJ,1];
124 tmp=sprintf(colorstrings[OBJ],tmp); break;
125 }
126 }
127 if (!maxcount) return tmp+"\n";
128 return sprintf("%-*s%s",(maxlen+sizeof(tmp)),tmp,
Zesstraefad7be2018-11-06 23:18:30 +0100129 ((counter++)==maxcount?(counter=0,"\n"):" "));
MG Mud User88f12472016-06-24 23:31:02 +0200130}
131
132private int _ls_maxlen(mixed filedata,int flags,int maxlen)
133{
134 string base;
135 int size;
136 base=filedata[BASENAME];
137 if (!(flags&LS_A)&&(base[0]=='.')) return 0;
MG Mud User88f12472016-06-24 23:31:02 +0200138 maxlen=max(maxlen,sizeof(base));
MG Mud User88f12472016-06-24 23:31:02 +0200139 return 1;
140}
141
142private string _ls_output_long(mixed filedata, int flags,closure valid_read,
143 closure valid_write,closure creator_file)
144{
Zesstraefad7be2018-11-06 23:18:30 +0100145 string base=filedata[BASENAME];
146 if (!(sizeof(base)) || ( (!(flags&LS_A)) && (base[0]=='.')) )
MG Mud User88f12472016-06-24 23:31:02 +0200147 return 0;
Zesstraefad7be2018-11-06 23:18:30 +0100148 int size=filedata[FILESIZE];
149 string path=filedata[PATHNAME];
Zesstraf22b6a82018-11-07 22:39:55 +0100150 string full=filedata[FULLNAME];
Zesstraefad7be2018-11-06 23:18:30 +0100151 int dir=(size==FSIZE_DIR);
152 object ob=find_object(full);
153 int ftime=filedata[FILEDATE];
154 string date;
Bugfix59cb0e52019-09-06 15:17:29 +0200155 if ((time()-ftime)>31536000) // ein Jahr
Zesstraefad7be2018-11-06 23:18:30 +0100156 date=strftime("%b %e %Y", ftime);
157 else
158 date=strftime("%b %e %H:%M", ftime);
159
160 string creator="";
161 string group="";
MG Mud User88f12472016-06-24 23:31:02 +0200162 if (flags&LS_U)
163 {
Vanion50652322020-03-10 21:13:25 +0100164 creator=({string})call_other(master(),"creator_file", full);
MG Mud User88f12472016-06-24 23:31:02 +0200165 switch(creator)
166 {
167 case ROOTID: creator="root"; break;
Zesstraefad7be2018-11-06 23:18:30 +0100168 case BACKBONEID: creator="std"; break;
169 case MAILID: creator="mail"; break;
170 case NEWSID: creator="news"; break;
171 case NOBODY: creator="nobody"; break;
172 case POLIZEIID: creator="polizei"; break;
173 case DOCID: creator="doc"; break;
174 case GUILDID: creator="gilde"; break;
175 case ITEMID: creator="items"; break;
MG Mud User88f12472016-06-24 23:31:02 +0200176 default: if(!creator) creator="none"; break;
177 }
178 }
179 if (flags&LS_G)
180 {
Zesstraf22b6a82018-11-07 22:39:55 +0100181 string *tmp=explode(path, "/") - ({""});
MG Mud User88f12472016-06-24 23:31:02 +0200182 if (sizeof(tmp))
183 {
184 switch(tmp[0])
185 {
186 case WIZARDDIR: group="magier"; break;
Zesstraefad7be2018-11-06 23:18:30 +0100187 case NEWSDIR: group="news"; break;
188 case MAILDIR: group="mail"; break;
189 case FTPDIR: group="public"; break;
190 case PROJECTDIR: group="project"; break;
MG Mud User88f12472016-06-24 23:31:02 +0200191 case DOMAINDIR: if (sizeof(tmp)>1) { group=tmp[1]; break; }
192 default: group="mud"; break;
193 }
194 }
195 else group="mud";
196 }
197 if (dir) base=sprintf(colorstrings[DIR],base);
198 else
199 {
200 if (ob)
201 {
Zesstraefad7be2018-11-06 23:18:30 +0100202 if (size==FSIZE_NOFILE)
MG Mud User88f12472016-06-24 23:31:02 +0200203 base=sprintf(colorstrings[VC],base);
204 else
205 base=sprintf(colorstrings[OBJ],base);
206 }
207 }
Zesstraefad7be2018-11-06 23:18:30 +0100208 return sprintf(("%c%c%c%c %3d" + ((flags&LS_U) ? " %-24.24s" : "%-0.1s")
209 +((flags&LS_G) ? " %-8.8s" : "%0.1s") + " %8s %s %s\n"),
210 (dir ? 'd' : '-'),
MG Mud User88f12472016-06-24 23:31:02 +0200211 (!funcall(valid_read,full,getuid(),
Zesstraefad7be2018-11-06 23:18:30 +0100212 "read_file",this_object()) ? '-' : 'r'),
MG Mud User88f12472016-06-24 23:31:02 +0200213 (!funcall(valid_write,full,getuid(),
Zesstraefad7be2018-11-06 23:18:30 +0100214 "write_file",this_object()) ? '-' : 'w'),
215 (ob ? 'x' : '-'),
216 (dir ? (sizeof((get_dir(full+"/*")||({}))-({".",".."}))) : 0),
217 creator, group,
218 (dir ? "-" : size==FSIZE_NOFILE ? "<vc>" : to_string(size)),
219 date, base);
MG Mud User88f12472016-06-24 23:31:02 +0200220}
221
222
223static int _ls(string cmdline)
224{
225 int flags,cmp,i,arg_size,size;
226 int maxlen,counter,maxcount;
Arathorna8ae8662019-11-25 19:01:19 +0100227 mixed* args;
228 string output;
MG Mud User88f12472016-06-24 23:31:02 +0200229 mixed *tmp;
230 closure output_fun,v_read,v_write,creator,sort_fun;
231
232 cmdline=_unparsed_args()||"";
233 args=parseargs(cmdline,&flags,LS_OPTS,1);
234 if (flags==-1)
235 return USAGE("ls [-" LS_OPTS "] [<Verzeichnis>] [<Verzeichnis2> ..]");
236 SetColorstrings();
237 output="";
238 if (!sizeof(args)) args=({ QueryProp(P_CURRENTDIR) });
239 if (!sizeof(args=file_list(args,MODE_LSA,0,"/")))
240 return notify_fail("ls: Keine passenden Verzeichnisse gefunden.\n"), 0;
241// Files sortieren die erste
242 if (flags&LS_T) cmp=FILEDATE;
243 else if (flags&LS_S) cmp=FILESIZE;
244 else cmp=BASENAME; // =0 :-)
Arathorn06b52922018-11-26 20:47:10 +0100245
246 if ( !cmp && !(flags&LS_R) || cmp && (flags&LS_R) )
247 sort_fun = function int (mixed* a, mixed* b) {
248 return (a[cmp] > b[cmp]);
249 };
250 else
251 sort_fun = function int (mixed* a, mixed* b) {
252 return (a[cmp] < b[cmp]);
253 };
MG Mud User88f12472016-06-24 23:31:02 +0200254 args=sort_array(args,sort_fun);
255// Ausgabeformat bestimmen
256 if (flags&LS_L)
257 {
258 v_read=VALID_READ_CL;
259 v_write=VALID_WRITE_CL;
260 creator=CREATOR_CL;
261 }
262 arg_size=sizeof(args);
263 if (arg_size>1||(arg_size&&args[0][FILESIZE]>=0))
264 {
265 if (flags&LS_L)
266 tmp=map(args,#'_ls_output_long,flags,v_read,
267 v_write,creator)-({0});
268 else
269 {
270 counter=0;maxlen=0;
271 tmp=filter(args,#'_ls_maxlen,flags,&maxlen);
272 if (maxlen>76) maxlen=76;
273 maxcount=(78/(maxlen+2))-1;
274 tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
275 }
276 output=sprintf("\n%d Dateien/Unterverzeichnisse:\n%s\n",
277 sizeof(tmp),implode(tmp,""));
278 }
279 for(i=0;i<arg_size;i++)
280 {
281 tmp=({});
282 size=args[i][FILESIZE];
Zesstraefad7be2018-11-06 23:18:30 +0100283 if (size==FSIZE_DIR)
MG Mud User88f12472016-06-24 23:31:02 +0200284 {
285 tmp=file_list(({args[i][FULLNAME]+"/*"}),MODE_LSB,0,"/");
286 tmp=sort_array(tmp,sort_fun);
287 if (flags&LS_L)
288 tmp=map(tmp,#'_ls_output_long,flags,v_read,
289 v_write,creator)-({0});
290 else
291 {
292 counter=0;maxlen=0;
293 tmp=filter(tmp,#'_ls_maxlen,flags,&maxlen);
294 maxcount=(78/(maxlen+2));
295 if (maxcount) maxcount--;
296 tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
297 }
298 if (sizeof(tmp))
299 {
300 output+=sprintf("\n%s: Verzeichnis, %d Dateien/Unterverzeichnisse:\n",
301 args[i][FULLNAME],sizeof(tmp));
302 output+=(implode(tmp,"")+((string)(tmp[<1][<1..<1])=="\n"?"":"\n"));
303 }
304 else
305 {
306 output+=sprintf("\n%s: Leeres Verzeichnis.\n",args[i][FULLNAME]);
307 }
308 }
309 }
310 More(output);
311 return 1;
312}
313
314// ########
315//############################### MORE ###################################
316// ########
317//
318// _more_file: Mehrere Files hintereinander ausgeben
319//
320
321private void _more_file(string *arg)
322{
323 if (!sizeof(arg)) return;
324 printf("more: Naechste Datei: %s\n",arg[0]);
Zesstra3de3a032018-11-08 19:17:03 +0100325 More(arg[0],1,#'_more_file,
326 (sizeof(arg)>1 ? ({ arg[1..]}) : ({})) );
MG Mud User88f12472016-06-24 23:31:02 +0200327 return;
328}
329
330
331private mixed _size_filter(mixed *arg)
332{
333 if (arg[FILESIZE]>0) return arg[FULLNAME];
334 if (arg[FILESIZE]==0)
335 {
336 printf("%s: %s: Leere Datei.\n",query_verb()||"more",arg[FULLNAME]);
337 return 0;
338 }
Zesstraefad7be2018-11-06 23:18:30 +0100339 if (arg[FILESIZE]==FSIZE_DIR)
MG Mud User88f12472016-06-24 23:31:02 +0200340 printf("%s: %s ist ein Verzeichnis.\n",query_verb()||"more",arg[FULLNAME]);
341 else
342 printf("%s: %s: Datei existiert nicht.\n", query_verb()||"more",
343 arg[FULLNAME]);
344 return 0;
345}
346
347
348//
349// _more: Dateien anzeigen
350// cmdline: Kommandozeile
351//
352
353static int _more(string cmdline)
354{
355 mixed *args;
356 int flags;
357 cmdline=_unparsed_args();
358 args=parseargs(cmdline,&flags,"",1);
359 if (flags==-1||!sizeof(args)) return USAGE("more <datei> [<datei2>..]");
360 args=file_list(args,MODE_MORE,0,"/");
361 if (!sizeof(args))
362 return printf("more: %s: Keine passende Datei gefunden.\n",cmdline),1;
363 args=map(args,#'_size_filter)-({0});
364 if (sizeof(args)) _more_file(args);
365 return 1;
366}
367
368// ###################
369//########################## HEAD, TAIL, CAT #############################
370// ###################
371
372static int _cat(string cmdline)
373{
374 mixed *args;
375 int flags;
376 cmdline=_unparsed_args();
377 args=parseargs(cmdline,&flags,"",1);
378 if(flags==-1||!sizeof(args))
379 return USAGE(query_verb()+" <dateiname> [<datei2>..]");
380 args=file_list(args,MODE_CAT,0,"/");
381 if (!sizeof(args))
382 return printf("%s: %s: Keine passende Datei gefunden.\n",query_verb(),
383 cmdline),1;
384 args=map(args,#'_size_filter)-({0});
385 if (!sizeof(args)) return 1;
386 while(sizeof(args))
387 {
388 switch(query_verb())
389 {
390 case "cat":
391 if (!cat(args[0]))
392 printf("cat: %s konnte nicht angezeigt werden.\n",args[0]);
393 break;
394 case "head":
395 if (!cat(args[0],0,10))
396 printf("head: %s konnte nicht angezeigt werden.\n",args[0]);
397 break;
398 case "tail": tail(args[0]); break;
399 }
Zesstra3de3a032018-11-08 19:17:03 +0100400 if (sizeof(args) > 1)
401 args=args[1..];
402 else
403 break;
MG Mud User88f12472016-06-24 23:31:02 +0200404 }
405 return 1;
406}
407
408// #######
409//############################### MAN ###################################
410// #######
411
412static int _man(string cmdline)
413{
414 mixed *args;
415 int i, flags;
416 string *tmp, *tmp2;
417
418 cmdline=_unparsed_args();
419 args=parseargs(cmdline,&flags,MAN_OPTS,0);
420
421 if (flags==-1 ||
422 (sizeof(args)!=1 &&
423 (sizeof(args)<2 || sizeof(args[1])>1 || !(i=to_int(args[1])))))
424 return USAGE("man [-" MAN_OPTS "] <hilfeseite>");
425 tmp=explode(args[0],"/");
426
427 if (oldman_result && sizeof(tmp)==1 && sizeof(args)==1 &&
428 sizeof(tmp[0])==1 && (i=to_int(tmp[0])) && member(oldman_result,i)) {
429 tmp=({oldman_result[i,0],oldman_result[i,1]});
430 i=0;
431 }
432 else if (!(flags&(MAN_M|MAN_R))&&sizeof(tmp)>1)
433 {
434 if (file_size(MAND_DOCDIR+args[0])>=0)
435 tmp=({tmp[<1],args[0]});
436 else
437 tmp=({});
438 }
439 else
440 {
441 if (flags&MAN_R)
442 {
443 flags&=(~MAN_M);
444 if (catch(regexp(({""}),args[0]))||
445 !regexp(({""}),args[0]))
446 return printf("man: Ungueltiger Ausdruck in Maske.\n"),1;
447 }
Vanion50652322020-03-10 21:13:25 +0100448 tmp=({string *})call_other(MAND,"locate",args[0],flags&(MAN_M|MAN_R));
MG Mud User88f12472016-06-24 23:31:02 +0200449 }
450
Vanion50652322020-03-10 21:13:25 +0100451 oldman_result=0;
MG Mud User88f12472016-06-24 23:31:02 +0200452 if(i && sizeof(tmp)>2 && sizeof(tmp)>=(i<<1))
453 tmp=tmp[((i<<1)-2)..((i<<1)-1)];
454 switch(sizeof(tmp))
455 {
456 case 0:
457 printf("Keine Hilfeseite gefunden fuer '%s'.\n",args[0]);
458 break;
459 case 2:
460 /*
461 if (flags&MAN_I)
462 {
463 // BRANCH TO MANUALD
464 return 1;
465 }
466 */
467 printf("Folgende Hilfeseite wurde gefunden: %s\n",tmp[1]);
468 More(MAND_DOCDIR+tmp[1],1);
469 return 1;
470 default:
471 i=sizeof(tmp)>>1;
472 tmp2=allocate(i);
473 oldman_result=m_allocate(i,2);
474 while(i)
475 {
Arathorndb5d16d2020-05-11 01:23:18 +0200476 tmp2[(i-1)]=tmp[(i<<1)-2];
Zesstraefad7be2018-11-06 23:18:30 +0100477 oldman_result[i,0]=tmp[(i<<1)-2];
478 oldman_result[i,1]=tmp[(i<<1)-1];
MG Mud User88f12472016-06-24 23:31:02 +0200479 i--;
480 }
Arathorndb5d16d2020-05-11 01:23:18 +0200481
482 // Sortierung case-insensitive, ggf. vorhandene Pfade dabei ignorieren
483 tmp2 = sort_array(tmp2, function int (string t1, string t2) {
484 t1 = explode(t1, "/")[<1];
485 t2 = explode(t2, "/")[<1];
486 return lower_case(t1) > lower_case(t2);
487 });
488
489 // Numerierung ergaenzen
490 foreach(int j : sizeof(tmp2)) {
491 tmp2[j] = sprintf("%d: %s", j+1, tmp2[j]);
492 }
493
494 int tty_cols = QueryProp(P_TTY_COLS)-2;
495 string list = "Es wurden die folgenden, potentiell passenden Seiten "
496 "gefunden:\n";
497
498 // Wer keine Grafik sehen will, bekommt eine andere Anzeige.
499 if (QueryProp(P_NO_ASCII_ART)) {
500 // @ als geschuetztes Leerzeichen verwenden, um einen Umbruch
501 // nach den Nummern zu verhindern.
502 tmp2 = map(tmp2, #'regreplace, ": ", ":@", 1);
503 list += break_string(implode(tmp2, " "), tty_cols);
504 list = regreplace(list, ":@", ": ", 1);
505 }
506 else {
507 // Anzahl Spalten ausrechnen: Terminalbreite / Laenge des laengsten
508 // Elements in <tmp2>. Kann der Spaltenmodus von sprintf() an sich
509 // selbst, das liefert aber nicht immer so guenstige Ergebnisse.
510 int maxwidth = max(map(tmp2, #'sizeof));
511 int tablecols = tty_cols/maxwidth;
512 list += "-"*tty_cols+"\n"+
Arathorn2b66ed32020-08-27 00:17:05 +0200513 sprintf("%#-*.*s\n", tty_cols, tablecols, implode(tmp2,"\n"))+
Arathorndb5d16d2020-05-11 01:23:18 +0200514 "-"*tty_cols+"\n";
515 }
516 printf(list);
MG Mud User88f12472016-06-24 23:31:02 +0200517 break;
518 }
519 return 1;
520}
521
522// ########
523//############################### RMAN ##################################
524// ########
525
526static int _rman(string str)
527{
528 int flags;
529 string *args;
530
531 str=_unparsed_args();
532 args=parseargs(str,&flags,"",0);
533 if (flags==-1||sizeof(args)!=2)
534 return USAGE("rman <hilfeseite> <mudname>");
535 write("man: " +
Vanion50652322020-03-10 21:13:25 +0100536 ({string})call_other(UDP_CMD_DIR+"man","send_request",args[1],args[0]));
MG Mud User88f12472016-06-24 23:31:02 +0200537 return 1;
538}
539
540
541// #############
542//############################# SHOWPROPS ###############################
543// #############
544
545//
546// _showprops: Zeigt Properties zu einem Objekt an
547//
548
549static int _showprops(string str)
550{
551 int i;
552 string *list, ausgabe;
553
554 if (str) {
555 if (str[0]!='/') str="/"+str;
556 if (str[0..4]!="/std/")
557 {
558 printf("showprops: Es koennen nur Properties von Objekten "
559 "aus /std/ angezeigt werden.\n");
560 return 1;
561 }
562 if (str[<1]=='.') str+="c";
563 if (str[<2..<1]!=".c") str+=".c";
564 if (file_size(str)<0)
565 {
566 printf("showprops: %s: Es gibt kein Objekt diesen Namens.\n",str[0..<3]);
567 return 1;
568 }
Zesstraefad7be2018-11-06 23:18:30 +0100569 if (catch(load_object(str)))
MG Mud User88f12472016-06-24 23:31:02 +0200570 {
571 printf("showprops: %s: Datei konnte nicht geladen werden.\n",str);
572 return 1;
573 }
574 }
575 if (!str || !find_object(str)) {
576 notify_fail("Welche Properties moechtest Du sehen?"
577 " Bsp.: <showprops /std/npc>\n");
578 return 0;
579 }
580 list=inherit_list(find_object(str));
MG Mud User88f12472016-06-24 23:31:02 +0200581 list=map(list,(: return $1[5..<2]+"h"; :));
582 list+=map(list,(: return explode($1,"/")[<1]; :));
583 list=map(m_indices(mkmapping(list)),(: return "/sys/"+$1; :));
584 list=filter(list,(: return file_size($1)>0; :));
MG Mud User88f12472016-06-24 23:31:02 +0200585 list=sort_array(list, #'<);
586 ausgabe="";
587 for (i=sizeof(list);i--;)
588 {
MG Mud User88f12472016-06-24 23:31:02 +0200589 str=implode(filter(explode(read_file(list[i]),"\n"),
590 (: return $1[0..9]=="#define P_";:)),"\n");
MG Mud User88f12472016-06-24 23:31:02 +0200591 if (str!="") ausgabe+=sprintf("%s\n%s\n\n", list[i], str);
592 }
593 if (ausgabe!="")
594 More(ausgabe);
595 else
596 printf("Keine Property-Definitionen zu diesem Objekt gefunden!\n");
597 return 1;
598}
599
600// ########
601//############################### GREP ###################################
602// ########
603
MG Mud User88f12472016-06-24 23:31:02 +0200604//
605// grep_file: Datei greppen
606// rexpr: Regular Expression
607// flags: Flags
608//
609
610private int grep_file(mixed filedata, string rexpr, int flags)
611{
Zesstrac70bf582019-11-26 00:43:17 +0100612 string fullname=filedata[FULLNAME];
MG Mud User88f12472016-06-24 23:31:02 +0200613 if ((flags&GREP_F)&&fullname=="/players/"+getuid()+"/grep.out")
Zesstraefad7be2018-11-06 23:18:30 +0100614 {
615 write_file("/players/"+getuid()+"/grep.out",
616 "Uebergehe grep.out ...\n");
617 return RET_FAIL;
MG Mud User88f12472016-06-24 23:31:02 +0200618 }
619 switch(filedata[FILESIZE])
620 {
Zesstraefad7be2018-11-06 23:18:30 +0100621 case FSIZE_DIR: return RET_FAIL;
622 case FSIZE_NOFILE: return ERROR(DOESNT_EXIST,fullname,RET_FAIL);
MG Mud User88f12472016-06-24 23:31:02 +0200623 case 0: return RET_FAIL;
624 default: break;
625 }
Zesstraefad7be2018-11-06 23:18:30 +0100626 if (!MAY_READ(fullname))
627 return ERROR(NO_READ,fullname,RET_FAIL);
Zesstrac70bf582019-11-26 00:43:17 +0100628
629 // Bei case-insensitiver Suche das Pattern in Kleinschreibung wandeln
MG Mud User88f12472016-06-24 23:31:02 +0200630 if (flags&GREP_I)
631 rexpr=lower_case(rexpr);
Zesstrac70bf582019-11-26 00:43:17 +0100632
633 // Portionsweise das komplette File einlesen.
634 int maxlen = query_limits()[LIMIT_BYTE];
635 int ptr;
636 bytes read_buffer;
637 bytes data = b"";
638 while (sizeof(read_buffer = read_bytes(fullname, ptr, maxlen)))
MG Mud User88f12472016-06-24 23:31:02 +0200639 {
Zesstrac70bf582019-11-26 00:43:17 +0100640 data += read_buffer;
641 ptr += sizeof(read_buffer);
642 // die Schleifenbedingung erkennt zwar auch, wenn das File vollstaendig
643 // ist, aber wir koennen den Speicherzugriff auch einsparen und schauen,
644 // ob wir schon alles haben.
645 if (ptr >= filedata[FILESIZE])
646 break;
MG Mud User88f12472016-06-24 23:31:02 +0200647 }
Zesstrac70bf582019-11-26 00:43:17 +0100648 // In string konvertieren, wir gehen davon aus, das File ist UTF8-kodiert.
649 string text = to_text(data, "UTF-8");
650 string *lines = explode(text, "\n");
651 int count; // Anzahl Zeilen mit Treffern
652 <string|string*> result = ({}); // zutreffende Zeilen
653 int linecount = 1;
654 foreach(string line: lines)
MG Mud User88f12472016-06-24 23:31:02 +0200655 {
Zesstrac70bf582019-11-26 00:43:17 +0100656 string orig_line = line;
657 // Suche case-insensitive?
658 if (flags&GREP_I)
659 line = lower_case(line);
660 int match = regmatch(line, rexpr) != 0;
661 if (flags&GREP_V) match = !match; // Match ggf. invertieren
MG Mud User88f12472016-06-24 23:31:02 +0200662 if (match)
663 {
Zesstrac70bf582019-11-26 00:43:17 +0100664 // Ausgeben oder nicht?
665 if (!(flags&GREP_C))
MG Mud User88f12472016-06-24 23:31:02 +0200666 {
Zesstrac70bf582019-11-26 00:43:17 +0100667 // Mit Zeilennummer?
668 if (flags&GREP_N)
669 result+=({ sprintf("%4d %s", linecount, orig_line)});
MG Mud User88f12472016-06-24 23:31:02 +0200670 else
Zesstrac70bf582019-11-26 00:43:17 +0100671 result+=({orig_line});
MG Mud User88f12472016-06-24 23:31:02 +0200672 }
Zesstrac70bf582019-11-26 00:43:17 +0100673 ++count;
MG Mud User88f12472016-06-24 23:31:02 +0200674 }
Zesstrac70bf582019-11-26 00:43:17 +0100675 ++linecount;
MG Mud User88f12472016-06-24 23:31:02 +0200676 }
Zesstrac70bf582019-11-26 00:43:17 +0100677
MG Mud User88f12472016-06-24 23:31:02 +0200678 if (count)
679 {
Zesstrac70bf582019-11-26 00:43:17 +0100680 // Bei -h werden die Dateinamen unterdrueckt.
681 if (flags&GREP_H)
682 fullname="";
MG Mud User88f12472016-06-24 23:31:02 +0200683 else
Zesstrac70bf582019-11-26 00:43:17 +0100684 fullname=sprintf("%s ",fullname);
685
686 if (flags&GREP_C)
687 result=sprintf("%s%d passende Zeile%s.\n",fullname, count,
688 (count==1?"":"n"));
689 else
690 result = ( (sizeof(fullname) ? fullname + "\n" : "")
691 + implode(result,"\n") + "\n");
Zesstrac70bf582019-11-26 00:43:17 +0100692
Zesstra77c0bf22020-01-07 22:27:27 +0100693 // Ergebnis ausgeben in File oder an Magier
694 if (flags&GREP_F)
695 return write_file("/players/"+getuid()+"/grep.out",result);
696 write(result);
697 }
MG Mud User88f12472016-06-24 23:31:02 +0200698 return RET_OK;
699}
700
701static int _grep(string cmdline)
702{
703 string rexpr,mask;
704 mixed *args;
705 int flags;
706 cmdline=_unparsed_args();
707 args=parseargs(cmdline,&flags,GREP_OPTS,0);
708 if ((flags==-1)||!sizeof(args))
709 return USAGE("grep [-" GREP_OPTS
710 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
711 rexpr=args[0];
712 if (catch(regexp(({""}),rexpr))||!regexp(({""}),rexpr))
713 return printf("grep: Ungueltiger Suchausdruck: %s\n",rexpr) ,1;
Zesstracc3f2502018-11-14 23:46:47 +0100714 args=(sizeof(args)>1 ? args[1..] : ({}) );
MG Mud User88f12472016-06-24 23:31:02 +0200715 if (flags&GREP_M)
716 {
717 mask=args[<1];
Zesstracc3f2502018-11-14 23:46:47 +0100718 if (sizeof(args) > 2)
719 args = (sizeof(args) > 1 ? args[0..<2] : ({}) );
MG Mud User88f12472016-06-24 23:31:02 +0200720 }
721 if (!sizeof(args))
722 return USAGE("grep [-" GREP_OPTS
723 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
724 args=map(args,#'to_filename)-({0});
MG Mud User88f12472016-06-24 23:31:02 +0200725 args=file_list(args,MODE_GREP,(flags&GREP_R?1:0),"/",mask);
726 if (!sizeof(args))
727 return printf("Keine passenden Dateien gefunden.\n"),1;
728 if (flags&GREP_I) rexpr=lower_case(rexpr);
729 if (flags&GREP_F)
730 {
Zesstraefad7be2018-11-06 23:18:30 +0100731 if (file_size("/players/"+getuid()+"/grep.out")==FSIZE_DIR
732 || !MAY_WRITE("/players/"+getuid()+"/grep.out"))
MG Mud User88f12472016-06-24 23:31:02 +0200733 return printf("grep: Datei /players/%s/grep.out kann nicht "
Zesstraefad7be2018-11-06 23:18:30 +0100734 "geschrieben werden.\n",getuid()),1;
MG Mud User88f12472016-06-24 23:31:02 +0200735 else
736 write_file("/players/"+getuid()+"/grep.out",
737 "Ausgabe von \"grep " + _unparsed_args() + "\":\n");
738 }
739 asynchron(args,#'grep_file,rexpr,flags,0);
740 return 1;
741}