Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/std/shells/magier/fileview.c b/std/shells/magier/fileview.c
new file mode 100644
index 0000000..731de5a
--- /dev/null
+++ b/std/shells/magier/fileview.c
@@ -0,0 +1,728 @@
+// MorgenGrauen MUDlib
+//
+// fileview.c
+//
+// $Id: fileview.c 9142 2015-02-04 22:17:29Z Zesstra $
+#pragma strict_types
+#pragma save_types
+//#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <ansi.h>
+#include <player/base.h>
+#include <wizlevels.h>
+#include <shells.h>
+#include <daemon/mand.h>
+#include <udp.h>
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <thing/properties.h>
+#include <player.h>
+
+private nosave mapping colorstrings;
+private nosave mapping oldman_result;
+
+// ###################
+//######################### INITIALISIERUNG #############################
+// ###################
+
+mixed _query_localcmds()
+{
+ return ({({"ls","_ls",0,LEARNER_LVL}),
+ ({"more","_more",0,LEARNER_LVL}),
+ ({"cat","_cat",0,LEARNER_LVL}),
+ ({"head","_cat",0,LEARNER_LVL}),
+ ({"tail","_cat",0,LEARNER_LVL}),
+ ({"man","_man",0,LEARNER_LVL}),
+ ({"rman","_rman",0,LEARNER_LVL}),
+ ({"showprops","_showprops",0,WIZARD_LVL}),
+ ({"grep","_grep",0,LEARNER_LVL})});
+}
+
+
+// ######
+//################################ LS ###################################
+// ######
+
+//
+// _ls: Der ls-Befehl: Verzeichnisse und Dateien anzeigen
+// cmdline: Kommandozeile
+//
+
+//
+// Funktionen zum Sortieren und fuer filter_ldfied/map_ldfied
+//
+
+
+private string _get_color(string color)
+{
+ return COLORS[lower_case(color)];
+}
+
+
+private void SetColorstrings()
+{
+ string tmp,term;
+ mapping vars;
+ vars=QueryProp(P_VARIABLES);
+ colorstrings=m_allocate(0,2);
+ switch(term=QueryProp(P_TTY))
+ {
+ case "vt100":
+ case "ansi":
+ if(stringp(vars["LS_DIR"]))
+ tmp=implode(map(explode(vars["LS_DIR"],"+"),#'_get_color),
+ "");
+ else
+ tmp = (term == "ansi") ? ANSI_BLUE+ANSI_BOLD: ANSI_BOLD;
+ colorstrings[DIR] = tmp+"%s"+(term == "vt100"?"/":"")+ANSI_NORMAL;
+ if(term == "vt100") colorstrings[DIR, 1] = 1;
+ if(stringp(vars["LS_OBJ"]))
+ tmp=implode(map(explode(vars["LS_OBJ"],"+"),#'_get_color),
+ "");
+ else
+ tmp = (term == "ansi") ? ANSI_RED : ANSI_INVERS;
+ colorstrings[OBJ] = tmp+"%s"+ANSI_NORMAL;
+ if(stringp(vars["LS_VC"]))
+ tmp=implode(map(explode(vars["LS_VC"],"+"),#'_get_color),
+ "");
+ else
+ tmp = (term == "ansi") ? ANSI_PURPLE : ANSI_INVERS;
+ colorstrings[VC] = tmp+"%s"+ANSI_NORMAL;
+ break;
+ case "dumb":
+ colorstrings[DIR] = "%s/"; colorstrings[DIR, 1] = 1;
+ colorstrings[OBJ] = "%s*"; colorstrings[OBJ, 1] = 1;
+ colorstrings[VC] = "%s*"; colorstrings[VC , 1] = 1;
+ break;
+ default:
+ colorstrings[DIR] = "%s";
+ colorstrings[OBJ] = "%s";
+ colorstrings[VC] = "%s";
+ }
+ return;
+}
+
+
+private string _ls_output_short(mixed filedata,
+ int maxlen,int counter,int maxcount)
+{
+ string tmp;
+ tmp=filedata[BASENAME];
+ maxlen-=sizeof(tmp);
+ switch(filedata[FILESIZE])
+ {
+ case -2: tmp=sprintf(colorstrings[DIR],tmp);
+ maxlen-=colorstrings[DIR,1]; break;
+ case -1: tmp=sprintf(colorstrings[VC],tmp);
+ maxlen-=colorstrings[VC,1]; break;
+ default: if (find_object(filedata[FULLNAME]))
+ {
+ maxlen-=colorstrings[OBJ,1];
+ tmp=sprintf(colorstrings[OBJ],tmp); break;
+ }
+ }
+ if (!maxcount) return tmp+"\n";
+ return sprintf("%-*s%s",(maxlen+sizeof(tmp)),tmp,
+ ((counter++)==maxcount?(counter=0,"\n"):" "));
+}
+
+private int _ls_maxlen(mixed filedata,int flags,int maxlen)
+{
+ string base;
+ int size;
+ base=filedata[BASENAME];
+ if (!(flags&LS_A)&&(base[0]=='.')) return 0;
+#if __VERSION__ < "3.2.9"
+ if (sizeof(base)>maxlen) maxlen=sizeof(base);
+#else
+ maxlen=max(maxlen,sizeof(base));
+#endif
+ return 1;
+}
+
+private string _ls_output_long(mixed filedata, int flags,closure valid_read,
+ closure valid_write,closure creator_file)
+{
+ string *tmp,full,base,path,date,creator,group;
+ int size,dir,ftime;
+ object ob;
+
+ base=filedata[BASENAME];
+ if (!(sizeof(base))||((!(flags&LS_A))&&(base[0]=='.')))
+ return 0;
+ size=filedata[FILESIZE];
+ path=filedata[PATHNAME];
+ tmp=(string *)call_other(master(),"full_path_array",
+ filedata[FULLNAME],getuid());
+ full=sprintf("/%s",implode(tmp,"/"));
+ dir=(size==-2);
+ ob=find_object(full);
+ ftime=filedata[FILEDATE];
+ date=dtime(ftime);
+ date=sprintf("%s %s %s",date[9..11],date[5..6],
+ ((time()-ftime)<31536000?date[19..23]:(" "+date[13..16])));
+ creator="";
+ group="";
+ if (flags&LS_U)
+ {
+ creator=(string)call_other(master(),"creator_file",full);
+ switch(creator)
+ {
+ case ROOTID: creator="root"; break;
+ case BACKBONEID: creator="daemon"; break;
+ default: if(!creator) creator="none"; break;
+ }
+ }
+ if (flags&LS_G)
+ {
+ if (sizeof(tmp))
+ {
+ switch(tmp[0])
+ {
+ case WIZARDDIR: group="magier"; break;
+ case "news": group="news"; break;
+ case "mail": group="mail"; break;
+ case "open": group="public"; break;
+ case "p": group="project"; break;
+ case DOMAINDIR: if (sizeof(tmp)>1) { group=tmp[1]; break; }
+ default: group="mud"; break;
+ }
+ }
+ else group="mud";
+ }
+ if (dir) base=sprintf(colorstrings[DIR],base);
+ else
+ {
+ if (ob)
+ {
+ if (size==-1)
+ base=sprintf(colorstrings[VC],base);
+ else
+ base=sprintf(colorstrings[OBJ],base);
+ }
+ }
+ return sprintf(("%c%c%c%c %3d"+((flags&LS_U)?" %-24.24s":"%-0.1s")+
+ ((flags&LS_G)?" %-8.8s":"%0.1s")+" %8s %s %s\n"),
+ (dir?'d':'-'),
+ (!funcall(valid_read,full,getuid(),
+ "read_file",this_object())?'-':'r'),
+ (!funcall(valid_write,full,getuid(),
+ "write_file",this_object())?'-':'w'),
+ (ob?'x':'-'),
+ (dir?(sizeof((get_dir(full+"/*")||({}))-({".",".."}))):0),
+ creator,group,(dir?"-":size==-1?"<vc>":to_string(size)),
+ date,base);
+}
+
+
+static int _ls(string cmdline)
+{
+ int flags,cmp,i,arg_size,size;
+ int maxlen,counter,maxcount;
+ string *args,output;
+ mixed *tmp;
+ closure output_fun,v_read,v_write,creator,sort_fun;
+
+ cmdline=_unparsed_args()||"";
+ args=parseargs(cmdline,&flags,LS_OPTS,1);
+ if (flags==-1)
+ return USAGE("ls [-" LS_OPTS "] [<Verzeichnis>] [<Verzeichnis2> ..]");
+ SetColorstrings();
+ output="";
+ if (!sizeof(args)) args=({ QueryProp(P_CURRENTDIR) });
+ if (!sizeof(args=file_list(args,MODE_LSA,0,"/")))
+ return notify_fail("ls: Keine passenden Verzeichnisse gefunden.\n"), 0;
+// Files sortieren die erste
+ if (flags&LS_T) cmp=FILEDATE;
+ else if (flags&LS_S) cmp=FILESIZE;
+ else cmp=BASENAME; // =0 :-)
+ sort_fun=lambda(({ 'a,'b }),({
+ ((!cmp&&!(flags&LS_R))||(cmp&&(flags&LS_R))?#'>:#'<),
+ ({#'[,'a,cmp}),({#'[,'b,cmp})}));
+ args=sort_array(args,sort_fun);
+// Ausgabeformat bestimmen
+ if (flags&LS_L)
+ {
+ v_read=VALID_READ_CL;
+ v_write=VALID_WRITE_CL;
+ creator=CREATOR_CL;
+ }
+ arg_size=sizeof(args);
+ if (arg_size>1||(arg_size&&args[0][FILESIZE]>=0))
+ {
+ if (flags&LS_L)
+ tmp=map(args,#'_ls_output_long,flags,v_read,
+ v_write,creator)-({0});
+ else
+ {
+ counter=0;maxlen=0;
+ tmp=filter(args,#'_ls_maxlen,flags,&maxlen);
+ if (maxlen>76) maxlen=76;
+ maxcount=(78/(maxlen+2))-1;
+ tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
+ }
+ output=sprintf("\n%d Dateien/Unterverzeichnisse:\n%s\n",
+ sizeof(tmp),implode(tmp,""));
+ }
+ for(i=0;i<arg_size;i++)
+ {
+ tmp=({});
+ size=args[i][FILESIZE];
+ if (size==-2)
+ {
+ tmp=file_list(({args[i][FULLNAME]+"/*"}),MODE_LSB,0,"/");
+ tmp=sort_array(tmp,sort_fun);
+ if (flags&LS_L)
+ tmp=map(tmp,#'_ls_output_long,flags,v_read,
+ v_write,creator)-({0});
+ else
+ {
+ counter=0;maxlen=0;
+ tmp=filter(tmp,#'_ls_maxlen,flags,&maxlen);
+ maxcount=(78/(maxlen+2));
+ if (maxcount) maxcount--;
+ tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
+ }
+ if (sizeof(tmp))
+ {
+ output+=sprintf("\n%s: Verzeichnis, %d Dateien/Unterverzeichnisse:\n",
+ args[i][FULLNAME],sizeof(tmp));
+ output+=(implode(tmp,"")+((string)(tmp[<1][<1..<1])=="\n"?"":"\n"));
+ }
+ else
+ {
+ output+=sprintf("\n%s: Leeres Verzeichnis.\n",args[i][FULLNAME]);
+ }
+ }
+ }
+ More(output);
+ return 1;
+}
+
+// ########
+//############################### MORE ###################################
+// ########
+//
+// _more_file: Mehrere Files hintereinander ausgeben
+//
+
+private void _more_file(string *arg)
+{
+ if (!sizeof(arg)) return;
+ printf("more: Naechste Datei: %s\n",arg[0]);
+ More(arg[0],1,#'_more_file,({ arg[1..]}));
+ return;
+}
+
+
+private mixed _size_filter(mixed *arg)
+{
+ if (arg[FILESIZE]>0) return arg[FULLNAME];
+ if (arg[FILESIZE]==0)
+ {
+ printf("%s: %s: Leere Datei.\n",query_verb()||"more",arg[FULLNAME]);
+ return 0;
+ }
+ if (arg[FILESIZE]==-2)
+ printf("%s: %s ist ein Verzeichnis.\n",query_verb()||"more",arg[FULLNAME]);
+ else
+ printf("%s: %s: Datei existiert nicht.\n", query_verb()||"more",
+ arg[FULLNAME]);
+ return 0;
+}
+
+
+//
+// _more: Dateien anzeigen
+// cmdline: Kommandozeile
+//
+
+static int _more(string cmdline)
+{
+ mixed *args;
+ int flags;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,"",1);
+ if (flags==-1||!sizeof(args)) return USAGE("more <datei> [<datei2>..]");
+ args=file_list(args,MODE_MORE,0,"/");
+ if (!sizeof(args))
+ return printf("more: %s: Keine passende Datei gefunden.\n",cmdline),1;
+ args=map(args,#'_size_filter)-({0});
+ if (sizeof(args)) _more_file(args);
+ return 1;
+}
+
+// ###################
+//########################## HEAD, TAIL, CAT #############################
+// ###################
+
+static int _cat(string cmdline)
+{
+ mixed *args;
+ int flags;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,"",1);
+ if(flags==-1||!sizeof(args))
+ return USAGE(query_verb()+" <dateiname> [<datei2>..]");
+ args=file_list(args,MODE_CAT,0,"/");
+ if (!sizeof(args))
+ return printf("%s: %s: Keine passende Datei gefunden.\n",query_verb(),
+ cmdline),1;
+ args=map(args,#'_size_filter)-({0});
+ if (!sizeof(args)) return 1;
+ while(sizeof(args))
+ {
+ switch(query_verb())
+ {
+ case "cat":
+ if (!cat(args[0]))
+ printf("cat: %s konnte nicht angezeigt werden.\n",args[0]);
+ break;
+ case "head":
+ if (!cat(args[0],0,10))
+ printf("head: %s konnte nicht angezeigt werden.\n",args[0]);
+ break;
+ case "tail": tail(args[0]); break;
+ }
+ args=args[1..];
+ }
+ return 1;
+}
+
+// #######
+//############################### MAN ###################################
+// #######
+
+static int _man(string cmdline)
+{
+ mixed *args;
+ int i, flags;
+ string *tmp, *tmp2;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,MAN_OPTS,0);
+
+ if (flags==-1 ||
+ (sizeof(args)!=1 &&
+ (sizeof(args)<2 || sizeof(args[1])>1 || !(i=to_int(args[1])))))
+ return USAGE("man [-" MAN_OPTS "] <hilfeseite>");
+ tmp=explode(args[0],"/");
+
+ if (oldman_result && sizeof(tmp)==1 && sizeof(args)==1 &&
+ sizeof(tmp[0])==1 && (i=to_int(tmp[0])) && member(oldman_result,i)) {
+ tmp=({oldman_result[i,0],oldman_result[i,1]});
+ i=0;
+ }
+ else if (!(flags&(MAN_M|MAN_R))&&sizeof(tmp)>1)
+ {
+ if (file_size(MAND_DOCDIR+args[0])>=0)
+ tmp=({tmp[<1],args[0]});
+ else
+ tmp=({});
+ }
+ else
+ {
+ if (flags&MAN_R)
+ {
+ flags&=(~MAN_M);
+ if (catch(regexp(({""}),args[0]))||
+ !regexp(({""}),args[0]))
+ return printf("man: Ungueltiger Ausdruck in Maske.\n"),1;
+ }
+ tmp=(string *)call_other(MAND,"locate",args[0],flags&(MAN_M|MAN_R));
+ }
+
+ oldman_result=(mapping)0;
+ if(i && sizeof(tmp)>2 && sizeof(tmp)>=(i<<1))
+ tmp=tmp[((i<<1)-2)..((i<<1)-1)];
+ switch(sizeof(tmp))
+ {
+ case 0:
+ printf("Keine Hilfeseite gefunden fuer '%s'.\n",args[0]);
+ break;
+ case 2:
+ /*
+ if (flags&MAN_I)
+ {
+ // BRANCH TO MANUALD
+ return 1;
+ }
+ */
+ printf("Folgende Hilfeseite wurde gefunden: %s\n",tmp[1]);
+ More(MAND_DOCDIR+tmp[1],1);
+ return 1;
+ default:
+ i=sizeof(tmp)>>1;
+ tmp2=allocate(i);
+ oldman_result=m_allocate(i,2);
+ while(i)
+ {
+ tmp2[(i-1)]=sprintf("%d: ",i)+tmp[(i<<1)-2];
+ oldman_result[i,0]=tmp[(i<<1)-2];
+ oldman_result[i,1]=tmp[(i<<1)-1];
+ i--;
+ }
+ printf("Es wurden folgende potentiell passenden Seiten gefunden:\n"
+ "%'-'78.78s\n%s%'-'78.78s\n","",
+ break_string(implode(tmp2," "),78),"");
+ break;
+ }
+ return 1;
+}
+
+// ########
+//############################### RMAN ##################################
+// ########
+
+static int _rman(string str)
+{
+ int flags;
+ string *args;
+
+ str=_unparsed_args();
+ args=parseargs(str,&flags,"",0);
+ if (flags==-1||sizeof(args)!=2)
+ return USAGE("rman <hilfeseite> <mudname>");
+ write("man: " +
+ (string)call_other(UDP_CMD_DIR+"man","send_request",args[1],args[0]));
+ return 1;
+}
+
+
+// #############
+//############################# SHOWPROPS ###############################
+// #############
+
+//
+// _showprops: Zeigt Properties zu einem Objekt an
+//
+
+static int _showprops(string str)
+{
+ int i;
+ string *list, ausgabe;
+
+ if (str) {
+ if (str[0]!='/') str="/"+str;
+ if (str[0..4]!="/std/")
+ {
+ printf("showprops: Es koennen nur Properties von Objekten "
+ "aus /std/ angezeigt werden.\n");
+ return 1;
+ }
+ if (str[<1]=='.') str+="c";
+ if (str[<2..<1]!=".c") str+=".c";
+ if (file_size(str)<0)
+ {
+ printf("showprops: %s: Es gibt kein Objekt diesen Namens.\n",str[0..<3]);
+ return 1;
+ }
+ if (catch(call_other(str[0..<3], "???")))
+ {
+ printf("showprops: %s: Datei konnte nicht geladen werden.\n",str);
+ return 1;
+ }
+ }
+ if (!str || !find_object(str)) {
+ notify_fail("Welche Properties moechtest Du sehen?"
+ " Bsp.: <showprops /std/npc>\n");
+ return 0;
+ }
+ list=inherit_list(find_object(str));
+#if __VERSION__ < "3.2.9"
+ list=map(list,lambda(({'x}),({#'extract,'x,4,-2})));
+ list+=map(list,lambda(({'x}),({#'[<,({#'old_explode,'x,"/"}),1})));
+ list=map(m_indices(mkmapping(list)),lambda(({'x}),({#'+,({#'+,"/sys/",'x}),"h"})));
+ list=filter(list,lambda(({'x}),({#'>,({#'file_size,'x}),0})) );
+#else
+ list=map(list,(: return $1[5..<2]+"h"; :));
+ list+=map(list,(: return explode($1,"/")[<1]; :));
+ list=map(m_indices(mkmapping(list)),(: return "/sys/"+$1; :));
+ list=filter(list,(: return file_size($1)>0; :));
+#endif
+ list=sort_array(list, #'<);
+ ausgabe="";
+ for (i=sizeof(list);i--;)
+ {
+#if __VERSION__ < "3.2.9"
+ str=implode(filter(old_explode(read_file(list[i]), "\n"),
+ lambda( ({ 'x }), ({#'==, ({#'extract, 'x, 0, 9}), "#define P_"}) ))
+ , "\n");
+#else
+ str=implode(filter(explode(read_file(list[i]),"\n"),
+ (: return $1[0..9]=="#define P_";:)),"\n");
+#endif
+ if (str!="") ausgabe+=sprintf("%s\n%s\n\n", list[i], str);
+ }
+ if (ausgabe!="")
+ More(ausgabe);
+ else
+ printf("Keine Property-Definitionen zu diesem Objekt gefunden!\n");
+ return 1;
+}
+
+// ########
+//############################### GREP ###################################
+// ########
+
+#if __VERSION__ < "3.2.9"
+
+private int _grep_filter(string filename)
+{
+ return (call_other("valid_write",filename,getuid(this_object()),
+ "write_file",this_object())!=0);
+}
+
+#endif
+
+//
+// grep_file: Datei greppen
+// rexpr: Regular Expression
+// flags: Flags
+//
+
+private int grep_file(mixed filedata, string rexpr, int flags)
+{
+ string fullname,data,carry,*lines,*lines_orig,*tmp,*result;
+ int ptr,count,i,nol,match,index;
+ fullname=filedata[FULLNAME];
+ if ((flags&GREP_F)&&fullname=="/players/"+getuid()+"/grep.out")
+ {
+ write_file("/players/"+getuid()+"/grep.out",
+ "Uebergehe grep.out ...\n");
+ return RET_FAIL;
+ }
+ switch(filedata[FILESIZE])
+ {
+ case -2: return RET_FAIL;
+ case -1: return ERROR(DOESNT_EXIST,fullname,RET_FAIL);
+ case 0: return RET_FAIL;
+ default: break;
+ }
+ if (!MAY_READ(fullname)) return ERROR(NO_READ,fullname,RET_FAIL);
+ carry=""; result=({});
+ if (flags&GREP_I)
+ rexpr=lower_case(rexpr);
+ do
+ {
+ data=read_bytes(fullname,ptr,MAXLEN)||"";
+ ptr+=MAXLEN;
+ lines=explode(carry+data,"\n");
+ switch(sizeof(lines))
+ {
+ case 0: continue;
+ case 1:
+ carry="";
+ break;
+ default:
+ carry=lines[<1];
+ lines=lines[0..<2];
+ break;
+ }
+ lines_orig=lines;
+ if (flags&GREP_I)
+ lines=map(lines,#'lower_case);
+ nol=sizeof(lines);
+ for (i=0;i<nol;i++)
+ {
+ match=sizeof(regexp(lines[i..i],rexpr));
+ if (flags&GREP_V) match=!match;
+ if (match)
+ {
+ if (!(flags&GREP_C))
+ {
+ if (flags&GREP_N)
+ result+=({ sprintf("%4d %s",index+i+1,lines_orig[i])});
+ else
+ result+=lines_orig[i..i];
+ }
+ count++;
+ }
+ }
+ index+=nol;
+ }
+ while(sizeof(data)==MAXLEN);
+ if (carry!="")
+ {
+ if (flags&GREP_I) carry=lower_case(carry);
+ match=sizeof(regexp(({ carry }),rexpr));
+ if (flags&GREP_V) match=!match;
+ if (match)
+ {
+ if(!(flags&GREP_C))
+ {
+ if(flags&GREP_N)
+ result+=({ sprintf("%4d %s",index+1,carry) });
+ else
+ result+=({carry});
+ }
+ count++;
+ }
+ }
+ carry="";
+ if (count)
+ {
+ if (flags&GREP_L) carry=sprintf("%s\n",fullname);
+ else if (flags&GREP_H) data="";
+ else data=sprintf(" %s:",fullname);
+ if (flags&GREP_C) carry=sprintf("%s %d passende Zeile%s.\n",data,count,
+ (count==1?"":"n"));
+ else
+ carry=(data+"\n"+implode(result,"\n")+"\n");
+ }
+ if (flags&GREP_F)
+ return write_file("/players/"+getuid()+"/grep.out",carry);
+ write(carry);
+ return RET_OK;
+}
+
+static int _grep(string cmdline)
+{
+ string rexpr,mask;
+ mixed *args;
+ int flags;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,GREP_OPTS,0);
+ if ((flags==-1)||!sizeof(args))
+ return USAGE("grep [-" GREP_OPTS
+ "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
+ rexpr=args[0];
+ if (catch(regexp(({""}),rexpr))||!regexp(({""}),rexpr))
+ return printf("grep: Ungueltiger Suchausdruck: %s\n",rexpr) ,1;
+ args=args[1..];
+ if (flags&GREP_M)
+ {
+ mask=args[<1];
+ args=args[0..<2];
+ }
+ if (!sizeof(args))
+ return USAGE("grep [-" GREP_OPTS
+ "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
+ args=map(args,#'to_filename)-({0});
+ /*
+#if __VERSION__ < "3.2.9"
+ args=filter(args,#'_grep_filter);
+#else
+ args=filter(args,(: return (valid_write($1,
+ getuid(this_object()),"write_file",this_object())!=0):));
+#endif
+ */
+ args=file_list(args,MODE_GREP,(flags&GREP_R?1:0),"/",mask);
+ if (!sizeof(args))
+ return printf("Keine passenden Dateien gefunden.\n"),1;
+ if (flags&GREP_I) rexpr=lower_case(rexpr);
+ if (flags&GREP_F)
+ {
+ if (file_size("/players/"+getuid()+"/grep.out")==-2||
+ !MAY_WRITE("/players/"+getuid()+"/grep.out"))
+ return printf("grep: Datei /players/%s/grep.out kann nicht "
+ "geschrieben werden.\n",getuid()),1;
+ else
+ write_file("/players/"+getuid()+"/grep.out",
+ "Ausgabe von \"grep " + _unparsed_args() + "\":\n");
+ }
+ asynchron(args,#'grep_file,rexpr,flags,0);
+ return 1;
+}