/* grep command, trial out by Turrican for a commands daemon. */
/* Added some safety checks -- Sin */
#include <runtime_config.h>
inherit COMMAND_BASE;
int check_size(string s1, string s2, string tag)
{
if (strlen(s1) + strlen(s2) > get_config(__MAX_STRING_LENGTH__)) {
#ifdef DEBUG
log_file("GREP_ERRORS",
sprintf("Grep of %s produced excessively large string\n", tag));
#endif
printf("Results are too big\n");
return 1;
}
return 0;
}
mixed cmd(string words) {
int i, j, size;
string found, output, pattern, *files, *lines, *match, temp;
seteuid( geteuid( this_player() ) );
if ( !words || ( words == "" ) )
return notify_fail( "Syntax: grep <pattern> <files>\n" );
if ( sscanf( words, "%s %s", pattern, words ) != 2 )
return notify_fail( "Syntax: grep <pattern> <files>\n" );
files = this_player()->get_files( words );
if ( !sizeof( files ) )
return notify_fail( "File(s) "+ words +" not found.\n" );
output = "";
for ( i = 0; i < sizeof( files ); i++ ) {
found = "";
if ((size = file_size( files[ i ] )) > 0) {
if (size > get_config(__MAX_READ_FILE_SIZE__) ||
size > get_config(__MAX_STRING_LENGTH__)) {
#ifdef letsnot
/* This is horribly slow. You really don't want this to happen
* since it freezes the mud as well. *sigh* */
j = 1;
while ((line = read_file(files[i], j++, 1)) != 0) {
if (regexp(({ line }), pattern) != ({}))
found += sprintf("%5d: %s", j-1, line);
}
if ( found != "" )
output += files[ i ] +"\n"+ found;
continue;
#endif
temp = sprintf("File %s is too big.\n", files[i]);
if (check_size(output, temp, words))
return 1;
output += temp;
continue;
}
if (!read_bytes(files[i], 0, 1)) {
#ifdef DEBUG
log_file("GREP_ERRORS", sprintf("File %s made grep barf.\n",
files[i]));
#endif
temp = sprintf("File %s is not an ASCII file.\n", files[i]);
if (check_size(output, temp, words))
return 1;
output += temp;
continue;
}
/* We can crash on the next line if the file contains more than
* get_config(__MAX_ARRAY_SIZE__) lines (currently 15,000).
* I don't really see a way to count the number of lines
* before calling explode. But if there are too many lines,
* explode will crash the mud. Looping on strsrch() seems to
* be excessively slow. Leave this as an open bug until
* someone comes up with an idea. */
lines = explode(read_file(files[i]), "\n");
if (sizeof(lines) > get_config(__MAX_ARRAY_SIZE__) / 2) {
#ifdef DEBUG
log_file("GREP_ERRORS",
sprintf("File %s has too many lines to grep.\n",
files[i]));
#endif
temp = sprintf("File %s is too big.\n", files[i]);
if (check_size(output, temp, words))
return 1;
output += temp;
continue;
}
match = regexp(lines, pattern, 1);
size = sizeof(match);
for (j = 0; j < size; j+=2) {
temp = sprintf("%5d: %s\n", match[j+1], match[j]);
if (check_size(found, temp, words))
return 1;
found += temp;
}
if ( found != "" ) {
temp = files[ i ] +"\n"+ found;
if (check_size(output, temp, words))
return 1;
output += temp;
}
}
}
if ( output != "" )
this_player()->more_string( output, "Grep" );
else
printf( "Pattern not found.\n" );
return 1;
}