void daemon_pipe::exec() { CHECK(!m_specs.empty(), "no procs to execute"); SignalBlocker signals; // LockFile will be unlocked on destruction; don't do this until // after the ProcHarvester is destroyed LockFile lock; // ProcHarvester will wait for all children on destruction. Since we want // all the FDs to get closed before that happens, this must be instantiated // before the FileMap. ProcHarvester harvester(&signals.m_sigset); // build a map of all the files we're going to need to open, and whether // we need to read or write from them FileMap files; for(std::vector<daemon_proc_spec_ptr>::iterator i = m_specs.begin(), end = m_specs.end(); i != end; ++i) { Proc &proc(harvester.addProc(*i)); if((*i)->m_stdin) proc.m_stdin = files.get((*i)->m_stdin, true, false); if((*i)->m_stdout) proc.m_stdout = files.get((*i)->m_stdout, false, true); if((*i)->m_stderr) proc.m_stderr = files.get((*i)->m_stderr, false, true); } if(!m_lockFile.empty()) lock.open(m_lockFile); std::vector<File *>::const_iterator file = files.m_files.begin(), end = files.m_files.end(); for(; file != end; ++file) (*file)->open(); int pgid = 0; for(std::vector<ProcPtr>::iterator i = harvester.m_procs.begin(), end = harvester.m_procs.end(); i != end; ++i) { Proc &proc = **i; proc.m_blockedSignals = &signals; proc.m_newPGID = pgid; int pid = proc.safe_fork_exec(); if(pgid == 0) pgid = pid; } }
void daemon_pipe::try_error_write(const std::string &input) { // keep signals blocked even inside our catch, so we can't // get SIGPIPE from the fwrite SignalBlocker signals; try { CHECK(m_specs.size() == 1, "specs must have 1 element"); const daemon_proc_spec_ptr &procSpec = m_specs[0]; { ProcHarvester harvester(&signals.m_sigset); file_spec_ptr pipe_spec(new file_spec); File file(pipe_spec); file.open(); file.m_writeSide->setNonBlock(); Proc &proc(harvester.addProc(procSpec)); proc.m_stdin = &file; proc.m_blockedSignals = &signals; proc.m_newPGID = 0; proc.safe_fork_exec(); file.m_readSide->reset(); int ret = ::write(file.m_writeSide->get(), input.c_str(), input.length()); CHECK(ret >= 0, "write failed: %m"); file.m_writeSide->reset(); } if(!(procSpec->finished() && WIFEXITED(procSpec->getStatus()) && WEXITSTATUS(procSpec->getStatus()) == 0)) throw failure("proc failed"); } catch(failure &f) { writeN(STDERR_FILENO, input.c_str(), input.length()); } }
bool ConsoleCommandParserResource::performParsing (const NetworkId & userId, const StringVector_t & argv, const String_t & originalCommand, String_t & result, const CommandParser * node) { NOT_NULL (node); UNREF (userId); UNREF(originalCommand); //----------------------------------------------------------------- if (isCommand( argv [0], "activate")) { CachedNetworkId harvester(Unicode::wideToNarrow (argv[1])); ServerObject* harvesterObject = safe_cast<ServerObject*>(harvester.getObject()); if (harvesterObject == NULL) { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); return true; } Controller *const controller = harvesterObject->getController(); NOT_NULL(controller); controller->appendMessage(static_cast<int>(CM_activateInstallation),0.0f,new MessageQueueActivateInstallation(), GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_SERVER); result += getErrorMessage(argv[0], ERR_SUCCESS); } else if (isCommand( argv [0], "harvest")) { CachedNetworkId harvester(Unicode::wideToNarrow (argv[1])); ServerObject* harvesterObject = safe_cast<ServerObject*>(harvester.getObject()); if (harvesterObject == NULL) { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); return true; } //TODO: Make all of these into function calls instead of sending messages Controller *const controller = harvesterObject->getController(); NOT_NULL(controller); controller->appendMessage(static_cast<int>(CM_installationHarvest),0.0f,new MessageQueueInstallationHarvest(), GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_SERVER); result += getErrorMessage(argv[0], ERR_SUCCESS); } else if (isCommand( argv [0], "discardHopper")) { CachedNetworkId harvester(Unicode::wideToNarrow (argv[1])); HarvesterInstallationObject* harvesterObject = dynamic_cast<HarvesterInstallationObject*>(harvester.getObject()); if (!harvesterObject) { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); return true; } harvesterObject->discardAllHopperContents (); result += getErrorMessage(argv[0], ERR_SUCCESS); } else if (isCommand( argv [0], "deactivate")) { CachedNetworkId harvester(Unicode::wideToNarrow (argv[1])); ServerObject* harvesterObject = safe_cast<ServerObject*>(harvester.getObject()); if (harvesterObject == NULL) { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); return true; } Controller *const controller = harvesterObject->getController(); NOT_NULL(controller); controller->appendMessage(static_cast<int>(CM_deactivateInstallation),0.0f,new MessageQueueDeactivateInstallation(), GameControllerMessageFlags::SEND | GameControllerMessageFlags::RELIABLE | GameControllerMessageFlags::DEST_AUTH_SERVER); result += getErrorMessage(argv[0], ERR_SUCCESS); } else if (isCommand( argv [0], "tree")) { ServerUniverse & universe = ServerUniverse::getInstance(); ResourceClassObject * root = 0; if (argv.size () > 1) root = universe.getResourceClassByName (Unicode::wideToNarrow (argv [1])); else root = universe.getResourceTreeRoot(); if (root) { std::string temp; root->debugOutput(temp); result += Unicode::narrowToWide(temp); result += getErrorMessage(argv[0], ERR_SUCCESS); } else result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } else if (isCommand( argv [0], "pools")) { PlanetObject* planet=ServerUniverse::getInstance().getPlanetByName(Unicode::wideToNarrow(argv[1])); if (planet) { std::string temp; planet->debugOutputPools(temp); result += Unicode::narrowToWide(temp); result += getErrorMessage(argv[0], ERR_SUCCESS); } else { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } } else if (isCommand( argv [0], "name")) { NetworkId resourceId(Unicode::wideToNarrow (argv[1])); ResourceTypeObject * const resource = ServerUniverse::getInstance().getResourceTypeById(resourceId); if (resource) { resource->setName(Unicode::wideToNarrow(argv[2])); result += getErrorMessage(argv[0], ERR_SUCCESS); } else { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } } else if (isCommand( argv [0], "viewcontainer")) { CachedNetworkId contId (Unicode::wideToNarrow (argv[1])); ResourceContainerObject* container=dynamic_cast<ResourceContainerObject*>(contId.getObject()); if (container) { result += Unicode::narrowToWide(container->debugPrint()+'\n'); result += getErrorMessage(argv[0], ERR_SUCCESS); } else { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } } else if (isCommand( argv [0], "addtocontainer")) { NetworkId const contId (Unicode::wideToNarrow (argv[1])); ResourceContainerObject * const container = dynamic_cast<ResourceContainerObject*>(NetworkIdManager::getObjectById(contId)); std::string const & resourcePath = Unicode::wideToNarrow(argv[2]); ResourceTypeObject * const resType = ServerUniverse::getInstance().getResourceTypeByName(resourcePath); int const amount = strtol(Unicode::wideToNarrow (argv[3]).c_str (), NULL, 10); NetworkId const source(Unicode::wideToNarrow (argv[4])); if (container && resType) { if (container->addResource(CachedNetworkId(resType->getNetworkId()),amount, source)) result += getErrorMessage(argv[0], ERR_SUCCESS); else result += getErrorMessage(argv[0], ERR_INVALID_CONTAINER_TRANSFER); } else { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } } else if (isCommand( argv [0], "fillcontainer")) { NetworkId contId (Unicode::wideToNarrow (argv[1])); ResourceContainerObject* container=dynamic_cast<ResourceContainerObject*>(NetworkIdManager::getObjectById(contId)); if (container != NULL) { NetworkId sourceId; if (argv.size() >= 3) sourceId = NetworkId(Unicode::wideToNarrow (argv[2])); if (container->addResource(container->getResourceType(), container->getMaxQuantity() - container->getQuantity(), sourceId)) { result += getErrorMessage(argv[0], ERR_SUCCESS); } else result += getErrorMessage(argv[0], ERR_INVALID_CONTAINER_TRANSFER); } else result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } else if (isCommand( argv [0], "recycle")) { NetworkId contId (Unicode::wideToNarrow (argv[1])); ResourceContainerObject* container=dynamic_cast<ResourceContainerObject*>(NetworkIdManager::getObjectById(contId)); if (container != NULL) { if (container->debugRecycle()) result += getErrorMessage(argv[0], ERR_SUCCESS); else result += Unicode::narrowToWide("The resource in the container could not be recycled.\n"); } else result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } else if (isCommand( argv [0], "removefromcontainer")) { CachedNetworkId contId (Unicode::wideToNarrow (argv[1])); ResourceContainerObject* container=dynamic_cast<ResourceContainerObject*>(contId.getObject()); ResourceTypeObject *resType=ServerUniverse::getInstance().getResourceTypeByName(Unicode::wideToNarrow(argv[2])); int amount=strtol(Unicode::wideToNarrow (argv[3]).c_str (), NULL, 10); if (container && resType) { NetworkId sourcePlayer(NetworkId::cms_invalid); typedef std::vector<std::pair<NetworkId, int> > SourcesType; SourcesType sources; if (container->removeResource(resType->getNetworkId(),amount,&sources)) { char buffer[50]; for(SourcesType::iterator i=sources.begin(); i!=sources.end(); ++i) { IGNORE_RETURN(snprintf(buffer,50,"%i",i->second)); result += Unicode::narrowToWide(std::string("Removed ") + buffer + " resources harvested by player " + i->first.getValueString() + '\n'); } result += getErrorMessage(argv[0], ERR_SUCCESS); } else result += getErrorMessage(argv[0], ERR_INVALID_CONTAINER_TRANSFER); } else { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } } else if (isCommand( argv [0], "getSurveyList")) { std::string parentResourceClassName(Unicode::wideToNarrow(argv[1])); CachedNetworkId tool(Unicode::wideToNarrow (argv[2])); SurveySystem::getInstance().requestResourceListForSurvey(userId, tool, parentResourceClassName); result += getErrorMessage(argv[0], ERR_SUCCESS); } else if (isCommand( argv [0], "survey")) { const std::string parentResourceClassName (Unicode::wideToNarrow(argv[1])); const std::string resourceTypeName (Unicode::wideToNarrow(argv[2])); const int surveyRange = strtol(Unicode::wideToNarrow(argv[3]).c_str(),NULL,10); const int numPoints = strtol(Unicode::wideToNarrow(argv[4]).c_str(),NULL,10); const Object * player = NetworkIdManager::getObjectById(userId); if (player) { SurveySystem::getInstance().requestSurvey(userId, parentResourceClassName, resourceTypeName, player->getPosition_w(), surveyRange, numPoints); result += getErrorMessage(argv[0], ERR_SUCCESS); } else result += getErrorMessage(argv [0], ERR_INVALID_OBJECT); } else if (isCommand( argv [0], "deplete")) { NetworkId resourceId (Unicode::wideToNarrow (argv[1])); if (ServerUniverse::getInstance().manualDepleteResource(resourceId)) result += getErrorMessage(argv[0], ERR_SUCCESS); else result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } return true; } // ConsoleCommandParserResource::performParsing