blob: 596e1b64d0c725281f1ed6c4cb4f5d1f358b89bf [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;
Arathorndb201cc2020-08-28 17:02:38 +0200415 string *input;
MG Mud User88f12472016-06-24 23:31:02 +0200416
Arathorn1facd5f2020-08-28 16:41:17 +0200417 string* args = parseargs(_unparsed_args(), &flags, MAN_OPTS, 0);
418
MG Mud User88f12472016-06-24 23:31:02 +0200419 if (flags==-1 ||
420 (sizeof(args)!=1 &&
421 (sizeof(args)<2 || sizeof(args[1])>1 || !(i=to_int(args[1])))))
422 return USAGE("man [-" MAN_OPTS "] <hilfeseite>");
MG Mud User88f12472016-06-24 23:31:02 +0200423
Arathorn72c7e542020-08-28 16:50:28 +0200424 input = explode(args[0], "/");
425
426 if (oldman_result && sizeof(input)==1 && sizeof(args)==1 &&
427 sizeof(input[0])==1 && (i=to_int(input[0])) &&
Arathornd0a1e662020-08-28 17:01:24 +0200428 member(oldman_result,i))
429 {
Arathorn72c7e542020-08-28 16:50:28 +0200430 input = ({oldman_result[i,0], oldman_result[i,1]});
Arathornd0a1e662020-08-28 17:01:24 +0200431 i = 0;
MG Mud User88f12472016-06-24 23:31:02 +0200432 }
Arathorn72c7e542020-08-28 16:50:28 +0200433 else if (!(flags&(MAN_M|MAN_R)) && sizeof(input)>1)
MG Mud User88f12472016-06-24 23:31:02 +0200434 {
Arathornd0a1e662020-08-28 17:01:24 +0200435 if (file_size(MAND_DOCDIR+args[0]) >= 0)
Arathorn72c7e542020-08-28 16:50:28 +0200436 input = ({input[<1], args[0]});
MG Mud User88f12472016-06-24 23:31:02 +0200437 else
Arathorn72c7e542020-08-28 16:50:28 +0200438 input = ({});
MG Mud User88f12472016-06-24 23:31:02 +0200439 }
440 else
441 {
442 if (flags&MAN_R)
443 {
Arathornd0a1e662020-08-28 17:01:24 +0200444 flags &= (~MAN_M);
445 if (catch(regexp(({""}), args[0])) || !regexp(({""}), args[0]))
446 {
447 printf("man: Ungueltiger Ausdruck in Maske.\n");
448 return 1;
449 }
MG Mud User88f12472016-06-24 23:31:02 +0200450 }
Arathorn72c7e542020-08-28 16:50:28 +0200451 input = ({string *})MAND->locate(args[0], flags&(MAN_M|MAN_R));
Arathorn84dd5f22020-08-28 17:24:44 +0200452 // Sortierung case-insensitive, ggf. vorhandene Pfade dabei ignorieren
453 // Wird fuer die spaetere Ausgabe der Liste benoetigt.
454 input = sort_array(input, function int (string t1, string t2)
455 {
456 t1 = explode(t1, "/")[<1];
457 t2 = explode(t2, "/")[<1];
458 return lower_case(t1) > lower_case(t2);
459 });
MG Mud User88f12472016-06-24 23:31:02 +0200460 }
461
Arathornd0a1e662020-08-28 17:01:24 +0200462 oldman_result = 0;
463
Arathorn131bb742020-08-28 17:05:02 +0200464 if(i && sizeof(input)>2 && sizeof(input) >= i*2)
465 input = input[(i*2-2)..(i*2-1)];
Arathornd0a1e662020-08-28 17:01:24 +0200466
Arathorn72c7e542020-08-28 16:50:28 +0200467 switch (sizeof(input))
MG Mud User88f12472016-06-24 23:31:02 +0200468 {
469 case 0:
Arathornd0a1e662020-08-28 17:01:24 +0200470 printf("Keine Hilfeseite gefunden fuer '%s'.\n", args[0]);
MG Mud User88f12472016-06-24 23:31:02 +0200471 break;
Arathornd0a1e662020-08-28 17:01:24 +0200472
MG Mud User88f12472016-06-24 23:31:02 +0200473 case 2:
474 /*
475 if (flags&MAN_I)
476 {
477 // BRANCH TO MANUALD
478 return 1;
479 }
480 */
Arathorn72c7e542020-08-28 16:50:28 +0200481 printf("Folgende Hilfeseite wurde gefunden: %s\n", input[1]);
482 More(MAND_DOCDIR+input[1], 1);
MG Mud User88f12472016-06-24 23:31:02 +0200483 return 1;
484 default:
Arathorn131bb742020-08-28 17:05:02 +0200485 i = sizeof(input)/2;
Arathorndb201cc2020-08-28 17:02:38 +0200486 string* output = allocate(i);
Arathornd0a1e662020-08-28 17:01:24 +0200487 oldman_result = m_allocate(i, 2);
488 while (i)
MG Mud User88f12472016-06-24 23:31:02 +0200489 {
Arathorn131bb742020-08-28 17:05:02 +0200490 output[i-1] = input[i*2-2];
491 oldman_result[i,0] = input[i*2-2];
492 oldman_result[i,1] = input[i*2-1];
MG Mud User88f12472016-06-24 23:31:02 +0200493 i--;
494 }
Arathorndb5d16d2020-05-11 01:23:18 +0200495
Arathorndb5d16d2020-05-11 01:23:18 +0200496 // Numerierung ergaenzen
Arathorndb201cc2020-08-28 17:02:38 +0200497 foreach(int j : sizeof(output))
Arathornd0a1e662020-08-28 17:01:24 +0200498 {
Arathorndb201cc2020-08-28 17:02:38 +0200499 output[j] = sprintf("%d: %s", j+1, output[j]);
Arathorndb5d16d2020-05-11 01:23:18 +0200500 }
501
502 int tty_cols = QueryProp(P_TTY_COLS)-2;
503 string list = "Es wurden die folgenden, potentiell passenden Seiten "
504 "gefunden:\n";
505
506 // Wer keine Grafik sehen will, bekommt eine andere Anzeige.
Arathornd0a1e662020-08-28 17:01:24 +0200507 if (QueryProp(P_NO_ASCII_ART))
508 {
Arathorndb5d16d2020-05-11 01:23:18 +0200509 // @ als geschuetztes Leerzeichen verwenden, um einen Umbruch
510 // nach den Nummern zu verhindern.
Arathorndb201cc2020-08-28 17:02:38 +0200511 output = map(output, #'regreplace, ": ", ":@", 1);
512 list += break_string(implode(output, " "), tty_cols);
Arathorndb5d16d2020-05-11 01:23:18 +0200513 list = regreplace(list, ":@", ": ", 1);
514 }
Arathornd0a1e662020-08-28 17:01:24 +0200515 else
516 {
Arathorndb5d16d2020-05-11 01:23:18 +0200517 // Anzahl Spalten ausrechnen: Terminalbreite / Laenge des laengsten
Arathorndb201cc2020-08-28 17:02:38 +0200518 // Elements in <output>. Kann der Spaltenmodus von sprintf() an sich
Arathorndb5d16d2020-05-11 01:23:18 +0200519 // selbst, das liefert aber nicht immer so guenstige Ergebnisse.
Arathorndb201cc2020-08-28 17:02:38 +0200520 int maxwidth = max(map(output, #'sizeof));
Arathorndb5d16d2020-05-11 01:23:18 +0200521 int tablecols = tty_cols/maxwidth;
522 list += "-"*tty_cols+"\n"+
Arathorndb201cc2020-08-28 17:02:38 +0200523 sprintf("%#-*.*s\n", tty_cols, tablecols, implode(output,"\n"))+
Arathorndb5d16d2020-05-11 01:23:18 +0200524 "-"*tty_cols+"\n";
525 }
526 printf(list);
MG Mud User88f12472016-06-24 23:31:02 +0200527 break;
528 }
529 return 1;
530}
531
532// ########
533//############################### RMAN ##################################
534// ########
535
536static int _rman(string str)
537{
538 int flags;
539 string *args;
540
541 str=_unparsed_args();
542 args=parseargs(str,&flags,"",0);
543 if (flags==-1||sizeof(args)!=2)
544 return USAGE("rman <hilfeseite> <mudname>");
545 write("man: " +
Vanion50652322020-03-10 21:13:25 +0100546 ({string})call_other(UDP_CMD_DIR+"man","send_request",args[1],args[0]));
MG Mud User88f12472016-06-24 23:31:02 +0200547 return 1;
548}
549
550
551// #############
552//############################# SHOWPROPS ###############################
553// #############
554
555//
556// _showprops: Zeigt Properties zu einem Objekt an
557//
558
559static int _showprops(string str)
560{
561 int i;
562 string *list, ausgabe;
563
564 if (str) {
565 if (str[0]!='/') str="/"+str;
566 if (str[0..4]!="/std/")
567 {
568 printf("showprops: Es koennen nur Properties von Objekten "
569 "aus /std/ angezeigt werden.\n");
570 return 1;
571 }
572 if (str[<1]=='.') str+="c";
573 if (str[<2..<1]!=".c") str+=".c";
574 if (file_size(str)<0)
575 {
576 printf("showprops: %s: Es gibt kein Objekt diesen Namens.\n",str[0..<3]);
577 return 1;
578 }
Zesstraefad7be2018-11-06 23:18:30 +0100579 if (catch(load_object(str)))
MG Mud User88f12472016-06-24 23:31:02 +0200580 {
581 printf("showprops: %s: Datei konnte nicht geladen werden.\n",str);
582 return 1;
583 }
584 }
585 if (!str || !find_object(str)) {
586 notify_fail("Welche Properties moechtest Du sehen?"
587 " Bsp.: <showprops /std/npc>\n");
588 return 0;
589 }
590 list=inherit_list(find_object(str));
MG Mud User88f12472016-06-24 23:31:02 +0200591 list=map(list,(: return $1[5..<2]+"h"; :));
592 list+=map(list,(: return explode($1,"/")[<1]; :));
593 list=map(m_indices(mkmapping(list)),(: return "/sys/"+$1; :));
594 list=filter(list,(: return file_size($1)>0; :));
MG Mud User88f12472016-06-24 23:31:02 +0200595 list=sort_array(list, #'<);
596 ausgabe="";
597 for (i=sizeof(list);i--;)
598 {
MG Mud User88f12472016-06-24 23:31:02 +0200599 str=implode(filter(explode(read_file(list[i]),"\n"),
600 (: return $1[0..9]=="#define P_";:)),"\n");
MG Mud User88f12472016-06-24 23:31:02 +0200601 if (str!="") ausgabe+=sprintf("%s\n%s\n\n", list[i], str);
602 }
603 if (ausgabe!="")
604 More(ausgabe);
605 else
606 printf("Keine Property-Definitionen zu diesem Objekt gefunden!\n");
607 return 1;
608}
609
610// ########
611//############################### GREP ###################################
612// ########
613
MG Mud User88f12472016-06-24 23:31:02 +0200614//
615// grep_file: Datei greppen
616// rexpr: Regular Expression
617// flags: Flags
618//
619
620private int grep_file(mixed filedata, string rexpr, int flags)
621{
Zesstrac70bf582019-11-26 00:43:17 +0100622 string fullname=filedata[FULLNAME];
MG Mud User88f12472016-06-24 23:31:02 +0200623 if ((flags&GREP_F)&&fullname=="/players/"+getuid()+"/grep.out")
Zesstraefad7be2018-11-06 23:18:30 +0100624 {
625 write_file("/players/"+getuid()+"/grep.out",
626 "Uebergehe grep.out ...\n");
627 return RET_FAIL;
MG Mud User88f12472016-06-24 23:31:02 +0200628 }
629 switch(filedata[FILESIZE])
630 {
Zesstraefad7be2018-11-06 23:18:30 +0100631 case FSIZE_DIR: return RET_FAIL;
632 case FSIZE_NOFILE: return ERROR(DOESNT_EXIST,fullname,RET_FAIL);
MG Mud User88f12472016-06-24 23:31:02 +0200633 case 0: return RET_FAIL;
634 default: break;
635 }
Zesstraefad7be2018-11-06 23:18:30 +0100636 if (!MAY_READ(fullname))
637 return ERROR(NO_READ,fullname,RET_FAIL);
Zesstrac70bf582019-11-26 00:43:17 +0100638
639 // Bei case-insensitiver Suche das Pattern in Kleinschreibung wandeln
MG Mud User88f12472016-06-24 23:31:02 +0200640 if (flags&GREP_I)
641 rexpr=lower_case(rexpr);
Zesstrac70bf582019-11-26 00:43:17 +0100642
643 // Portionsweise das komplette File einlesen.
644 int maxlen = query_limits()[LIMIT_BYTE];
645 int ptr;
646 bytes read_buffer;
647 bytes data = b"";
648 while (sizeof(read_buffer = read_bytes(fullname, ptr, maxlen)))
MG Mud User88f12472016-06-24 23:31:02 +0200649 {
Zesstrac70bf582019-11-26 00:43:17 +0100650 data += read_buffer;
651 ptr += sizeof(read_buffer);
652 // die Schleifenbedingung erkennt zwar auch, wenn das File vollstaendig
653 // ist, aber wir koennen den Speicherzugriff auch einsparen und schauen,
654 // ob wir schon alles haben.
655 if (ptr >= filedata[FILESIZE])
656 break;
MG Mud User88f12472016-06-24 23:31:02 +0200657 }
Zesstrac70bf582019-11-26 00:43:17 +0100658 // In string konvertieren, wir gehen davon aus, das File ist UTF8-kodiert.
659 string text = to_text(data, "UTF-8");
660 string *lines = explode(text, "\n");
661 int count; // Anzahl Zeilen mit Treffern
662 <string|string*> result = ({}); // zutreffende Zeilen
663 int linecount = 1;
664 foreach(string line: lines)
MG Mud User88f12472016-06-24 23:31:02 +0200665 {
Zesstrac70bf582019-11-26 00:43:17 +0100666 string orig_line = line;
667 // Suche case-insensitive?
668 if (flags&GREP_I)
669 line = lower_case(line);
670 int match = regmatch(line, rexpr) != 0;
671 if (flags&GREP_V) match = !match; // Match ggf. invertieren
MG Mud User88f12472016-06-24 23:31:02 +0200672 if (match)
673 {
Zesstrac70bf582019-11-26 00:43:17 +0100674 // Ausgeben oder nicht?
675 if (!(flags&GREP_C))
MG Mud User88f12472016-06-24 23:31:02 +0200676 {
Zesstrac70bf582019-11-26 00:43:17 +0100677 // Mit Zeilennummer?
678 if (flags&GREP_N)
679 result+=({ sprintf("%4d %s", linecount, orig_line)});
MG Mud User88f12472016-06-24 23:31:02 +0200680 else
Zesstrac70bf582019-11-26 00:43:17 +0100681 result+=({orig_line});
MG Mud User88f12472016-06-24 23:31:02 +0200682 }
Zesstrac70bf582019-11-26 00:43:17 +0100683 ++count;
MG Mud User88f12472016-06-24 23:31:02 +0200684 }
Zesstrac70bf582019-11-26 00:43:17 +0100685 ++linecount;
MG Mud User88f12472016-06-24 23:31:02 +0200686 }
Zesstrac70bf582019-11-26 00:43:17 +0100687
MG Mud User88f12472016-06-24 23:31:02 +0200688 if (count)
689 {
Zesstrac70bf582019-11-26 00:43:17 +0100690 // Bei -h werden die Dateinamen unterdrueckt.
691 if (flags&GREP_H)
692 fullname="";
MG Mud User88f12472016-06-24 23:31:02 +0200693 else
Zesstrac70bf582019-11-26 00:43:17 +0100694 fullname=sprintf("%s ",fullname);
695
696 if (flags&GREP_C)
697 result=sprintf("%s%d passende Zeile%s.\n",fullname, count,
698 (count==1?"":"n"));
699 else
700 result = ( (sizeof(fullname) ? fullname + "\n" : "")
701 + implode(result,"\n") + "\n");
Zesstrac70bf582019-11-26 00:43:17 +0100702
Zesstra77c0bf22020-01-07 22:27:27 +0100703 // Ergebnis ausgeben in File oder an Magier
704 if (flags&GREP_F)
705 return write_file("/players/"+getuid()+"/grep.out",result);
706 write(result);
707 }
MG Mud User88f12472016-06-24 23:31:02 +0200708 return RET_OK;
709}
710
711static int _grep(string cmdline)
712{
713 string rexpr,mask;
714 mixed *args;
715 int flags;
716 cmdline=_unparsed_args();
717 args=parseargs(cmdline,&flags,GREP_OPTS,0);
718 if ((flags==-1)||!sizeof(args))
719 return USAGE("grep [-" GREP_OPTS
720 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
721 rexpr=args[0];
722 if (catch(regexp(({""}),rexpr))||!regexp(({""}),rexpr))
723 return printf("grep: Ungueltiger Suchausdruck: %s\n",rexpr) ,1;
Zesstracc3f2502018-11-14 23:46:47 +0100724 args=(sizeof(args)>1 ? args[1..] : ({}) );
MG Mud User88f12472016-06-24 23:31:02 +0200725 if (flags&GREP_M)
726 {
727 mask=args[<1];
Zesstracc3f2502018-11-14 23:46:47 +0100728 if (sizeof(args) > 2)
729 args = (sizeof(args) > 1 ? args[0..<2] : ({}) );
MG Mud User88f12472016-06-24 23:31:02 +0200730 }
731 if (!sizeof(args))
732 return USAGE("grep [-" GREP_OPTS
733 "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
734 args=map(args,#'to_filename)-({0});
MG Mud User88f12472016-06-24 23:31:02 +0200735 args=file_list(args,MODE_GREP,(flags&GREP_R?1:0),"/",mask);
736 if (!sizeof(args))
737 return printf("Keine passenden Dateien gefunden.\n"),1;
738 if (flags&GREP_I) rexpr=lower_case(rexpr);
739 if (flags&GREP_F)
740 {
Zesstraefad7be2018-11-06 23:18:30 +0100741 if (file_size("/players/"+getuid()+"/grep.out")==FSIZE_DIR
742 || !MAY_WRITE("/players/"+getuid()+"/grep.out"))
MG Mud User88f12472016-06-24 23:31:02 +0200743 return printf("grep: Datei /players/%s/grep.out kann nicht "
Zesstraefad7be2018-11-06 23:18:30 +0100744 "geschrieben werden.\n",getuid()),1;
MG Mud User88f12472016-06-24 23:31:02 +0200745 else
746 write_file("/players/"+getuid()+"/grep.out",
747 "Ausgabe von \"grep " + _unparsed_args() + "\":\n");
748 }
749 asynchron(args,#'grep_file,rexpr,flags,0);
750 return 1;
751}