/** /daemon/command.c
* from the Nightmare IVr1 Object Library
* a new commands daemon, much faster than the old
* created by Descartes of Borg 940119
* Hacked for Discworld by Turrican 9-11-95
*/
#include <command.h>
#include <user_parser.h>
private nosave mapping Commands;
private nosave string *Paths, *GRCommands;
void eventRehash(string *paths);
void create() {
seteuid(getuid());
Commands = ([]);
GRCommands = ({});
Paths = ({});
eventRehash( ({ DIR_PLAYER_CMDS,
DIR_PLAYTESTER_CMDS,
DIR_CREATOR_CMDS,
DIR_SECURE_CREATOR_CMDS,
DIR_LORD_CMDS,
DIR_LIVING_CMDS,
DIR_ADMIN_CMDS,
DIR_SECURE_ADMIN_CMDS,
DIR_GUILD_CMDS,
DIR_PENDING_CMDS }) );
} /* create() */
void eventGuildRaceRehash() {
string *paths, path;
paths = ({ DIR_GUILD_CMDS });
paths += map( filter( unguarded( (: get_dir, DIR_GUILD_CMDS + "/", -1 :) ),
(: $1[1] == -2 :) ), (: DIR_GUILD_CMDS + "/" + $1[0] :) );
GRCommands = ({ });
foreach( path in paths ) {
string *files, cmd;
files = map( unguarded( (: get_dir, path + "/*.c" :) ), (: $1[0..<3] :) );
GRCommands += files;
foreach( cmd in files ) {
if( pointerp(Commands[cmd]) ) {
Commands[cmd] += ({ path });
} else {
Commands[cmd] = ({ path });
}
}
Paths = uniq_array( Paths + ({ path }) );
}
} /* eventGuildRaceRehash() */
void eventRehash( mixed paths ) {
string path;
if( stringp(paths) ) {
paths = ({ paths });
} else if( !pointerp(paths) ) {
return;
}
foreach( path in paths ) {
string file;
if( path[<1..<1] == "/" )
continue;
if( file_size(path) != -2 )
continue;
if( path == DIR_GUILD_CMDS ) {
eventGuildRaceRehash();
continue;
}
foreach( file in unguarded( (: get_dir, path + "/*.c" :) ) ) {
string cmd;
cmd = file[0..<3];
if( pointerp(Commands[cmd]) ) {
Commands[cmd] += ({ path });
} else {
Commands[cmd] = ({ path });
}
}
Paths = uniq_array( Paths + ({ path }) );
}
} /* eventRehash() */
void HandleCommandLine( class command cmd ) {
string args = cmd->args;
int i;
args = replace_string( args, "%^", " " );
if( ( i = strsrch(args, " ") ) != -1 ) {
cmd->verb = args[0..i-1];
cmd->args = args[i+1..];
} else {
cmd->verb = args;
cmd->args = (string)0;
}
} /* HandleCommandLine() */
int strncmp( string s1, string s2, int len ) {
return strcmp( s1[0..len-1], s2[0..len-1] );
} /* strncmp() */
int HandleStars( class command cmd ) {
int i;
string file, *files;
if( Commands[cmd->verb] ) {
/* Yippiee ! No searching needed ! */
return 1;
}
/* Darn. Need to search for shortcuts. */
files = keys(Commands);
files = filter( files, (: (int)$1[0] == $(cmd)->verb[0] :) );
foreach( file in files ) {
string tmpverb, tmpargs = 0, tmpfile = 0;
int len, length;
if( ( i = strsrch(file, "_") ) == -1 ) {
continue;
}
tmpfile = (string)delete( file, i, 1 );
len = strlen(tmpfile);
if( i == len ) {
tmpargs = cmd->verb[i..]+( cmd->args ?
( strlen(cmd->verb) == i ? "" : " " ) + cmd->args : "" );
tmpverb = cmd->verb[0..i-1];
if( strncmp(tmpfile, tmpverb, len) != 0 ) {
continue;
}
} else {
length = strlen(cmd->verb);
if( ( length > len ) || ( length < i ) ) {
continue;
}
if( strncmp(cmd->verb, tmpfile, length) != 0 ) {
continue;
}
}
/* Yay! Found a match! */
cmd->verb = file;
if( stringp(tmpargs) ) {
cmd->args = tmpargs;
}
return 1;
}
return 0;
} /* HandleStars() */
int GetCommand( class command cmd, string *path ) {
string *tmp;
int i;
if( !stringp(cmd->args) ) {
return 0;
}
tmp = ( path & Paths );
if( sizeof( tmp = path - tmp ) ) {
eventRehash(tmp);
}
HandleCommandLine(cmd);
if( HandleStars(cmd) && Commands[cmd->verb] &&
sizeof( tmp = ( path & (string *)Commands[cmd->verb]) ) ) {
cmd->file = sprintf("%s/%s", tmp[0], cmd->verb );
cmd->filepart = cmd->verb;
if( ( i = strsrch(cmd->verb, "_") ) != -1 ) {
cmd->verb = (string)delete( cmd->verb, i, 1 );
}
if( cmd->args && cmd->args == "") {
cmd->args = (string)0;
}
if( file_size(cmd->file+".c") < 0 )
return 1;
if( (cmd->file)->query_patterns() ) {
return 0;
}
return 1;
}
return 0;
} /* GetCommand() */
mixed ReturnPatterns( class command cmd, string *path ) {
mixed *q_patterns;
mixed *r_patterns;
mixed *stuff;
mixed *tmp;
mixed *ret_patterns;
int i, j;
string fname;
tmp = (path & Paths);
tmp = path - tmp;
if( sizeof(tmp) ) {
eventRehash(tmp);
}
if( HandleStars(cmd) && Commands[cmd->verb] ) {
tmp = (path & (string *)Commands[cmd->verb]);
if( tmp ) {
ret_patterns = ({ });
foreach (fname in tmp) {
cmd->file = sprintf("%s/%s", fname, cmd->verb);
//if ((i = strsrch(cmd->verb, "_")) != -1) {
//cmd->verb = (string)delete(cmd->verb, i, 1);
//}
q_patterns = (cmd->file)->query_patterns();
if (!q_patterns) {
return 0;
}
r_patterns = ({ });
for (i = 0; i < sizeof(q_patterns); i += 2) {
if (q_patterns[i+1] && !functionp(q_patterns[i+1])) {
continue;
}
stuff = (mixed *)PATTERN_OB->query_pattern(q_patterns[i]);
j = 0;
while (j < sizeof(r_patterns) &&
r_patterns[j][PATTERN_WEIGHT] >= stuff[0]) {
j++;
}
r_patterns = r_patterns[0..j-1] +
({ ({ stuff[0], q_patterns[i], 0, find_object(cmd->file),
q_patterns[i+1] }) }) + r_patterns[j..];
}
ret_patterns += r_patterns;
}
return ret_patterns;
}
}
return 0;
} /* ReturnPatterns() */
mixed *GetCommandPatterns(string cmd_name, string *path) {
class command cmd;
mixed *stuff;
cmd = new(class command);
cmd->verb = cmd_name;
cmd->args = 0;
stuff = ReturnPatterns(cmd, path);
return stuff;
} /* GetCommandPatterns() */
varargs string *GetCommands(string path) {
string *paths, *tmp;
string cmd;
if (!path) {
return keys(Commands);
}
tmp = ({ });
foreach (cmd, paths in Commands) {
if (member_array(path, paths) != -1) {
tmp += ({ cmd });
}
}
return tmp;
} /* GetCommands() */
varargs string *GetPaths(string cmd) {
if (cmd) {
string *paths;
class command tmp;
if (sizeof(paths = Commands[cmd])) {
return paths;
}
tmp = new(class command, verb : cmd);
if (HandleStars(tmp)) {
return Commands[tmp->verb];
} else {
return 0;
}
}
return Paths;
} /* GetPaths() */
int IsGRCommand(string cmd) {
if (member_array(cmd, GRCommands) != -1) {
return 1;
} else {
class command tmp = new(class command, verb : cmd);
if (HandleStars(tmp)) {
return (member_array(tmp->verb, GRCommands) != -1);
}
}
} /* IsGRCommand() */