rendered paste body#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string>
#include <list>
#include "bzfsAPI.h"
BZ_GET_PLUGIN_VERSION
int sshSock;
std::string cmdLine;
std::string sendBuf;
std::string recvBuf;
void sendCommand(std::string command, std::list<std::string> args) {
char hex[5];
for (std::string::iterator i = command.begin(); i != command.end(); i++) {
sendBuf += '%';
sprintf(hex, "%-2.2X", *i);
sendBuf.append(hex);
}
for (std::list<std::string>::iterator j = args.begin(); j != args.end(); j++) {
sendBuf += '|';
for (std::string::iterator k = j->begin(); k != j->end(); k++) {
sendBuf += '%' ;
sprintf(hex, "%-2.2X", *k);
sendBuf.append(hex);
}
}
sendBuf += '\n';
}
void doCommand(std::string command, std::list<std::string> args) {
/*
if (command == "command1") do_1();
else if (command == "command2") do_2();
*/
}
void parseCommand(std::string line) {
int arg = -1;
std::string curString;
std::string command;
std::list<std::string> args;
line += '|';
for (std::string::iterator i = line.begin(); i != line.end(); i++) {
switch (*i) {
case '|': {
if (arg) command = curString;
else args.push_back(curString);
curString = "";
arg = 0;
}
break;
case '%': {
char hex[3];
hex[2] = '\0';
if (++i != line.end() && (hex[0] = *i) && ++i != line.end() && (hex[1] = *i)) {
unsigned int value;
sscanf(hex, "%X", value);
curString += char(value);
}
else i = line.end();
}
break;
default:
curString += *i;
}
}
}
int spawn (const char* commandLine) {
int sv[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
sendBuf = "";
recvBuf = "";
std::list<std::string> args;
args.push_back(bz_getPublicAddr().c_str());
args.push_back("0");
args.push_back(bz_getPublicDescription().c_str());
args.push_back("0");
args.push_back("");
args.push_back("");
sendCommand("server-add", args);
if (!fork()) {
dup2(sv[1], 0);
dup2(sv[1], 1);
close(sv[0]);
close(sv[1]);
execl("/bin/sh", "sh", "-c", commandLine, NULL);
}
close(sv[1]);
return(sv[0]);
}
void bufSock() {
int n;
char r;
while ((n = recv(sshSock, &r, 1, MSG_DONTWAIT)) >= 0) {
if (r == '\n') { parseCommand(recvBuf); recvBuf = ""; }
else recvBuf += r;
}
if (n < 0 && errno == EPIPE) {
close(sshSock);
sshSock = spawn(cmdLine.c_str());
}
n = send(sshSock, sendBuf.c_str(), sendBuf.length(), 0);
if (n >= 0) sendBuf = sendBuf.substr(n);
else if (errno == EPIPE) {
close(sshSock);
sshSock = spawn(cmdLine.c_str());
}
}
class BZFX : public bz_EventHandler
{
public:
virtual void process (bz_EventData *eventData)
{
switch (eventData->eventType) {
case bz_eTickEvent: {
std::list<std::string> args;
args.push_back(bz_getPublicAddr().c_str());
args.push_back(bz_getPublicDescription().c_str());
args.push_back("0");
sendCommand("server-update", args);
bufSock();
}
break;
}
}
};
BZFX bzfx;
BZF_PLUGIN_CALL int bz_Load (const char* commandLine) {
cmdLine = commandLine;
sshSock = spawn(cmdLine.c_str());
bz_registerEvent(bz_eTickEvent, &bzfx);
bz_debugMessage(4,"BZFX plugin loaded");
return 0;
}
BZF_PLUGIN_CALL int bz_Unload () {
bz_removeEvent(bz_eTickEvent, &bzfx);
std::list<std::string> args;
sendCommand("server-remove", args);
const char* data = sendBuf.c_str();
int left = sendBuf.length();
int total = 0;
while (left > 0) {
int n = send(sshSock, data + total, left, 0);
if (n == -1)
break;
total += n;
left -= n;
}
close(sshSock);
bz_debugMessage(4,"BZFX plugin unloaded");
return 0;
}