/***************************************************************************** * DikuMUD (C) 1990, 1991 by: * * Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen, * * and Katja Nyboe. * *---------------------------------------------------------------------------* * MERC 2.1 (C) 1992, 1993 by: * * Michael Chastain, Michael Quan, and Mitchell Tse. * *---------------------------------------------------------------------------* * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider. * * Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, * * gorog, Grishnakh, Nivek, Tricops, and Fireblade. * *---------------------------------------------------------------------------* * SMAUG 1.7 FUSS by: Samson and others of the SMAUG community. * * Their contributions are greatly appreciated. * *---------------------------------------------------------------------------* * LoP (C) 2006, 2007, 2008 by: the LoP team. * *****************************************************************************/ #include <stdio.h> #include <string.h> #include "h/mud.h" CMDTYPE *find_command( char *command ) { CMDTYPE *cmd; int hash; if( !command || command[0] == '\0' ) return NULL; hash = LOWER( command[0] ) % 126; for( cmd = command_hash[hash]; cmd; cmd = cmd->next ) if( !str_prefix( command, cmd->name ) ) return cmd; return NULL; } /* Check for the exact command used in creation/renaming */ CMDTYPE *find_exact_command( char *command ) { CMDTYPE *cmd; int hash; if( !command || command[0] == '\0' ) return NULL; hash = LOWER( command[0] ) % 126; for( cmd = command_hash[hash]; cmd; cmd = cmd->next ) if( !str_cmp( command, cmd->name ) ) return cmd; return NULL; } void fread_command( FILE *fp ) { const char *word; bool fMatch; CMDTYPE *command; char *infoflags, flag[MSL]; int value; CREATE( command, CMDTYPE, 1 ); command->lag_count = 0; /* can't have caused lag yet... FB */ xCLEAR_BITS( command->flags ); for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = false; switch( UPPER( word[0] ) ) { case '*': fMatch = true; fread_to_eol( fp ); break; case 'C': KEY( "Code", command->fun_name, STRALLOC( fread_word( fp ) ) ); break; case 'E': if ( !str_cmp( word, "End" ) ) { if( !command->name ) { bug( "%s: Name not found", __FUNCTION__ ); free_command( command ); return; } if( !command->fun_name ) { bug( "%s: No function name supplied for %s", __FUNCTION__, command->name ); free_command( command ); return; } /* * Mods by Trax * Fread in code into char* and try linkage here then * deal in the "usual" way I suppose.. */ command->do_fun = skill_function( command->fun_name ); if( command->do_fun == skill_notfound ) { bug( "%s: Function %s not found for %s", __FUNCTION__, command->fun_name, command->name ); free_command( command ); return; } add_command( command ); return; } break; case 'F': WEXTKEY( "Flags", command->flags, fp, cmd_flags, CMD_MAX ); break; case 'L': KEY( "Log", command->log, fread_number( fp ) ); break; case 'N': KEY( "Name", command->name, fread_string( fp ) ); break; case 'P': SKEY( "Position", command->position, fp, pos_names, POS_MAX ); SKEY( "Perm", command->perm, fp, perms_flag, PERM_MAX ); break; } if( !fMatch ) { bug( "%s: no match: %s", __FUNCTION__, word ); fread_to_eol( fp ); } } } void load_commands( void ) { FILE *fp; if( !( fp = fopen( COMMAND_FILE, "r" ) ) ) return; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "%s: # not found, (%c) found instead.", __FUNCTION__, letter ); break; } word = fread_word( fp ); if( !str_cmp( word, "COMMAND" ) ) { fread_command( fp ); continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "%s: bad section (%s).", __FUNCTION__, word ); continue; } } fclose( fp ); fp = NULL; } void save_commands( void ) { FILE *fp; CMDTYPE *command; int x; bool found = false; if( !( fp = fopen( COMMAND_FILE, "w" ) ) ) { bug( "%s: Can't open %s for writing", __FUNCTION__, COMMAND_FILE ); perror( COMMAND_FILE ); return; } for( x = 0; x < 126; x++ ) { for( command = command_hash[x]; command; command = command->next ) { if( !command->name || command->name[0] == '\0' ) { bug( "%s: blank command in hash bucket %d", __FUNCTION__, x ); continue; } found = true; fprintf( fp, "#COMMAND\n" ); fprintf( fp, "Name %s~\n", command->name ); fprintf( fp, "Code %s\n", command->fun_name ? command->fun_name : "" ); fprintf( fp, "Position %s~\n", pos_names[command->position] ); fprintf( fp, "Perm %s~\n", perms_flag[command->perm] ); fprintf( fp, "Log %d\n", command->log ); if( !xIS_EMPTY( command->flags ) ) fprintf( fp, "Flags %s~\n", ext_flag_string( &command->flags, cmd_flags ) ); fprintf( fp, "End\n\n" ); } } fprintf( fp, "#END\n" ); fclose( fp ); fp = NULL; if( !found ) remove_file( COMMAND_FILE ); } void free_command( CMDTYPE *command ) { STRFREE( command->name ); STRFREE( command->fun_name ); DISPOSE( command ); } void free_commands( void ) { CMDTYPE *command, *cmd_next; int hash; for( hash = 0; hash < 126; hash++ ) { for( command = command_hash[hash]; command; command = cmd_next ) { cmd_next = command->next; command->next = NULL; command->do_fun = NULL; free_command( command ); } } } void unlink_command( CMDTYPE *command ) { CMDTYPE *tmp, *tmp_next; int hash; if( !command ) { bug( "%s: NULL command", __FUNCTION__ ); return; } if( !command->name || command->name[0] == '\0' ) { bug( "%s: command with invalid name", __FUNCTION__ ); return; } hash = command->name[0] % 126; if( command == ( tmp = command_hash[hash] ) ) { command_hash[hash] = tmp->next; return; } for( ; tmp; tmp = tmp_next ) { tmp_next = tmp->next; if( command == tmp_next ) { tmp->next = tmp_next->next; return; } } } void add_command( CMDTYPE *command ) { int hash, x; CMDTYPE *tmp, *prev; if( !command ) { bug( "%s: NULL command", __FUNCTION__ ); return; } if( !command->name ) { bug( "%s: NULL command->name", __FUNCTION__ ); return; } if( !command->do_fun ) { bug( "%s: NULL command->do_fun", __FUNCTION__ ); return; } for( x = 0; command->name[x] != '\0'; x++ ) command->name[x] = LOWER( command->name[x] ); hash = command->name[0] % 126; if( !( prev = tmp = command_hash[hash] ) ) { command->next = command_hash[hash]; command_hash[hash] = command; return; } for( ; tmp; tmp = tmp->next ) { if( !tmp->next ) { tmp->next = command; command->next = NULL; } } } void do_cedit( CHAR_DATA *ch, char *argument ) { CMDTYPE *command; char arg1[MIL], arg2[MIL]; set_char_color( AT_IMMORT, ch ); argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if( !arg1 || arg1[0] == '\0' ) { send_to_char( "Usage: cedit save cmdtable\r\n", ch ); if( get_trust( ch ) >= PERM_HEAD ) { send_to_char( "Usage: cedit save cmdtable\r\n", ch ); send_to_char( "Usage: cedit <command> create [code]\r\n", ch ); send_to_char( "Usage: cedit <command> [field] [values]\r\n", ch ); send_to_char( " Fields: delete show raise lower list perm position log code flags\r\n", ch ); } return; } if( get_trust( ch ) >= PERM_HEAD && !str_cmp( arg1, "save" ) && !str_cmp( arg2, "cmdtable" ) ) { save_commands( ); send_to_char( "Saved.\r\n", ch ); return; } command = find_command( arg1 ); if( get_trust( ch ) >= PERM_HEAD && !str_cmp( arg2, "create" ) ) { /* Reget the command but this time check for the exact command */ if( ( command = find_exact_command( arg1 ) ) ) { send_to_char( "That command already exists!\r\n", ch ); return; } CREATE( command, CMDTYPE, 1 ); command->lag_count = 0; /* FB */ command->name = STRALLOC( arg1 ); command->perm = get_trust( ch ); if( *argument ) one_argument( argument, arg2 ); else snprintf( arg2, sizeof( arg2 ), "do_%s", arg1 ); command->do_fun = skill_function( arg2 ); command->fun_name = STRALLOC( arg2 ); add_command( command ); send_to_char( "Command added.\r\n", ch ); if( command->do_fun == skill_notfound ) ch_printf( ch, "Code %s not found. Set to no code.\r\n", arg2 ); return; } if( !command ) { send_to_char( "Command not found.\r\n", ch ); return; } else if( command->perm > get_trust( ch ) ) { send_to_char( "You can't touch this command.\r\n", ch ); return; } if( !arg2 || arg2[0] == '\0' || !str_cmp( arg2, "show" ) ) { ch_printf( ch, "Command: %s\r\n", command->name ); ch_printf( ch, "Perm: %s\r\n", perms_flag[command->perm] ); ch_printf( ch, "Position: %s\r\n", pos_names[command->position] ); ch_printf( ch, "Log: %d\r\n", command->log ); ch_printf( ch, "Code: %s\r\n", command->fun_name ); ch_printf( ch, "Flags: %s\r\n", ext_flag_string( &command->flags, cmd_flags ) ); if( command->userec.num_uses ) send_timer( &command->userec, ch ); return; } if( get_trust( ch ) < PERM_HEAD ) { do_cedit( ch, "" ); return; } if( !str_cmp( arg2, "raise" ) ) { CMDTYPE *tmp, *tmp_next; int hash = command->name[0] % 126; if( ( tmp = command_hash[hash] ) == command ) { send_to_char( "That command is already at the top.\r\n", ch ); return; } if( tmp->next == command ) { command_hash[hash] = command; tmp_next = tmp->next; tmp->next = command->next; command->next = tmp; ch_printf( ch, "Moved %s above %s.\r\n", command->name, command->next->name ); return; } for( ; tmp; tmp = tmp->next ) { tmp_next = tmp->next; if( tmp_next->next == command ) { tmp->next = command; tmp_next->next = command->next; command->next = tmp_next; ch_printf( ch, "Moved %s above %s.\r\n", command->name, command->next->name ); return; } } send_to_char( "ERROR -- Not Found!\r\n", ch ); return; } if( !str_cmp( arg2, "lower" ) ) { CMDTYPE *tmp, *tmp_next; int hash = command->name[0] % 126; if( !command->next ) { send_to_char( "That command is already at the bottom.\r\n", ch ); return; } tmp = command_hash[hash]; if( tmp == command ) { tmp_next = tmp->next; command_hash[hash] = command->next; command->next = tmp_next->next; tmp_next->next = command; ch_printf( ch, "Moved %s below %s.\r\n", command->name, tmp_next->name ); return; } for( ; tmp; tmp = tmp->next ) { if( tmp->next == command ) { tmp_next = command->next; tmp->next = tmp_next; command->next = tmp_next->next; tmp_next->next = command; ch_printf( ch, "Moved %s below %s.\r\n", command->name, tmp_next->name ); return; } } send_to_char( "ERROR -- Not Found!\r\n", ch ); return; } if( !str_cmp( arg2, "list" ) ) { CMDTYPE *tmp; int hash = command->name[0] % 126; int col = 0; pager_printf( ch, "Priority placement for [%s]:\r\n", command->name ); for( tmp = command_hash[hash]; tmp; tmp = tmp->next ) { pager_printf( ch, " %s%-12s", tmp == command ? "&[green]" : "&[plain]", tmp->name ); if( ++col == 6 ) { send_to_pager( "\r\n", ch ); col = 0; } } if( col != 0 ) send_to_pager( "\r\n", ch ); return; } if( !str_cmp( arg2, "delete" ) ) { unlink_command( command ); free_command( command ); send_to_char( "Deleted.\r\n", ch ); return; } if( !str_cmp( arg2, "code" ) ) { DO_FUN *fun = skill_function( argument ); if( fun == skill_notfound ) { send_to_char( "Code not found.\r\n", ch ); return; } command->do_fun = fun; STRSET( command->fun_name, argument ); send_to_char( "Code Set.\r\n", ch ); return; } if( !str_cmp( arg2, "perm" ) ) { int level; if( is_number( argument ) ) level = atoi( argument ); else level = get_flag( argument, perms_flag, PERM_MAX ); if( level < 0 || level > get_trust( ch ) || level >= PERM_MAX ) { send_to_char( "Permission out of range.\r\n", ch ); return; } command->perm = level; send_to_char( "Perm Set.\r\n", ch ); return; } if( !str_cmp( arg2, "log" ) ) { int clog = atoi( argument ); if( clog < 0 || clog > LOG_COMM ) { send_to_char( "Log out of range.\r\n", ch ); return; } command->log = clog; send_to_char( "Log Set.\r\n", ch ); return; } if( !str_cmp( arg2, "position" ) ) { int position; position = get_flag( argument, pos_names, POS_MAX ); if( position < 0 || position > POS_DRAG ) { send_to_char( "Position out of range.\r\n", ch ); return; } command->position = position; send_to_char( "Position Set.\r\n", ch ); return; } if( !str_cmp( arg2, "flags" ) ) { int value; char flag[MSL]; while( argument && argument[0] != '\0' ) { argument = one_argument( argument, flag ); value = get_flag( flag, cmd_flags, CMD_MAX ); if( value < 0 || value >= CMD_MAX ) ch_printf( ch, "Unknown flag %s.\r\n", flag ); else xTOGGLE_BIT( command->flags, value ); } send_to_char( "Flags Set.\r\n", ch ); return; } if( !str_cmp( arg2, "name" ) ) { bool relocate; CMDTYPE *checkcmd; one_argument( argument, arg1 ); if( !arg1 || arg1[0] == '\0' ) { send_to_char( "Can't clear name field!\r\n", ch ); return; } if( ( checkcmd = find_exact_command( arg1 ) ) ) { ch_printf( ch, "There is already a command named %s.\r\n", arg1 ); return; } if( arg1[0] != command->name[0] ) { unlink_command( command ); relocate = true; } else relocate = false; STRSET( command->name, arg1 ); if( relocate ) add_command( command ); send_to_char( "Name Set.\r\n", ch ); return; } do_cedit( ch, "" ); } CMDF( do_commands ) { char arg[MIL], arg2[MIL]; int col = 0, cnt = 0, hash, level, minlevel, maxlevel; bool found, dislevel, changecolor = true, showhidden = false; CMDTYPE *command; set_pager_color( AT_PLAIN, ch ); argument = one_argument( argument, arg ); if( arg && arg[0] != '\0' && !str_cmp( arg, "showhidden" ) && get_trust( ch ) >= PERM_IMM ) { argument = one_argument( argument, arg ); showhidden = true; } argument = one_argument( argument, arg2 ); if( arg && arg[0] != '\0' && is_number( arg ) ) minlevel = URANGE( 0, atoi( arg ), PERM_MAX ); else minlevel = 0; if( arg2 && arg2[0] != '\0' && is_number( arg2 ) ) maxlevel = URANGE( minlevel, atoi( arg2 ), MAX_LEVEL ); else if( arg && arg[0] != '\0' && is_number( arg ) ) maxlevel = minlevel; else maxlevel = ( PERM_MAX - 1 ); found = false; for( level = minlevel; level <= maxlevel; level++ ) { dislevel = true; col = 0; for( hash = 0; hash < 126; hash++ ) { for( command = command_hash[hash]; command; command = command->next ) { if( command->perm != level ) continue; if( command->perm > get_trust( ch ) ) continue; if( arg && arg[0] != '\0' && !is_number( arg ) && command->name && command->name[0] != '\0' && str_prefix( arg, command->name ) ) continue; if( xIS_SET( command->flags, CMD_FLAG_NOSHOW ) && !showhidden ) continue; if( !is_npc( ch ) && xIS_SET( command->flags, CMD_FLAG_NPC ) && !showhidden ) continue; if( is_npc( ch ) && xIS_SET( command->flags, CMD_FLAG_PC ) && !showhidden ) continue; found = true; cnt++; if( dislevel ) { dislevel = false; pager_printf( ch, "\r\n&W[Permission &C%s&W]\r\n", perms_flag[level] ); changecolor = true; } if( xIS_SET( command->flags, CMD_FLAG_NOSHOW ) || xIS_SET( command->flags, CMD_FLAG_NPC ) || xIS_SET( command->flags, CMD_FLAG_PC ) ) { send_to_pager( "&R", ch ); changecolor = true; } else if( changecolor ) { send_to_pager( "&C", ch ); changecolor = false; } pager_printf( ch, "%-16s", command->name ); if( ++col == 5 ) { send_to_pager( "\r\n", ch ); col = 0; } } } if( col != 0 ) send_to_pager( "\r\n", ch ); } if( col != 0 ) send_to_pager( "\r\n", ch ); if( arg && arg[0] != '\0' ) { if( is_number( arg ) ) { if( !found ) pager_printf( ch, "&WNo command found from level &C%d &Wto &C%d&W.&D\r\n", minlevel, maxlevel ); else pager_printf( ch, "&C%d &Wcommands found from level &C%d &Wto &C%d&W.&D\r\n", cnt, minlevel, maxlevel ); } else { if( !found ) pager_printf( ch, "&WNo command found under &C%s&W.&D\r\n", arg ); else pager_printf( ch, "&C%d &Wcommands found under &C%s&W.&D\r\n", cnt, arg ); } } else { if( !found ) send_to_pager( "&WNo commands found at all.&D\r\n", ch ); else pager_printf( ch, "&C%d &Wcommands found in all.&D\r\n", cnt ); } } CMDF( do_restrict ) { char arg[MIL], arg2[MIL], buf[MSL]; short level, hash; CMDTYPE *cmd; bool found = false, canrestrict = false; if( !ch ) return; set_char_color( AT_IMMORT, ch ); argument = one_argument( argument, arg ); if( !arg || arg[0] == '\0' ) { send_to_char( "Restrict which command?\r\n", ch ); return; } argument = one_argument( argument, arg2 ); if( !arg || arg2[0] == '\0' ) level = get_trust( ch ); else level = get_flag( arg2, perms_flag, PERM_MAX ); if( level < 0 || level > get_trust( ch ) ) { send_to_char( "You can't restrict it to that permission level.\r\n", ch ); return; } level = URANGE( 0, level, get_trust( ch ) ); hash = arg[0] % 126; for( cmd = command_hash[hash]; cmd; cmd = cmd->next ) { if( !str_prefix( arg, cmd->name ) ) { found = true; if( cmd->perm <= get_trust( ch ) ) { canrestrict = true; break; } } } if( !found ) ch_printf( ch, "No command found for (%s).\r\n", arg ); else if( !canrestrict ) send_to_char( "You may not restrict that command.\r\n", ch ); else { if( !str_prefix( arg2, "show" ) ) { snprintf( buf, sizeof( buf ), "%s show", cmd->name ); do_cedit( ch, buf ); return; } cmd->perm = level; ch_printf( ch, "You restrict %s to %s\r\n", cmd->name, perms_flag[cmd->perm] ); log_printf( "%s restricting %s to %s", ch->name, cmd->name, perms_flag[cmd->perm] ); } }