blob: 428ce5cd482d763dac3f90001abcc5aa0360b720 [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{
MG Mud User88f12472016-06-24 23:31:02 +0200414 int i, flags;
415 string *tmp, *tmp2;
Arathorn0a5f4822020-08-27 18:16:44 +0200416 string* args = parseargs(cmdline, &flags, MAN_OPTS, 0);
MG Mud User88f12472016-06-24 23:31:02 +0200417
418 cmdline=_unparsed_args();
MG Mud User88f12472016-06-24 23:31:02 +0200419
420 if (flags==-1 ||
421 (sizeof(args)!=1 &&
422 (sizeof(args)<2 || sizeof(args[1])>1 || !(i=to_int(args[1])))))
423 return USAGE("man [-" MAN_OPTS "] <hilfeseite>");
424 tmp=explode(args[0],"/");
425
426 if (oldman_result && sizeof(tmp)==1 && sizeof(args)==1 &&
427 sizeof(tmp[0])==1 && (i=to_int(tmp[0])) && member(oldman_result,i)) {
428 tmp=({oldman_result[i,0],oldman_result[i,1]});
429 i=0;
430 }
431 else if (!(flags&(MAN_M|MAN_R))&&sizeof(tmp)>1)
432 {
433 if (file_size(MAND_DOCDIR+args[0])>=0)
434 tmp=({tmp[<1],args[0]});
435 else
436 tmp=({});
437 }
438 else
439 {
440 if (flags&MAN_R)
441 {
442 flags&=(~MAN_M);
443 if (catch(regexp(({""}),args[0]))||
444 !regexp(({""}),args[0]))
445 return printf("man: Ungueltiger Ausdruck in Maske.\n"),1;
446 }
Vanion50652322020-03-10 21:13:25 +0100447 tmp=({string *})call_other(MAND,"locate",args[0],flags&(MAN_M|MAN_R));
MG Mud User88f12472016-06-24 23:31:02 +0200448 }
449
Vanion50652322020-03-10 21:13:25 +0100450 oldman_result=0;
MG Mud User88f12472016-06-24 23:31:02 +0200451 if(i && sizeof(tmp)>2 && sizeof(tmp)>=(i<<1))
452 tmp=tmp[((i<<1)-2)..((i<<1)-1)];
453 switch(sizeof(tmp))
454 {
455 case 0:
456 printf("Keine Hilfeseite gefunden fuer '%s'.\n",args[0]);
457 break;
458 case 2:
459 /*
460 if (flags&MAN_I)
461 {
462 // BRANCH TO MANUALD
463 return 1;
464 }
465 */
466 printf("Folgende Hilfeseite wurde gefunden: %s\n",tmp[1]);
467 More(MAND_DOCDIR+tmp[1],1);
468 return 1;
469 default:
470 i=sizeof(tmp)>>1;
471 tmp2=allocate(i);
472 oldman_result=m_allocate(i,2);
473 while(i)
474 {
Arathorndb5d16d2020-05-11 01:23:18 +0200475 tmp2[(i-1)]=tmp[(i<<1)-2];
Zesstraefad7be2018-11-06 23:18:30 +0100476 oldman_result[i,0]=tmp[(i<<1)-2];
477 oldman_result[i,1]=tmp[(i<<1)-1];
MG Mud User88f12472016-06-24 23:31:02 +0200478 i--;
479 }
Arathorndb5d16d2020-05-11 01:23:18 +0200480
481 // Sortierung case-insensitive, ggf. vorhandene Pfade dabei ignorieren
482 tmp2 = sort_array(tmp2, function int (string t1, string t2) {
483 t1 = explode(t1, "/")[<1];
484 t2 = explode(t2, "/")[<1];
485 return lower_case(t1) > lower_case(t2);
486 });
487
488 // Numerierung ergaenzen
489 foreach(int j : sizeof(tmp2)) {
490 tmp2[j] = sprintf("%d: %s", j+1, tmp2[j]);
491 }
492
493 int tty_cols = QueryProp(P_TTY_COLS)-2;
494 string list = "Es wurden die folgenden, potentiell passenden Seiten "
495 "gefunden:\n";
496
497 // Wer keine Grafik sehen will, bekommt eine andere Anzeige.
498 if (QueryProp(P_NO_ASCII_ART)) {
499 // @ als geschuetztes Leerzeichen verwenden, um einen Umbruch
500 // nach den Nummern zu verhindern.
501 tmp2 = map(tmp2, #'regreplace, ": ", ":@", 1);
502 list += break_string(implode(tmp2, " "), tty_cols);
503 list = regreplace(list, ":@", ": ", 1);
504 }
505 else {
506 // Anzahl Spalten ausrechnen: Terminalbreite / Laenge des laengsten
507 // Elements in <tmp2>. Kann der Spaltenmodus von sprintf() an sich
508 // selbst, das liefert aber nicht immer so guenstige Ergebnisse.
509 int maxwidth = max(map(tmp2, #'sizeof));
510 int tablecols = tty_cols/maxwidth;
511 list += "-"*tty_cols+"\n"+
Arathorn2b66ed32020-08-27 00:17:05 +0200512 sprintf("%#-*.*s\n", tty_cols, tablecols, implode(tmp2,"\n"))+
Arathorndb5d16d2020-05-11 01:23:18 +0200513 "-"*tty_cols+"\n";
514 }
515 printf(list);
MG Mud User88f12472016-06-24 23:31:02 +0200516 break;
517 }
518 return 1;
519}
520
521// ########
522//############################### RMAN ##################################
523// ########
524
525static int _rman(string str)
526{
527 int flags;
528 string *args;
529
530 str=_unparsed_args();
531 args=parseargs(str,&flags,"",0);
532 if (flags==-1||sizeof(args)!=2)
533 return USAGE("rman <hilfeseite> <mudname>");
534 write("man: " +
Vanion50652322020-03-10 21:13:25 +0100535 ({string})call_other(UDP_CMD_DIR+"man","send_request",args[1],args[0]));
MG Mud User88f12472016-06-24 23:31:02 +0200536 return 1;
537}
538
539
540// #############
541//############################# SHOWPROPS ###############################
542// #############
543
544//
545// _showprops: Zeigt Properties zu einem Objekt an
546//
547
548static int _showprops(string str)
549{
550 int i;
551 string *list, ausgabe;
552
553 if (str) {
554 if (str[0]!='/') str="/"+str;
555 if (str[0..4]!="/std/")
556 {
557 printf("showprops: Es koennen nur Properties von Objekten "
558 "aus /std/ angezeigt werden.\n");
559 return 1;
560 }
561 if (str[<1]=='.') str+="c";
562 if (str[<2..<1]!=".c") str+=".c";
563 if (file_size(str)<0)
564 {
565 printf("showprops: %s: Es gibt kein Objekt diesen Namens.\n",str[0..<3]);
566 return 1;
567 }
Zesstraefad7be2018-11-06 23:18:30 +0100568 if (catch(load_object(str)))
MG Mud User88f12472016-06-24 23:31:02 +0200569 {
570 printf("showprops: %s: Datei konnte nicht geladen werden.\n",str);
571 return 1;
572 }
573 }
574 if (!str || !find_object(str)) {
575 notify_fail("Welche Properties moechtest Du sehen?"
576 " Bsp.: <showprops /std/npc>\n");
577 return 0;
578 }
579 list=inherit_list(find_object(str));
MG Mud User88f12472016-06-24 23:31:02 +0200580 list=map(list,(: return $1[5..<2]+"h"; :));
581 list+=map(list,(: return explode($1,"/")[<1]; :));
582 list=map(m_indices(mkmapping(list)),(: return "/sys/"+$1; :));
583 list=filter(list,(: return file_size($1)>0; :));
MG Mud User88f12472016-06-24 23:31:02 +0200584 list=sort_array(list, #'<);
585 ausgabe="";
586 for (i=sizeof(list);i--;)
587 {
MG Mud User88f12472016-06-24 23:31:02 +0200588 str=implode(filter(explode(read_file(list[i]),"\n"),
589 (: return $1[0..9]=="#define P_";:)),"\n");
MG Mud User88f12472016-06-24 23:31:02 +0200590 if (str!="") ausgabe+=sprintf("%s\n%s\n\n", list[i], str);
591 }
592 if (ausgabe!="")
593 More(ausgabe);
594 else
595 printf("Keine Property-Definitionen zu diesem Objekt gefunden!\n");
596 return 1;
597}
598
599// ########
600//############################### GREP ###################################
601// ########
602
MG Mud User88f12472016-06-24 23:31:02 +0200603//
604// grep_file: Datei greppen
605// rexpr: Regular Expression
606// flags: Flags
607//
608
609private int grep_file(mixed filedata, string rexpr, int flags)
610{
Zesstrac70bf582019-11-26 00:43:17 +0100611 string fullname=filedata[FULLNAME];
MG Mud User88f12472016-06-24 23:31:02 +0200612 if ((flags&GREP_F)&&fullname=="/players/"+getuid()+"/grep.out")
Zesstraefad7be2018-11-06 23:18:30 +0100613 {
614 write_file("/players/"+getuid()+"/grep.out",
615 "Uebergehe grep.out ...\n");
616 return RET_FAIL;
MG Mud User88f12472016-06-24 23:31:02 +0200617 }
618 switch(filedata[FILESIZE])
619 {
Zesstraefad7be2018-11-06 23:18:30 +0100620 case FSIZE_DIR: return RET_FAIL;
621 case FSIZE_NOFILE: return ERROR(DOESNT_EXIST,fullname,RET_FAIL);
MG Mud User88f12472016-06-24 23:31:02 +0200622 case 0: return RET_FAIL;
623 default: break;
624 }
Zesstraefad7be2018-11-06 23:18:30 +0100625 if (!MAY_READ(fullname))
626 return ERROR(NO_READ,fullname,RET_FAIL);
Zesstrac70bf582019-11-26 00:43:17 +0100627
628 // Bei case-insensitiver Suche das Pattern in Kleinschreibung wandeln
MG Mud User88f12472016-06-24 23:31:02 +0200629 if (flags&GREP_I)
630 rexpr=lower_case(rexpr);
Zesstrac70bf582019-11-26 00:43:17 +0100631
632 // Portionsweise das komplette File einlesen.
633 int maxlen = query_limits()[LIMIT_BYTE];
634 int ptr;
635 bytes read_buffer;
636 bytes data = b"";
637 while (sizeof(read_buffer = read_bytes(fullname, ptr, maxlen)))
MG Mud User88f12472016-06-24 23:31:02 +0200638 {
Zesstrac70bf582019-11-26 00:43:17 +0100639 data += read_buffer;
640 ptr += sizeof(read_buffer);
641 // die Schleifenbedingung erkennt zwar auch, wenn das File vollstaendig
642 // ist, aber wir koennen den Speicherzugriff auch einsparen und schauen,
643 // ob wir schon alles haben.
644 if (ptr >= filedata[FILESIZE])
645 break;
MG Mud User88f12472016-06-24 23:31:02 +0200646 }
Zesstrac70bf582019-11-26 00:43:17 +0100647 // In string konvertieren, wir gehen davon aus, das File ist UTF8-kodiert.
648 string text = to_text(data, "UTF-8");
649 string *lines = explode(text, "\n");
650 int count; // Anzahl Zeilen mit Treffern
651 <string|string*> result = ({}); // zutreffende Zeilen
652 int linecount = 1;
653 foreach(string line: lines)
MG Mud User88f12472016-06-24 23:31:02 +0200654 {
Zesstrac70bf582019-11-26 00:43:17 +0100655 string orig_line = line;
656 // Suche case-insensitive?
657 if (flags&GREP_I)
658 line = lower_case(line);
659 int match = regmatch(line, rexpr) != 0;
660 if (flags&GREP_V) match = !match; // Match ggf. invertieren
MG Mud User88f12472016-06-24 23:31:02 +0200661 if (match)
662 {
Zesstrac70bf582019-11-26 00:43:17 +0100663 // Ausgeben oder nicht?
664 if (!(flags&GREP_C))
MG Mud User88f12472016-06-24 23:31:02 +0200665 {
Zesstrac70bf582019-11-26 00:43:17 +0100666 // Mit Zeilennummer?
667 if (flags&GREP_N)
668 result+=({ sprintf("%4d %s", linecount, orig_line)});
MG Mud User88f12472016-06-24 23:31:02 +0200669 else
Zesstrac70bf582019-11-26 00:43:17 +0100670 result+=({orig_line});
MG Mud User88f12472016-06-24 23:31:02 +0200671 }
Zesstrac70bf582019-11-26 00:43:17 +0100672 ++count;
MG Mud User88f12472016-06-24 23:31:02 +0200673 }
Zesstrac70bf582019-11-26 00:43:17 +0100674 ++linecount;
MG Mud User88f12472016-06-24 23:31:02 +0200675 }
Zesstrac70bf582019-11-26 00:43:17 +0100676
MG Mud User88f12472016-06-24 23:31:02 +0200677 if (count)
678 {
Zesstrac70bf582019-11-26 00:43:17 +0100679 // Bei -h werden die Dateinamen unterdrueckt.
680 if (flags&GREP_H)
681 fullname="";
MG Mud User88f12472016-06-24 23:31:02 +0200682 else
Zesstrac70bf582019-11-26 00:43:17 +0100683 fullname=sprintf("%s ",fullname);
684
685 if (flags&GREP_C)
686 result=sprintf("%s%d passende Zeile%s.\n",fullname, count,
687 (count==1?"":"n"));
688 else
689 result = ( (sizeof(fullname) ? fullname + "\n" : "")
690 + implode(result,"\n") + "\n");
Zesstrac70bf582019-11-26 00:43:17 +0100691
Zesstra77c0bf22020-01-07 22:27:27 +0100692 // Ergebnis ausgeben in File oder an Magier
693 if (flags&GREP_F)
694 return write_file("/players/"+getuid()+"/grep.out",result);
695 write(result);
696 }
MG Mud User88f12472016-06-24 23:31:02 +0200697 return RET_OK;
698}
699
700static int _grep(string cmdline)
701{
702 string rexpr,mask;
703 mixed *args;
704 int flags;
705 cmdline=_unparsed_args();
706 args=parseargs(cmdline,&flags,GREP_OPTS,0);
707 if ((flags==-1)||!sizeof(args))
708 return USAGE("grep [-" GREP_OPTS
709 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
710 rexpr=args[0];
711 if (catch(regexp(({""}),rexpr))||!regexp(({""}),rexpr))
712 return printf("grep: Ungueltiger Suchausdruck: %s\n",rexpr) ,1;
Zesstracc3f2502018-11-14 23:46:47 +0100713 args=(sizeof(args)>1 ? args[1..] : ({}) );
MG Mud User88f12472016-06-24 23:31:02 +0200714 if (flags&GREP_M)
715 {
716 mask=args[<1];
Zesstracc3f2502018-11-14 23:46:47 +0100717 if (sizeof(args) > 2)
718 args = (sizeof(args) > 1 ? args[0..<2] : ({}) );
MG Mud User88f12472016-06-24 23:31:02 +0200719 }
720 if (!sizeof(args))
721 return USAGE("grep [-" GREP_OPTS
722 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
723 args=map(args,#'to_filename)-({0});
MG Mud User88f12472016-06-24 23:31:02 +0200724 args=file_list(args,MODE_GREP,(flags&GREP_R?1:0),"/",mask);
725 if (!sizeof(args))
726 return printf("Keine passenden Dateien gefunden.\n"),1;
727 if (flags&GREP_I) rexpr=lower_case(rexpr);
728 if (flags&GREP_F)
729 {
Zesstraefad7be2018-11-06 23:18:30 +0100730 if (file_size("/players/"+getuid()+"/grep.out")==FSIZE_DIR
731 || !MAY_WRITE("/players/"+getuid()+"/grep.out"))
MG Mud User88f12472016-06-24 23:31:02 +0200732 return printf("grep: Datei /players/%s/grep.out kann nicht "
Zesstraefad7be2018-11-06 23:18:30 +0100733 "geschrieben werden.\n",getuid()),1;
MG Mud User88f12472016-06-24 23:31:02 +0200734 else
735 write_file("/players/"+getuid()+"/grep.out",
736 "Ausgabe von \"grep " + _unparsed_args() + "\":\n");
737 }
738 asynchron(args,#'grep_file,rexpr,flags,0);
739 return 1;
740}