X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fmodules%2Fglobal.mod%2Fcmd_global_extscript.c;fp=src%2Fmodules%2Fglobal.mod%2Fcmd_global_extscript.c;h=b0a15ea11b4c13c48f911db2df5caa6c467c86c5;hb=2a23dc8a34a8760bce197be5ff9a44221f537383;hp=0000000000000000000000000000000000000000;hpb=2127915ca67077bb6ea0146ea1f32102badb4b16;p=NeonServV5.git diff --git a/src/modules/global.mod/cmd_global_extscript.c b/src/modules/global.mod/cmd_global_extscript.c new file mode 100644 index 0000000..b0a15ea --- /dev/null +++ b/src/modules/global.mod/cmd_global_extscript.c @@ -0,0 +1,170 @@ +/* cmd_global_extscript.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" +#include + +/* +* argv[0] 'toys' if it's a toy command (check if toys are enabled) +* argv[0-*] script name & parameter patterns +* argv[argc-1] all arguments passed to the command +*/ + +static TIMEQ_CALLBACK(global_cmd_extscript_callback); + +struct global_cmd_extscript_cache { + struct ClientSocket *client, *textclient; + struct Event *event; + struct UserNode *user; + struct ChanNode *chan; + int answere_channel; + FILE *pipe; +}; + +CMD_BIND(global_cmd_extscript) { + int i, j; + char *args[MAXNUMPARAMS]; + int argpos = 0; + char *next, *curr; + char command[1024]; + int commandpos = 0; + char part[MAXLEN]; + int partpos; + int escape_param; + int answere_channel = 0; + //check first arg + if(argc && !stricmp(argv[0], "toys")) { + if(!chan) return; //toys are not allowed via query + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_toys` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name)); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row || !strcmp(row[0], "0")) { + //disabled + reply(getTextBot(), user, "NS_FUN_DISABLED", chan->name); + return; + } else if(!strcmp(row[0], "2")) + answere_channel = 1; + argc--; + argv++; + } + //parse arguments + if(argc < 2) return; + curr = argv[argc-1]; + while(curr) { + next = strstr(curr, " "); + args[argpos++] = curr; + if(next) { + *next = '\0'; + curr = next+1; + } else + curr = NULL; + } + //parse command pattern and build command + commandpos = sprintf(command, "%s", argv[0]); + for(i = 1; i < argc-1; i++) { + partpos = 0; + escape_param = 1; + if(argv[i][0] == '$') { + argv[i]++; + if(argv[i][strlen(argv[i])-1] == '-') { + argv[i][strlen(argv[i])-1] = '\0'; + j = atoi(argv[i]); + if(j <= argpos) + partpos = sprintf(part, "%s", merge_argv(args, j-1, argpos)); + } else if((j = atoi(argv[i])) > 0) { + if(j <= argpos) + partpos = sprintf(part, "%s", args[j-1]); + } else if(!strcmp(argv[i], "c")) { + partpos = sprintf(part, "%s", (chan ? chan->name : "")); + } else if(!strcmp(argv[i], "n")) { + partpos = sprintf(part, "%s", user->nick); + } else if(!strcmp(argv[i], "a")) { + partpos = sprintf(part, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "")); + } else if(!strcmp(argv[i], "access")) { + if(chan) + partpos = sprintf(part, "%d", getChannelAccess(user, chan)); + } + } else { + partpos = sprintf(part, "%s", argv[i]); + escape_param = 0; + } + //escape shell argument + command[commandpos++] = ' '; + if(escape_param) { + command[commandpos++] = '\''; + for(j = 0; j < partpos; j++) { + if(part[j] == '\'') { + command[commandpos++] = '\''; + command[commandpos++] = '\\'; + command[commandpos++] = '\''; + command[commandpos++] = '\''; + } else + command[commandpos++] = part[j]; + } + command[commandpos++] = '\''; + } else + commandpos += sprintf(command + commandpos, " %s", part); + } + command[commandpos] = '\0'; + //we should now have a valid command + + struct global_cmd_extscript_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->event = event; + cache->user = user; + cache->chan = chan; + cache->answere_channel = answere_channel; + cache->pipe = popen(command, "r"); + #ifndef WIN32 + fcntl(fileno(cache->pipe), F_SETFL, O_NONBLOCK); + #endif + timeq_uadd(200, module_id, global_cmd_extscript_callback, cache); +} + +static TIMEQ_CALLBACK(global_cmd_extscript_callback) { + struct global_cmd_extscript_cache *cache = data; + char command[512]; + char *a; + if(feof(cache->pipe)) { + pclose(cache->pipe); + free(cache); + return; + } + while (fgets(command, 512, cache->pipe) != NULL) { + if((a = strchr(command, '\n'))) + *a = '\0'; + if(!stricmp(command, "/log")) { + logEvent(cache->event); + continue; + } + if(cache->answere_channel) + putsock(cache->client, "PRIVMSG %s :%s", cache->chan->name, command); + else + reply(cache->textclient, cache->user, "%s", command); + } + timeq_uadd(200, module_id, global_cmd_extscript_callback, cache); +} + + +