From 75927aa05fd7b74f1d5b2f5adf5f65ff60e6cccd Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 10 Nov 2011 14:57:54 +0100 Subject: [PATCH] added possibility for subcommands --- src/EventLogger.c | 7 +++--- src/EventLogger.h | 5 ++-- src/commands.c | 6 ++--- src/modcmd.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-- src/modcmd.h | 1 + 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/src/EventLogger.c b/src/EventLogger.c index 097ac95..a71722e 100644 --- a/src/EventLogger.c +++ b/src/EventLogger.c @@ -24,7 +24,7 @@ static struct Event *first_event = NULL, *last_event = NULL; -struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags) { +struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct cmd_binding *command, char **args, int argc, int flags) { struct Event *event = malloc(sizeof(*event)); if (!event) { @@ -35,7 +35,7 @@ struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, st event->user = user; event->chan = chan; event->event_time = time(0); - event->command = strdup(command); + event->command = command; char arguments[MAXLEN]; int argpos = 0; int i; @@ -57,7 +57,7 @@ struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, st void logEvent(struct Event *event) { char fullcmd[MAXLEN]; - sprintf(fullcmd, "%s %s", event->command, event->arguments); + sprintf(fullcmd, "%s %s", event->command->func->name, event->arguments); if((event->flags & CMDFLAG_LOG) && event->chan) { char *auth = ((event->user->flags & USERFLAG_ISAUTHED) ? event->user->auth : "*"); loadChannelSettings(event->chan); @@ -92,7 +92,6 @@ static void destroyEvent(struct Event *event) { if(last->next == NULL) break; last_event = last; } - free(event->command); free(event->arguments); free(event); } diff --git a/src/EventLogger.h b/src/EventLogger.h index 3bc730a..b28c2a5 100644 --- a/src/EventLogger.h +++ b/src/EventLogger.h @@ -21,20 +21,21 @@ struct ClientSocket; struct UserNode; struct ChanNode; +struct cmd_binding; struct Event { struct ClientSocket *client; struct UserNode *user; struct ChanNode *chan; time_t event_time; - char *command; + struct cmd_binding *command; char *arguments; unsigned int flags; /* defined in modcmd.h */ struct Event *next; }; -struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags); +struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct cmd_binding *command, char **args, int argc, int flags); void logEvent(struct Event *event); void destroyEvents(); diff --git a/src/commands.c b/src/commands.c index 07adfac..cece07d 100644 --- a/src/commands.c +++ b/src/commands.c @@ -29,7 +29,7 @@ void register_commands() { USER_COMMAND("version", global_cmd_version, 0, NULL, 0); USER_COMMAND("netinfo", global_cmd_netinfo, 0, NULL, 0); USER_COMMAND("commands", global_cmd_commands, 0, NULL, 0); - USER_COMMAND("command", global_cmd_command, 1, NULL, 0); + USER_COMMAND("command", global_cmd_command, 1, NULL, CMDFLAG_ESCAPE_ARGS); USER_COMMAND("staff", global_cmd_staff, 0, NULL, 0); USER_COMMAND("motd", global_cmd_motd, 0, NULL, 0); #undef USER_COMMAND @@ -44,8 +44,8 @@ void register_commands() { OPER_COMMAND("raw", global_cmd_raw, 1, 800, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); OPER_COMMAND("god", global_cmd_god, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); OPER_COMMAND("reloadlang", global_cmd_reloadlang,1, 500, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("bind", global_cmd_bind, 2, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED); - OPER_COMMAND("unbind", global_cmd_unbind, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED); + OPER_COMMAND("bind", global_cmd_bind, 2, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); + OPER_COMMAND("unbind", global_cmd_unbind, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); OPER_COMMAND("setaccess", global_cmd_setaccess, 2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); OPER_COMMAND("bots", global_cmd_bots, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); #undef OPER_COMMAND diff --git a/src/modcmd.c b/src/modcmd.c index 931c508..f6ff75f 100644 --- a/src/modcmd.c +++ b/src/modcmd.c @@ -68,6 +68,7 @@ static const struct default_language_entry msgtab[] = { {"MODCMD_PRIVILEGED", "$b%s$b is a privileged command."}, /* {ARGS: "god"} */ {"MODCMD_PUBCMD", "Public commands in $b%s$b are restricted."}, /* {ARGS: "#TestChan"} */ {"MODCMD_ACCESS_DENIED", "Access denied."}, + {"MODCMD_SUBCOMMANDS", "Subcommands of %s: %s"}, /* {ARGS: "bot", "ADD, DEL, EDIT"} */ {NULL, NULL} }; @@ -132,6 +133,11 @@ static USERAUTH_CALLBACK(command_checked_auth) { free(cache); } +static CMD_BIND(modcmd_linker) { + //fake command for subcommands + //just empty +} + static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) { struct ChanNode *sent_chan = chan; if(message[0] == '#') { @@ -155,6 +161,38 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s struct cmd_binding *cbind; for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { if(cbind->botid == client->botid && stricmp(cbind->cmd, message) == 0) { + if(cbind->func->func == modcmd_linker) { + //links subcommands + char command[MAXLEN]; + struct cmd_binding *parent_bind = cbind; + if(args) { + char *subcmd = args; + args = strstr(args, " "); + if(args) { + *args = '\0'; + args++; + } + sprintf(command, "%s %s", parent_bind->cmd, subcmd); + for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { + if(cbind->botid == client->botid && stricmp(cbind->cmd, command) == 0) + break; + } + if(!cbind) + break; + } else { + //list all sub commands + int commandlen = sprintf(command, "%s ", parent_bind->cmd); + char subcommands[MAXLEN]; + int subcompos = 0; + for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { + if(cbind->botid == client->botid && stricmplen(cbind->cmd, command, commandlen) == 0) { + subcompos += sprintf(subcommands + subcompos, (subcompos ? ", %s" : "%s"), cbind->cmd + commandlen); + } + } + reply(tmp_text_client, user, "MODCMD_SUBCOMMANDS", parent_bind->cmd, subcommands); + break; + } + } if(statistics_enabled) statistics_commands++; total_triggered++; @@ -170,6 +208,8 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s char *arga[MAXNUMPARAMS]; char **argv; int argc = 0; + int escape = 0; + int offset = 0; if(args) { while(*args) { //skip leading spaces @@ -178,8 +218,22 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s arga[argc++] = args; if (argc >= MAXNUMPARAMS) break; - while (*args != ' ' && *args) + while ((escape || *args != ' ') && *args) { + if((cbind->func->flags & CMDFLAG_ESCAPE_ARGS) && *args == '\\') { + escape = 1; + offset++; + } else if(escape) + escape = 0; + if(!escape && offset) { + args[0 - offset] = args[0]; + } args++; + + } + if(offset) { + args[0-offset] = '\0'; + offset = 0; + } } } argv = arga; @@ -428,7 +482,7 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd); return; } - struct Event *event = createEvent(client, user, chan, cbind->func->name, argv, argc, eventflags); + struct Event *event = createEvent(client, user, chan, cbind, argv, argc, eventflags); cbind->func->func(client, user, chan, argv, argc, event); } @@ -645,6 +699,7 @@ void init_modcmd() { bind_chanmsg(got_chanmsg); bind_privmsg(got_privmsg); register_default_language_table(msgtab); + register_command(0, "linker", modcmd_linker, 0, 0, 0, 0); //fake command for subcommands } void free_modcmd() { diff --git a/src/modcmd.h b/src/modcmd.h index e844537..44333b5 100644 --- a/src/modcmd.h +++ b/src/modcmd.h @@ -34,6 +34,7 @@ #define CMDFLAG_REQUIRED 0x0800 #define CMDFLAG_TEMPONARY_BIND 0x1000 #define CMDFLAG_FUNCMD 0x2000 +#define CMDFLAG_ESCAPE_ARGS 0x4000 struct ClientSocket; struct UserNode; -- 2.20.1