1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-17 16:53:13 +00:00

Updated documentation

This commit is contained in:
Bryan Roe
2022-10-08 18:27:56 -07:00
parent 0a1fa58d4d
commit f811d1fc93
3 changed files with 99 additions and 6 deletions

View File

@@ -16,18 +16,28 @@ limitations under the License.
const SYNCHRONIZE = 0x00100000; const SYNCHRONIZE = 0x00100000;
//
// util-descriptors is a helper module that will enable enumeration of all open descriptors, as well as a means to close them
//
function invalid() function invalid()
{ {
throw ('Not supported on ' + process.platform); throw ('Not supported on ' + process.platform);
} }
//
// Returns an array containing all the open descriptors for the current process
//
function getOpenDescriptors() function getOpenDescriptors()
{ {
switch (process.platform) switch (process.platform)
{ {
case "freebsd": case "freebsd":
//
// BSD will use the system utility procstat to fetch the list of descriptors
//
var child = require('child_process').execFile('/bin/sh', ['sh']); var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); }); child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.on('data', function (c) { }); child.stderr.on('data', function (c) { });
@@ -61,6 +71,9 @@ function getOpenDescriptors()
} }
break; break;
case "linux": case "linux":
//
// Linux we will just rely on procfs to find the descriptors for our PID
//
var child = require('child_process').execFile('/bin/sh', ['sh']); var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); }); child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.on('data', function (c) { }); child.stderr.on('data', function (c) { });
@@ -92,6 +105,9 @@ function getOpenDescriptors()
return ([]); return ([]);
} }
} }
//
// This function will enumerate the specified array of descriptors, and close each one
//
function closeDescriptors(fdArray) function closeDescriptors(fdArray)
{ {
var fd = null; var fd = null;
@@ -102,10 +118,14 @@ function closeDescriptors(fdArray)
fd = fdArray.pop(); fd = fdArray.pop();
if (fd > 2) if (fd > 2)
{ {
this.libc.close(fd); this.libc.close(fd); // use glibc to close the descriptor
} }
} }
} }
//
// execv helper function, which will close all open descriptors immediately before invoking execv()
//
function _execv(exePath, argarr) function _execv(exePath, argarr)
{ {
if (this.libc == null) if (this.libc == null)
@@ -119,11 +139,16 @@ function _execv(exePath, argarr)
var args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize); var args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
for (i = 0; i < argarr.length; ++i) for (i = 0; i < argarr.length; ++i)
{ {
// convert the JS array into a native array to be passed to execv
var arg = require('_GenericMarshal').CreateVariable(argarr[i]); var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
tmp.push(arg); tmp.push(arg);
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize); arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
} }
//
// Fetch the list of all open descriptors, then close all of them. We need to do this, becuase
// execv() is going to inherit all the descriptors, so they will probably leak if the new process doesn't know what to do with them
//
var fds = this.getOpenDescriptors(); var fds = this.getOpenDescriptors();
this.closeDescriptors(fds); this.closeDescriptors(fds);
@@ -131,15 +156,22 @@ function _execv(exePath, argarr)
throw('exec error'); throw('exec error');
} }
//
// This function returns the native marshaler for glibc, specifically for 'execv' and 'close'
//
function getLibc() function getLibc()
{ {
var libs = require('monitor-info').getLibInfo('libc'); var libs = require('monitor-info').getLibInfo('libc'); // This will fetch the location of all the libc modules on the platform.
var libc = null; var libc = null;
while (libs.length > 0) while (libs.length > 0)
{ {
try try
{ {
//
// We need to enumerate each libc module, and try to load it, becuase it is common for a linux distribution
// to include modules for several different architectures. So only the correct one will load. We need to find it.
//
libc = require('_GenericMarshal').CreateNativeProxy(libs.pop().path); libc = require('_GenericMarshal').CreateNativeProxy(libs.pop().path);
libc.CreateMethod('execv'); libc.CreateMethod('execv');
libc.CreateMethod('close'); libc.CreateMethod('close');
@@ -155,16 +187,24 @@ function getLibc()
return (libc); return (libc);
} }
//
// Windows helper function to fetch a HANDLE to the specified process
//
function win_getProcessHandle(pid) function win_getProcessHandle(pid)
{ {
try try
{ {
if(!this.kernel32) if(!this.kernel32)
{ {
//
// Reference to OpenProcess() can be found at:
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
//
this.kernel32 = require('_GenericMarshal').CreateNativeProxy('kernel32.dll'); this.kernel32 = require('_GenericMarshal').CreateNativeProxy('kernel32.dll');
this.kernel32.CreateMethod('OpenProcess'); this.kernel32.CreateMethod('OpenProcess');
} }
// This will return a HANDLE to the specified prcoess
return (this.kernel32.OpenProcess(SYNCHRONIZE, 0, pid)); return (this.kernel32.OpenProcess(SYNCHRONIZE, 0, pid));
} }
catch(e) catch(e)
@@ -177,9 +217,11 @@ switch (process.platform)
{ {
case 'linux': case 'linux':
case 'freebsd': case 'freebsd':
// Only Linux and FreeBSD support finding the list of open descriptors
module.exports = { getOpenDescriptors: getOpenDescriptors, closeDescriptors: closeDescriptors, _execv: _execv, libc: getLibc() }; module.exports = { getOpenDescriptors: getOpenDescriptors, closeDescriptors: closeDescriptors, _execv: _execv, libc: getLibc() };
break; break;
default: default:
// For other platforms, we will return an error
module.exports = { getOpenDescriptors: invalid, closeDescriptors: invalid }; module.exports = { getOpenDescriptors: invalid, closeDescriptors: invalid };
break; break;
} }

View File

@@ -14,9 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
//
// util-language is a helper module to fetch the currently configured Language Locale of the Operating System
//
//
// This is a windows helper function to convert LCID to language name
//
function toLang(val) function toLang(val)
{ {
//
// Windows Language codes can be found at:
// https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/6c085406-a698-4e12-9d4d-c3b0ee3dbc4a
//
var ret; var ret;
switch (val) switch (val)
{ {
@@ -959,10 +970,15 @@ function toLang(val)
} }
return (ret); return (ret);
} }
//
// Try to determine the current language locale
//
function getCurrent() function getCurrent()
{ {
if(process.platform == 'win32') if(process.platform == 'win32')
{ {
// On windows wi will use WMI via WMIC to get the LCID.
var child = require('child_process').execFile(process.env['windir'] + '\\system32\\wbem\\wmic.exe', ['wmic', 'os', 'get', 'oslanguage','/FORMAT:LIST']); var child = require('child_process').execFile(process.env['windir'] + '\\system32\\wbem\\wmic.exe', ['wmic', 'os', 'get', 'oslanguage','/FORMAT:LIST']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); }); child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); }); child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
@@ -975,6 +991,7 @@ function getCurrent()
tokens = lines[i].split('='); tokens = lines[i].split('=');
if(tokens[0]=='OSLanguage') if(tokens[0]=='OSLanguage')
{ {
// Convert LCID to language string
return (toLang(tokens[1])); return (toLang(tokens[1]));
} }
} }
@@ -983,12 +1000,14 @@ function getCurrent()
if(process.env['LANG']) if(process.env['LANG'])
{ {
// If 'LANG" is defined in the environment variable, we can just return that
return (process.env['LANG'].split('.')[0]); return (process.env['LANG'].split('.')[0]);
} }
else else
{ {
if (process.platform == 'darwin') if (process.platform == 'darwin')
{ {
// On macOS we can use the system utility 'osascript' to fetch the current locale of the system
var child = require('child_process').execFile('/bin/sh', ['sh']); var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); }); child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); }); child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
@@ -1000,6 +1019,7 @@ function getCurrent()
{ {
try try
{ {
// On Linux/BSD, we are goign to fetch the environment variables of the Display Manager process, and see what locale was set for it
var uid = require('user-sessions').gdmUid; var uid = require('user-sessions').gdmUid;
var child = require('child_process').execFile('/bin/sh', ['sh']); var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); }); child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
@@ -1019,7 +1039,7 @@ function getCurrent()
} }
} }
// This property will fetch the current locale the first time, and cache the results
var obj = {}; var obj = {};
Object.defineProperty(obj, 'current', { Object.defineProperty(obj, 'current', {
get: function () get: function ()
@@ -1039,6 +1059,9 @@ module.exports = obj;
if (process.platform == 'win32') if (process.platform == 'win32')
{ {
//
// On Windows, we will set a property to fetch/cache the wmicXslPath
//
Object.defineProperty(module.exports, 'wmicXslPath', Object.defineProperty(module.exports, 'wmicXslPath',
{ {
get: function () get: function ()

View File

@@ -15,21 +15,40 @@ limitations under the License.
*/ */
//
// This is a windows helper that will try to determine the service name for the currently running service
//
//
// Will return the name of the currently running service if it can be determined, null otherwise
//
function win_serviceCheck() function win_serviceCheck()
{ {
var s; var s;
var reg = require('win-registry'); var reg = require('win-registry');
var path; var path;
var values = reg.QueryKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Open Source'); var values = reg.QueryKey(reg.HKEY.LocalMachine, 'SOFTWARE\\Open Source');
//
// The MeshAgent will normally add a registry entry into the above registry path, at installation time
//
if (values.subkeys) if (values.subkeys)
{ {
for (var i in values.subkeys) for (var i in values.subkeys)
{ {
try try
{ {
//
// We are enumerating all the Mesh Agents listed in the registry above, and check with the
// windows service manager to see if the PID matches the PID of the current process
//
s = require('service-manager').manager.getService(values.subkeys[i]); s = require('service-manager').manager.getService(values.subkeys[i]);
if(s.isMe()) if(s.isMe())
{ {
//
// This service is us, so we can return the results
//
s.close(); s.close();
return (values.subkeys[i]); return (values.subkeys[i]);
} }
@@ -48,10 +67,16 @@ function win_serviceCheck()
values = reg.QueryKey(reg.HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Services'); values = reg.QueryKey(reg.HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Services');
if (values.subkeys) if (values.subkeys)
{ {
//
// We couldn't find a match in the registry where the Mesh Agent normally saves information about installation,
// so we're going to just enumerate all the windows services, and try to manually brute force it
//
for(var i in values.subkeys) for(var i in values.subkeys)
{ {
try try
{ {
// We're going to look at the exe path for each enumerated service
path = reg.QueryKey(reg.HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Services\\' + values.subkeys[i], 'ImagePath'); path = reg.QueryKey(reg.HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Services\\' + values.subkeys[i], 'ImagePath');
} }
catch(xx) catch(xx)
@@ -65,13 +90,16 @@ function win_serviceCheck()
if (path.startsWith('"')) { path = path.substring(1); } if (path.startsWith('"')) { path = path.substring(1); }
if(path == process.execPath) if(path == process.execPath)
{ {
//
// If the service's exe path matches the exe path of the current process, we'll check the PID to see if it is indeed us
//
try try
{ {
s = require('service-manager').manager.getService(values.subkeys[i]); s = require('service-manager').manager.getService(values.subkeys[i]);
if(s.isMe()) if(s.isMe())
{ {
s.close(); s.close();
return (values.subkeys[i]); return (values.subkeys[i]); // It is a match!
} }
s.close(); s.close();
} }
@@ -82,7 +110,7 @@ function win_serviceCheck()
} }
} }
} }
return (null); return (null); // We couldn't find the right service
} }
switch(process.platform) switch(process.platform)