blob: 731de5a15106dcbda368f75861ca8ff7b49eff3b [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 $
6#pragma strict_types
7#pragma save_types
8//#pragma range_check
9#pragma no_clone
10#pragma pedantic
11
12#include <ansi.h>
13#include <player/base.h>
14#include <wizlevels.h>
15#include <shells.h>
16#include <daemon/mand.h>
17#include <udp.h>
18#define NEED_PROTOTYPES
19#include <magier.h>
20#include <thing/properties.h>
21#include <player.h>
22
23private nosave mapping colorstrings;
24private nosave mapping oldman_result;
25
26// ###################
27//######################### INITIALISIERUNG #############################
28// ###################
29
30mixed _query_localcmds()
31{
32 return ({({"ls","_ls",0,LEARNER_LVL}),
33 ({"more","_more",0,LEARNER_LVL}),
34 ({"cat","_cat",0,LEARNER_LVL}),
35 ({"head","_cat",0,LEARNER_LVL}),
36 ({"tail","_cat",0,LEARNER_LVL}),
37 ({"man","_man",0,LEARNER_LVL}),
38 ({"rman","_rman",0,LEARNER_LVL}),
39 ({"showprops","_showprops",0,WIZARD_LVL}),
40 ({"grep","_grep",0,LEARNER_LVL})});
41}
42
43
44// ######
45//################################ LS ###################################
46// ######
47
48//
49// _ls: Der ls-Befehl: Verzeichnisse und Dateien anzeigen
50// cmdline: Kommandozeile
51//
52
53//
54// Funktionen zum Sortieren und fuer filter_ldfied/map_ldfied
55//
56
57
58private string _get_color(string color)
59{
60 return COLORS[lower_case(color)];
61}
62
63
64private void SetColorstrings()
65{
66 string tmp,term;
67 mapping vars;
68 vars=QueryProp(P_VARIABLES);
69 colorstrings=m_allocate(0,2);
70 switch(term=QueryProp(P_TTY))
71 {
72 case "vt100":
73 case "ansi":
74 if(stringp(vars["LS_DIR"]))
75 tmp=implode(map(explode(vars["LS_DIR"],"+"),#'_get_color),
76 "");
77 else
78 tmp = (term == "ansi") ? ANSI_BLUE+ANSI_BOLD: ANSI_BOLD;
79 colorstrings[DIR] = tmp+"%s"+(term == "vt100"?"/":"")+ANSI_NORMAL;
80 if(term == "vt100") colorstrings[DIR, 1] = 1;
81 if(stringp(vars["LS_OBJ"]))
82 tmp=implode(map(explode(vars["LS_OBJ"],"+"),#'_get_color),
83 "");
84 else
85 tmp = (term == "ansi") ? ANSI_RED : ANSI_INVERS;
86 colorstrings[OBJ] = tmp+"%s"+ANSI_NORMAL;
87 if(stringp(vars["LS_VC"]))
88 tmp=implode(map(explode(vars["LS_VC"],"+"),#'_get_color),
89 "");
90 else
91 tmp = (term == "ansi") ? ANSI_PURPLE : ANSI_INVERS;
92 colorstrings[VC] = tmp+"%s"+ANSI_NORMAL;
93 break;
94 case "dumb":
95 colorstrings[DIR] = "%s/"; colorstrings[DIR, 1] = 1;
96 colorstrings[OBJ] = "%s*"; colorstrings[OBJ, 1] = 1;
97 colorstrings[VC] = "%s*"; colorstrings[VC , 1] = 1;
98 break;
99 default:
100 colorstrings[DIR] = "%s";
101 colorstrings[OBJ] = "%s";
102 colorstrings[VC] = "%s";
103 }
104 return;
105}
106
107
108private string _ls_output_short(mixed filedata,
109 int maxlen,int counter,int maxcount)
110{
111 string tmp;
112 tmp=filedata[BASENAME];
113 maxlen-=sizeof(tmp);
114 switch(filedata[FILESIZE])
115 {
116 case -2: tmp=sprintf(colorstrings[DIR],tmp);
117 maxlen-=colorstrings[DIR,1]; break;
118 case -1: tmp=sprintf(colorstrings[VC],tmp);
119 maxlen-=colorstrings[VC,1]; break;
120 default: if (find_object(filedata[FULLNAME]))
121 {
122 maxlen-=colorstrings[OBJ,1];
123 tmp=sprintf(colorstrings[OBJ],tmp); break;
124 }
125 }
126 if (!maxcount) return tmp+"\n";
127 return sprintf("%-*s%s",(maxlen+sizeof(tmp)),tmp,
128 ((counter++)==maxcount?(counter=0,"\n"):" "));
129}
130
131private int _ls_maxlen(mixed filedata,int flags,int maxlen)
132{
133 string base;
134 int size;
135 base=filedata[BASENAME];
136 if (!(flags&LS_A)&&(base[0]=='.')) return 0;
137#if __VERSION__ < "3.2.9"
138 if (sizeof(base)>maxlen) maxlen=sizeof(base);
139#else
140 maxlen=max(maxlen,sizeof(base));
141#endif
142 return 1;
143}
144
145private string _ls_output_long(mixed filedata, int flags,closure valid_read,
146 closure valid_write,closure creator_file)
147{
148 string *tmp,full,base,path,date,creator,group;
149 int size,dir,ftime;
150 object ob;
151
152 base=filedata[BASENAME];
153 if (!(sizeof(base))||((!(flags&LS_A))&&(base[0]=='.')))
154 return 0;
155 size=filedata[FILESIZE];
156 path=filedata[PATHNAME];
157 tmp=(string *)call_other(master(),"full_path_array",
158 filedata[FULLNAME],getuid());
159 full=sprintf("/%s",implode(tmp,"/"));
160 dir=(size==-2);
161 ob=find_object(full);
162 ftime=filedata[FILEDATE];
163 date=dtime(ftime);
164 date=sprintf("%s %s %s",date[9..11],date[5..6],
165 ((time()-ftime)<31536000?date[19..23]:(" "+date[13..16])));
166 creator="";
167 group="";
168 if (flags&LS_U)
169 {
170 creator=(string)call_other(master(),"creator_file",full);
171 switch(creator)
172 {
173 case ROOTID: creator="root"; break;
174 case BACKBONEID: creator="daemon"; break;
175 default: if(!creator) creator="none"; break;
176 }
177 }
178 if (flags&LS_G)
179 {
180 if (sizeof(tmp))
181 {
182 switch(tmp[0])
183 {
184 case WIZARDDIR: group="magier"; break;
185 case "news": group="news"; break;
186 case "mail": group="mail"; break;
187 case "open": group="public"; break;
188 case "p": group="project"; break;
189 case DOMAINDIR: if (sizeof(tmp)>1) { group=tmp[1]; break; }
190 default: group="mud"; break;
191 }
192 }
193 else group="mud";
194 }
195 if (dir) base=sprintf(colorstrings[DIR],base);
196 else
197 {
198 if (ob)
199 {
200 if (size==-1)
201 base=sprintf(colorstrings[VC],base);
202 else
203 base=sprintf(colorstrings[OBJ],base);
204 }
205 }
206 return sprintf(("%c%c%c%c %3d"+((flags&LS_U)?" %-24.24s":"%-0.1s")+
207 ((flags&LS_G)?" %-8.8s":"%0.1s")+" %8s %s %s\n"),
208 (dir?'d':'-'),
209 (!funcall(valid_read,full,getuid(),
210 "read_file",this_object())?'-':'r'),
211 (!funcall(valid_write,full,getuid(),
212 "write_file",this_object())?'-':'w'),
213 (ob?'x':'-'),
214 (dir?(sizeof((get_dir(full+"/*")||({}))-({".",".."}))):0),
215 creator,group,(dir?"-":size==-1?"<vc>":to_string(size)),
216 date,base);
217}
218
219
220static int _ls(string cmdline)
221{
222 int flags,cmp,i,arg_size,size;
223 int maxlen,counter,maxcount;
224 string *args,output;
225 mixed *tmp;
226 closure output_fun,v_read,v_write,creator,sort_fun;
227
228 cmdline=_unparsed_args()||"";
229 args=parseargs(cmdline,&flags,LS_OPTS,1);
230 if (flags==-1)
231 return USAGE("ls [-" LS_OPTS "] [<Verzeichnis>] [<Verzeichnis2> ..]");
232 SetColorstrings();
233 output="";
234 if (!sizeof(args)) args=({ QueryProp(P_CURRENTDIR) });
235 if (!sizeof(args=file_list(args,MODE_LSA,0,"/")))
236 return notify_fail("ls: Keine passenden Verzeichnisse gefunden.\n"), 0;
237// Files sortieren die erste
238 if (flags&LS_T) cmp=FILEDATE;
239 else if (flags&LS_S) cmp=FILESIZE;
240 else cmp=BASENAME; // =0 :-)
241 sort_fun=lambda(({ 'a,'b }),({
242 ((!cmp&&!(flags&LS_R))||(cmp&&(flags&LS_R))?#'>:#'<),
243 ({#'[,'a,cmp}),({#'[,'b,cmp})}));
244 args=sort_array(args,sort_fun);
245// Ausgabeformat bestimmen
246 if (flags&LS_L)
247 {
248 v_read=VALID_READ_CL;
249 v_write=VALID_WRITE_CL;
250 creator=CREATOR_CL;
251 }
252 arg_size=sizeof(args);
253 if (arg_size>1||(arg_size&&args[0][FILESIZE]>=0))
254 {
255 if (flags&LS_L)
256 tmp=map(args,#'_ls_output_long,flags,v_read,
257 v_write,creator)-({0});
258 else
259 {
260 counter=0;maxlen=0;
261 tmp=filter(args,#'_ls_maxlen,flags,&maxlen);
262 if (maxlen>76) maxlen=76;
263 maxcount=(78/(maxlen+2))-1;
264 tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
265 }
266 output=sprintf("\n%d Dateien/Unterverzeichnisse:\n%s\n",
267 sizeof(tmp),implode(tmp,""));
268 }
269 for(i=0;i<arg_size;i++)
270 {
271 tmp=({});
272 size=args[i][FILESIZE];
273 if (size==-2)
274 {
275 tmp=file_list(({args[i][FULLNAME]+"/*"}),MODE_LSB,0,"/");
276 tmp=sort_array(tmp,sort_fun);
277 if (flags&LS_L)
278 tmp=map(tmp,#'_ls_output_long,flags,v_read,
279 v_write,creator)-({0});
280 else
281 {
282 counter=0;maxlen=0;
283 tmp=filter(tmp,#'_ls_maxlen,flags,&maxlen);
284 maxcount=(78/(maxlen+2));
285 if (maxcount) maxcount--;
286 tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
287 }
288 if (sizeof(tmp))
289 {
290 output+=sprintf("\n%s: Verzeichnis, %d Dateien/Unterverzeichnisse:\n",
291 args[i][FULLNAME],sizeof(tmp));
292 output+=(implode(tmp,"")+((string)(tmp[<1][<1..<1])=="\n"?"":"\n"));
293 }
294 else
295 {
296 output+=sprintf("\n%s: Leeres Verzeichnis.\n",args[i][FULLNAME]);
297 }
298 }
299 }
300 More(output);
301 return 1;
302}
303
304// ########
305//############################### MORE ###################################
306// ########
307//
308// _more_file: Mehrere Files hintereinander ausgeben
309//
310
311private void _more_file(string *arg)
312{
313 if (!sizeof(arg)) return;
314 printf("more: Naechste Datei: %s\n",arg[0]);
315 More(arg[0],1,#'_more_file,({ arg[1..]}));
316 return;
317}
318
319
320private mixed _size_filter(mixed *arg)
321{
322 if (arg[FILESIZE]>0) return arg[FULLNAME];
323 if (arg[FILESIZE]==0)
324 {
325 printf("%s: %s: Leere Datei.\n",query_verb()||"more",arg[FULLNAME]);
326 return 0;
327 }
328 if (arg[FILESIZE]==-2)
329 printf("%s: %s ist ein Verzeichnis.\n",query_verb()||"more",arg[FULLNAME]);
330 else
331 printf("%s: %s: Datei existiert nicht.\n", query_verb()||"more",
332 arg[FULLNAME]);
333 return 0;
334}
335
336
337//
338// _more: Dateien anzeigen
339// cmdline: Kommandozeile
340//
341
342static int _more(string cmdline)
343{
344 mixed *args;
345 int flags;
346 cmdline=_unparsed_args();
347 args=parseargs(cmdline,&flags,"",1);
348 if (flags==-1||!sizeof(args)) return USAGE("more <datei> [<datei2>..]");
349 args=file_list(args,MODE_MORE,0,"/");
350 if (!sizeof(args))
351 return printf("more: %s: Keine passende Datei gefunden.\n",cmdline),1;
352 args=map(args,#'_size_filter)-({0});
353 if (sizeof(args)) _more_file(args);
354 return 1;
355}
356
357// ###################
358//########################## HEAD, TAIL, CAT #############################
359// ###################
360
361static int _cat(string cmdline)
362{
363 mixed *args;
364 int flags;
365 cmdline=_unparsed_args();
366 args=parseargs(cmdline,&flags,"",1);
367 if(flags==-1||!sizeof(args))
368 return USAGE(query_verb()+" <dateiname> [<datei2>..]");
369 args=file_list(args,MODE_CAT,0,"/");
370 if (!sizeof(args))
371 return printf("%s: %s: Keine passende Datei gefunden.\n",query_verb(),
372 cmdline),1;
373 args=map(args,#'_size_filter)-({0});
374 if (!sizeof(args)) return 1;
375 while(sizeof(args))
376 {
377 switch(query_verb())
378 {
379 case "cat":
380 if (!cat(args[0]))
381 printf("cat: %s konnte nicht angezeigt werden.\n",args[0]);
382 break;
383 case "head":
384 if (!cat(args[0],0,10))
385 printf("head: %s konnte nicht angezeigt werden.\n",args[0]);
386 break;
387 case "tail": tail(args[0]); break;
388 }
389 args=args[1..];
390 }
391 return 1;
392}
393
394// #######
395//############################### MAN ###################################
396// #######
397
398static int _man(string cmdline)
399{
400 mixed *args;
401 int i, flags;
402 string *tmp, *tmp2;
403
404 cmdline=_unparsed_args();
405 args=parseargs(cmdline,&flags,MAN_OPTS,0);
406
407 if (flags==-1 ||
408 (sizeof(args)!=1 &&
409 (sizeof(args)<2 || sizeof(args[1])>1 || !(i=to_int(args[1])))))
410 return USAGE("man [-" MAN_OPTS "] <hilfeseite>");
411 tmp=explode(args[0],"/");
412
413 if (oldman_result && sizeof(tmp)==1 && sizeof(args)==1 &&
414 sizeof(tmp[0])==1 && (i=to_int(tmp[0])) && member(oldman_result,i)) {
415 tmp=({oldman_result[i,0],oldman_result[i,1]});
416 i=0;
417 }
418 else if (!(flags&(MAN_M|MAN_R))&&sizeof(tmp)>1)
419 {
420 if (file_size(MAND_DOCDIR+args[0])>=0)
421 tmp=({tmp[<1],args[0]});
422 else
423 tmp=({});
424 }
425 else
426 {
427 if (flags&MAN_R)
428 {
429 flags&=(~MAN_M);
430 if (catch(regexp(({""}),args[0]))||
431 !regexp(({""}),args[0]))
432 return printf("man: Ungueltiger Ausdruck in Maske.\n"),1;
433 }
434 tmp=(string *)call_other(MAND,"locate",args[0],flags&(MAN_M|MAN_R));
435 }
436
437 oldman_result=(mapping)0;
438 if(i && sizeof(tmp)>2 && sizeof(tmp)>=(i<<1))
439 tmp=tmp[((i<<1)-2)..((i<<1)-1)];
440 switch(sizeof(tmp))
441 {
442 case 0:
443 printf("Keine Hilfeseite gefunden fuer '%s'.\n",args[0]);
444 break;
445 case 2:
446 /*
447 if (flags&MAN_I)
448 {
449 // BRANCH TO MANUALD
450 return 1;
451 }
452 */
453 printf("Folgende Hilfeseite wurde gefunden: %s\n",tmp[1]);
454 More(MAND_DOCDIR+tmp[1],1);
455 return 1;
456 default:
457 i=sizeof(tmp)>>1;
458 tmp2=allocate(i);
459 oldman_result=m_allocate(i,2);
460 while(i)
461 {
462 tmp2[(i-1)]=sprintf("%d: ",i)+tmp[(i<<1)-2];
463 oldman_result[i,0]=tmp[(i<<1)-2];
464 oldman_result[i,1]=tmp[(i<<1)-1];
465 i--;
466 }
467 printf("Es wurden folgende potentiell passenden Seiten gefunden:\n"
468 "%'-'78.78s\n%s%'-'78.78s\n","",
469 break_string(implode(tmp2," "),78),"");
470 break;
471 }
472 return 1;
473}
474
475// ########
476//############################### RMAN ##################################
477// ########
478
479static int _rman(string str)
480{
481 int flags;
482 string *args;
483
484 str=_unparsed_args();
485 args=parseargs(str,&flags,"",0);
486 if (flags==-1||sizeof(args)!=2)
487 return USAGE("rman <hilfeseite> <mudname>");
488 write("man: " +
489 (string)call_other(UDP_CMD_DIR+"man","send_request",args[1],args[0]));
490 return 1;
491}
492
493
494// #############
495//############################# SHOWPROPS ###############################
496// #############
497
498//
499// _showprops: Zeigt Properties zu einem Objekt an
500//
501
502static int _showprops(string str)
503{
504 int i;
505 string *list, ausgabe;
506
507 if (str) {
508 if (str[0]!='/') str="/"+str;
509 if (str[0..4]!="/std/")
510 {
511 printf("showprops: Es koennen nur Properties von Objekten "
512 "aus /std/ angezeigt werden.\n");
513 return 1;
514 }
515 if (str[<1]=='.') str+="c";
516 if (str[<2..<1]!=".c") str+=".c";
517 if (file_size(str)<0)
518 {
519 printf("showprops: %s: Es gibt kein Objekt diesen Namens.\n",str[0..<3]);
520 return 1;
521 }
522 if (catch(call_other(str[0..<3], "???")))
523 {
524 printf("showprops: %s: Datei konnte nicht geladen werden.\n",str);
525 return 1;
526 }
527 }
528 if (!str || !find_object(str)) {
529 notify_fail("Welche Properties moechtest Du sehen?"
530 " Bsp.: <showprops /std/npc>\n");
531 return 0;
532 }
533 list=inherit_list(find_object(str));
534#if __VERSION__ < "3.2.9"
535 list=map(list,lambda(({'x}),({#'extract,'x,4,-2})));
536 list+=map(list,lambda(({'x}),({#'[<,({#'old_explode,'x,"/"}),1})));
537 list=map(m_indices(mkmapping(list)),lambda(({'x}),({#'+,({#'+,"/sys/",'x}),"h"})));
538 list=filter(list,lambda(({'x}),({#'>,({#'file_size,'x}),0})) );
539#else
540 list=map(list,(: return $1[5..<2]+"h"; :));
541 list+=map(list,(: return explode($1,"/")[<1]; :));
542 list=map(m_indices(mkmapping(list)),(: return "/sys/"+$1; :));
543 list=filter(list,(: return file_size($1)>0; :));
544#endif
545 list=sort_array(list, #'<);
546 ausgabe="";
547 for (i=sizeof(list);i--;)
548 {
549#if __VERSION__ < "3.2.9"
550 str=implode(filter(old_explode(read_file(list[i]), "\n"),
551 lambda( ({ 'x }), ({#'==, ({#'extract, 'x, 0, 9}), "#define P_"}) ))
552 , "\n");
553#else
554 str=implode(filter(explode(read_file(list[i]),"\n"),
555 (: return $1[0..9]=="#define P_";:)),"\n");
556#endif
557 if (str!="") ausgabe+=sprintf("%s\n%s\n\n", list[i], str);
558 }
559 if (ausgabe!="")
560 More(ausgabe);
561 else
562 printf("Keine Property-Definitionen zu diesem Objekt gefunden!\n");
563 return 1;
564}
565
566// ########
567//############################### GREP ###################################
568// ########
569
570#if __VERSION__ < "3.2.9"
571
572private int _grep_filter(string filename)
573{
574 return (call_other("valid_write",filename,getuid(this_object()),
575 "write_file",this_object())!=0);
576}
577
578#endif
579
580//
581// grep_file: Datei greppen
582// rexpr: Regular Expression
583// flags: Flags
584//
585
586private int grep_file(mixed filedata, string rexpr, int flags)
587{
588 string fullname,data,carry,*lines,*lines_orig,*tmp,*result;
589 int ptr,count,i,nol,match,index;
590 fullname=filedata[FULLNAME];
591 if ((flags&GREP_F)&&fullname=="/players/"+getuid()+"/grep.out")
592 {
593 write_file("/players/"+getuid()+"/grep.out",
594 "Uebergehe grep.out ...\n");
595 return RET_FAIL;
596 }
597 switch(filedata[FILESIZE])
598 {
599 case -2: return RET_FAIL;
600 case -1: return ERROR(DOESNT_EXIST,fullname,RET_FAIL);
601 case 0: return RET_FAIL;
602 default: break;
603 }
604 if (!MAY_READ(fullname)) return ERROR(NO_READ,fullname,RET_FAIL);
605 carry=""; result=({});
606 if (flags&GREP_I)
607 rexpr=lower_case(rexpr);
608 do
609 {
610 data=read_bytes(fullname,ptr,MAXLEN)||"";
611 ptr+=MAXLEN;
612 lines=explode(carry+data,"\n");
613 switch(sizeof(lines))
614 {
615 case 0: continue;
616 case 1:
617 carry="";
618 break;
619 default:
620 carry=lines[<1];
621 lines=lines[0..<2];
622 break;
623 }
624 lines_orig=lines;
625 if (flags&GREP_I)
626 lines=map(lines,#'lower_case);
627 nol=sizeof(lines);
628 for (i=0;i<nol;i++)
629 {
630 match=sizeof(regexp(lines[i..i],rexpr));
631 if (flags&GREP_V) match=!match;
632 if (match)
633 {
634 if (!(flags&GREP_C))
635 {
636 if (flags&GREP_N)
637 result+=({ sprintf("%4d %s",index+i+1,lines_orig[i])});
638 else
639 result+=lines_orig[i..i];
640 }
641 count++;
642 }
643 }
644 index+=nol;
645 }
646 while(sizeof(data)==MAXLEN);
647 if (carry!="")
648 {
649 if (flags&GREP_I) carry=lower_case(carry);
650 match=sizeof(regexp(({ carry }),rexpr));
651 if (flags&GREP_V) match=!match;
652 if (match)
653 {
654 if(!(flags&GREP_C))
655 {
656 if(flags&GREP_N)
657 result+=({ sprintf("%4d %s",index+1,carry) });
658 else
659 result+=({carry});
660 }
661 count++;
662 }
663 }
664 carry="";
665 if (count)
666 {
667 if (flags&GREP_L) carry=sprintf("%s\n",fullname);
668 else if (flags&GREP_H) data="";
669 else data=sprintf(" %s:",fullname);
670 if (flags&GREP_C) carry=sprintf("%s %d passende Zeile%s.\n",data,count,
671 (count==1?"":"n"));
672 else
673 carry=(data+"\n"+implode(result,"\n")+"\n");
674 }
675 if (flags&GREP_F)
676 return write_file("/players/"+getuid()+"/grep.out",carry);
677 write(carry);
678 return RET_OK;
679}
680
681static int _grep(string cmdline)
682{
683 string rexpr,mask;
684 mixed *args;
685 int flags;
686 cmdline=_unparsed_args();
687 args=parseargs(cmdline,&flags,GREP_OPTS,0);
688 if ((flags==-1)||!sizeof(args))
689 return USAGE("grep [-" GREP_OPTS
690 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
691 rexpr=args[0];
692 if (catch(regexp(({""}),rexpr))||!regexp(({""}),rexpr))
693 return printf("grep: Ungueltiger Suchausdruck: %s\n",rexpr) ,1;
694 args=args[1..];
695 if (flags&GREP_M)
696 {
697 mask=args[<1];
698 args=args[0..<2];
699 }
700 if (!sizeof(args))
701 return USAGE("grep [-" GREP_OPTS
702 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
703 args=map(args,#'to_filename)-({0});
704 /*
705#if __VERSION__ < "3.2.9"
706 args=filter(args,#'_grep_filter);
707#else
708 args=filter(args,(: return (valid_write($1,
709 getuid(this_object()),"write_file",this_object())!=0):));
710#endif
711 */
712 args=file_list(args,MODE_GREP,(flags&GREP_R?1:0),"/",mask);
713 if (!sizeof(args))
714 return printf("Keine passenden Dateien gefunden.\n"),1;
715 if (flags&GREP_I) rexpr=lower_case(rexpr);
716 if (flags&GREP_F)
717 {
718 if (file_size("/players/"+getuid()+"/grep.out")==-2||
719 !MAY_WRITE("/players/"+getuid()+"/grep.out"))
720 return printf("grep: Datei /players/%s/grep.out kann nicht "
721 "geschrieben werden.\n",getuid()),1;
722 else
723 write_file("/players/"+getuid()+"/grep.out",
724 "Ausgabe von \"grep " + _unparsed_args() + "\":\n");
725 }
726 asynchron(args,#'grep_file,rexpr,flags,0);
727 return 1;
728}