diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c index 7d1686d..08b3bd8 100644 --- a/meshcore/agentcore.c +++ b/meshcore/agentcore.c @@ -2248,7 +2248,16 @@ void MeshServer_SendAgentInfo(MeshAgentHostContainer* agent, ILibWebClient_State // Send mesh agent information to the server ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)info, sizeof(MeshCommand_BinaryPacket_AuthInfo) + hostnamelen, ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete); agent->retryTime = 0; - printf("Connected.\n"); + + if ((agent->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) + { + printf("[Recovery Agent] Connected.\n"); + } + else + { + printf("Connected.\n"); + } + if (agent->serverAuthState == 3) { MeshServer_ServerAuthenticated(WebStateObject, agent); } } @@ -3531,9 +3540,15 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char ** } } } - #endif + int ri; + for (ri = 0; ri < paramLen; ++ri) + { + if (strcmp(param[ri], "-recovery") == 0) { agentHost->capabilities |= MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY; parseCommands = 0; } + } + + // We are a Mesh Agent if (agentHost->masterDb == NULL) { agentHost->masterDb = ILibSimpleDataStore_Create(MeshAgent_MakeAbsolutePath(agentHost->exePath, ".db")); } if (agentHost->masterDb == NULL) @@ -3689,6 +3704,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char ** #ifdef WIN32 // If running as a Windows service, set basic values to the registry, this allows other applications to know what the mesh agent is doing. + if((agentHost->capabilities & MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY) == 0) { HKEY hKey; diff --git a/meshcore/agentcore.h b/meshcore/agentcore.h index d5fdd6f..90d692f 100644 --- a/meshcore/agentcore.h +++ b/meshcore/agentcore.h @@ -54,7 +54,8 @@ typedef enum MeshCommand_AuthInfo_CapabilitiesMask MeshCommand_AuthInfo_CapabilitiesMask_FILES = 0x04, MeshCommand_AuthInfo_CapabilitiesMask_CONSOLE = 0x08, MeshCommand_AuthInfo_CapabilitiesMask_JAVASCRIPT = 0x10, - MeshCommand_AuthInfo_CapabilitiesMask_TEMPORARY = 0x20 + MeshCommand_AuthInfo_CapabilitiesMask_TEMPORARY = 0x20, + MeshCommand_AuthInfo_CapabilitiesMask_RECOVERY = 0x40 }MeshCommand_AuthInfo_CapabilitiesMask; typedef enum AgentIdentifiers diff --git a/modules/service-manager.js b/modules/service-manager.js index 1a71ef3..4ed5c72 100644 --- a/modules/service-manager.js +++ b/modules/service-manager.js @@ -190,6 +190,18 @@ function serviceManager() require('events').inherits(retVal); retVal.on('~', function () { this._proxy.CloseServiceHandle(this); this._proxy.CloseServiceHandle(this._scm); }); retVal.name = name; + retVal.isRunning = function () + { + var bytesNeeded = this._GM.CreateVariable(this._GM.PointerSize); + this._proxy.QueryServiceStatusEx(this._service, 0, 0, 0, bytesNeeded); + var st = this._GM.CreateVariable(bytesNeeded.toBuffer().readUInt32LE()); + if(this._proxy.QueryServiceStatusEx(this._service, 0, st, st._size, bytesNeeded).Val != 0) + { + var state = parseServiceStatus(st); + return (state.state == 'RUNNING'); + } + return (false); + }; retVal.stop = function () { if (this.status.state == 'RUNNING') { var newstate = this._GM.CreateVariable(36); @@ -230,6 +242,117 @@ function serviceManager() { return (require('user-sessions').isRoot()); } + if(process.platform == 'linux') + { + this.getService = function (name, platform) + { + if (!platform) { platform = this.getServiceType(); } + var ret = { name: name }; + switch(platform) + { + case 'init': + case 'upstart': + if ((platform == 'init' && require('fs').existsSync('/etc/init.d/' + name)) || + (platform == 'upstart' && require('fs').existsSync('/etc/init/' + name + '.conf'))) + { + ret.isRunning = function isRunning() + { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.str = ''; + child.stdout.on('data', function (chunk) { this.str += chunk.toString(); }); + child.stdin.write("service " + this.name + " status | awk '{print $2}' | awk -F, '{print $1}'\nexit\n"); + child.waitExit(); + return (child.stdout.str.trim() == 'start/running'); + }; + ret.start = function start() + { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.on('data', function (chunk) { }); + child.stdin.write('service ' + this.name + ' start\nexit\n'); + child.waitExit(); + }; + ret.stop = function stop() + { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.on('data', function (chunk) { }); + child.stdin.write('service ' + this.name + ' stop\nexit\n'); + child.waitExit(); + }; + ret.restart = function restart() + { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.on('data', function (chunk) { }); + child.stdin.write('service ' + this.name + ' restart\nexit\n'); + child.waitExit(); + }; + ret.status = function status() + { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout._str = ''; + child.stdout.on('data', function (chunk) { this._str += chunk.toString(); }); + child.stdin.write('service ' + this.name + ' status\nexit\n'); + child.waitExit(); + return (child.stdout._str); + }; + return (ret); + } + else + { + throw (platform + ' Service (' + name + ') NOT FOUND'); + } + break; + case 'systemd': + if (require('fs').existsSync('/lib/systemd/system/' + name + '.service') || + require('fs').existsSync('/usr/lib/systemd/system/' + name + '.service')) + { + ret.isRunning = function isRunning() + { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.str = ''; + child.stdout.on('data', function (chunk) { this.str += chunk.toString(); }); + child.stdin.write("systemctl status " + this.name + " | grep 'Active:' | awk '{print $2}'\nexit\n"); + child.waitExit(); + return (child.stdout.str.trim() == 'active'); + }; + ret.start = function start() { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.on('data', function (chunk) { }); + child.stdin.write('systemctl start ' + this.name + '\nexit\n'); + child.waitExit(); + }; + ret.stop = function stop() { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.on('data', function (chunk) { }); + child.stdin.write('systemctl stop ' + this.name + '\nexit\n'); + child.waitExit(); + }; + ret.restart = function restart() { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout.on('data', function (chunk) { }); + child.stdin.write('systemctl restart ' + this.name + '\nexit\n'); + child.waitExit(); + }; + ret.status = function status() { + var child = require('child_process').execFile('/bin/sh', ['sh']); + child.stdout._str = ''; + child.stdout.on('data', function (chunk) { this._str += chunk.toString(); }); + child.stdin.write('systemctl status ' + this.name + '\nexit\n'); + child.waitExit(); + return (child.stdout._str); + }; + return (ret); + } + else + { + throw (platform + ' Service (' + name + ') NOT FOUND'); + } + break; + default: + throw ('Unknown Service Platform: ' + platform); + break; + } + }; + } } this.installService = function installService(options) { @@ -312,7 +435,9 @@ function serviceManager() if (!this.isAdmin()) { console.log('Installing a Service requires root'); throw ('Installing as Service, requires root'); } var parameters = options.parameters ? options.parameters.join(' ') : ''; var conf; - switch (this.getServiceType()) + if (!options.servicePlatform) { options.servicePlatform = this.getServiceType(); } + + switch (options.servicePlatform) { case 'init': if (!require('fs').existsSync('/usr/local/mesh_services/')) { require('fs').mkdirSync('/usr/local/mesh_services'); }