mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-06 00:13:33 +00:00
1493 lines
65 KiB
JavaScript
1493 lines
65 KiB
JavaScript
/*
|
|
Copyright 2018 Intel Corporation
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
var NOTIFY_FOR_THIS_SESSION = 0;
|
|
var NOTIFY_FOR_ALL_SESSIONS = 1;
|
|
var WM_WTSSESSION_CHANGE = 0x02B1;
|
|
var WM_POWERBROADCAST = 0x218;
|
|
var PBT_POWERSETTINGCHANGE = 0x8013;
|
|
var PBT_APMSUSPEND = 0x4;
|
|
var PBT_APMRESUMESUSPEND = 0x7;
|
|
var PBT_APMRESUMEAUTOMATIC = 0x12;
|
|
var PBT_APMPOWERSTATUSCHANGE = 0xA;
|
|
var PROCESS_QUERY_INFORMATION = 0x0400;
|
|
var TOKEN_QUERY = 0x0008;
|
|
var TokenUser = 1;
|
|
var TokenType = 8;
|
|
var TokenSessionId = 12;
|
|
var ERROR_INSUFFICIENT_BUFFER = 122;
|
|
var HEAP_ZERO_MEMORY = 0x00000008;
|
|
|
|
var WTS_CONSOLE_CONNECT = (0x1);
|
|
var WTS_CONSOLE_DISCONNECT = (0x2);
|
|
var WTS_REMOTE_CONNECT = (0x3);
|
|
var WTS_REMOTE_DISCONNECT = (0x4);
|
|
var WTS_SESSION_LOGON = (0x5);
|
|
var WTS_SESSION_LOGOFF = (0x6);
|
|
var WTS_SESSION_LOCK = (0x7);
|
|
var WTS_SESSION_UNLOCK = (0x8);
|
|
var WTS_SESSION_REMOTE_CONTROL = (0x9);
|
|
var WTS_SESSION_CREATE = (0xA);
|
|
var WTS_SESSION_TERMINATE = (0xB);
|
|
|
|
var GUID_ACDC_POWER_SOURCE;
|
|
var GUID_BATTERY_PERCENTAGE_REMAINING;
|
|
var GUID_CONSOLE_DISPLAY_STATE;
|
|
|
|
function columnParse(data, delimiter)
|
|
{
|
|
var tokens = data.split(delimiter);
|
|
var ret = [];
|
|
for(var i in tokens)
|
|
{
|
|
if (tokens[i].length > 0) { ret.push(tokens[i]); }
|
|
}
|
|
return (ret);
|
|
}
|
|
|
|
|
|
function UserSessions()
|
|
{
|
|
this._ObjectID = 'user-sessions';
|
|
require('events').EventEmitter.call(this, true)
|
|
.createEvent('changed')
|
|
.createEvent('locked')
|
|
.createEvent('unlocked')
|
|
.addMethod('locked', function () { return (this._locked); })
|
|
.addMethod('unlocked', function () { return (!this._locked); });
|
|
this._locked = false;
|
|
this.on('locked', function () { this._locked = true; });
|
|
this.on('unlocked', function () { this._locked = false; });
|
|
|
|
if (process.platform == 'win32')
|
|
{
|
|
this._serviceHooked = false;
|
|
this._marshal = require('_GenericMarshal');
|
|
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
|
this._kernel32.CreateMethod('GetLastError');
|
|
this._kernel32.CreateMethod('WTSGetActiveConsoleSessionId')
|
|
this._kernel32.CreateMethod('CloseHandle');
|
|
|
|
try
|
|
{
|
|
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
|
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
|
this._wts.CreateMethod('WTSQuerySessionInformationW');
|
|
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
|
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
|
this._wts.CreateMethod('WTSFreeMemory');
|
|
}
|
|
catch(exc)
|
|
{
|
|
}
|
|
|
|
this._advapi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
|
this._advapi.CreateMethod('AllocateAndInitializeSid');
|
|
this._advapi.CreateMethod('CheckTokenMembership');
|
|
this._advapi.CreateMethod('FreeSid');
|
|
|
|
this._user32 = this._marshal.CreateNativeProxy('user32.dll');
|
|
this._user32.CreateMethod({ method: 'RegisterPowerSettingNotification', threadDispatch: 1});
|
|
this._user32.CreateMethod('UnregisterPowerSettingNotification');
|
|
this._rpcrt = this._marshal.CreateNativeProxy('Rpcrt4.dll');
|
|
this._rpcrt.CreateMethod('UuidFromStringA');
|
|
this._rpcrt.StringToUUID = function StringToUUID(guid)
|
|
{
|
|
var retVal = StringToUUID.us._marshal.CreateVariable(16);
|
|
if(StringToUUID.us._rpcrt.UuidFromStringA(StringToUUID.us._marshal.CreateVariable(guid), retVal).Val == 0)
|
|
{
|
|
return (retVal);
|
|
}
|
|
else
|
|
{
|
|
throw ('Could not convert string to UUID');
|
|
}
|
|
}
|
|
this._rpcrt.StringToUUID.us = this;
|
|
|
|
try
|
|
{
|
|
this._kernel32.CreateMethod('OpenProcess')
|
|
this._advapi.CreateMethod('OpenProcessToken');
|
|
this._advapi.CreateMethod('GetTokenInformation');
|
|
this._advapi.CreateMethod('LookupAccountSidW');
|
|
this._advapi.CreateMethod('OpenThreadToken');
|
|
}
|
|
catch(e)
|
|
{
|
|
}
|
|
|
|
|
|
GUID_ACDC_POWER_SOURCE = this._rpcrt.StringToUUID('5d3e9a59-e9D5-4b00-a6bd-ff34ff516548');
|
|
GUID_BATTERY_PERCENTAGE_REMAINING = this._rpcrt.StringToUUID('a7ad8041-b45a-4cae-87a3-eecbb468a9e1');
|
|
GUID_CONSOLE_DISPLAY_STATE = this._rpcrt.StringToUUID('6fe69556-704a-47a0-8f24-c28d936fda47');
|
|
|
|
this.SessionStates = ['Active', 'Connected', 'ConnectQuery', 'Shadow', 'Disconnected', 'Idle', 'Listening', 'Reset', 'Down', 'Init'];
|
|
this.InfoClass =
|
|
{
|
|
'WTSInitialProgram': 0,
|
|
'WTSApplicationName': 1,
|
|
'WTSWorkingDirectory': 2,
|
|
'WTSOEMId': 3,
|
|
'WTSSessionId': 4,
|
|
'WTSUserName': 5,
|
|
'WTSWinStationName': 6,
|
|
'WTSDomainName': 7,
|
|
'WTSConnectState': 8,
|
|
'WTSClientBuildNumber': 9,
|
|
'WTSClientName': 10,
|
|
'WTSClientDirectory': 11,
|
|
'WTSClientProductId': 12,
|
|
'WTSClientHardwareId': 13,
|
|
'WTSClientAddress': 14,
|
|
'WTSClientDisplay': 15,
|
|
'WTSClientProtocolType': 16,
|
|
'WTSIdleTime': 17,
|
|
'WTSLogonTime': 18,
|
|
'WTSIncomingBytes': 19,
|
|
'WTSOutgoingBytes': 20,
|
|
'WTSIncomingFrames': 21,
|
|
'WTSOutgoingFrames': 22,
|
|
'WTSClientInfo': 23,
|
|
'WTSSessionInfo': 24,
|
|
'WTSSessionInfoEx': 25,
|
|
'WTSConfigInfo': 26,
|
|
'WTSValidationInfo': 27,
|
|
'WTSSessionAddressV4': 28,
|
|
'WTSIsRemoteSession': 29
|
|
};
|
|
|
|
this.isRoot = function isRoot()
|
|
{
|
|
var NTAuthority = this._marshal.CreateVariable(6);
|
|
NTAuthority.toBuffer().writeInt8(5, 5);
|
|
|
|
var AdministratorsGroup = this._marshal.CreatePointer();
|
|
var admin = false;
|
|
|
|
if (this._advapi.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
|
{
|
|
var member = this._marshal.CreateInteger();
|
|
if (this._advapi.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
|
{
|
|
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
|
}
|
|
this._advapi.FreeSid(AdministratorsGroup.Deref());
|
|
}
|
|
return admin;
|
|
}
|
|
this.getProcessOwnerName = function getProcessOwnerName(pid)
|
|
{
|
|
var ret = null;
|
|
var name = this._marshal.CreateVariable(1024);
|
|
var domain = this._marshal.CreateVariable(1024);
|
|
var nameDomainLength = this._marshal.CreateVariable(4); nameDomainLength.toBuffer().writeUInt32LE(1024);
|
|
var bufferLength = this._marshal.CreateVariable(4);
|
|
var sidtype = this._marshal.CreateVariable(4);
|
|
var tokenuser = 0;
|
|
var token = this._marshal.CreatePointer();
|
|
|
|
var h = this._kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, 1, pid);
|
|
if (h.Val == 0) { throw ('Failed to query process id: ' + pid); }
|
|
|
|
if(this._advapi.OpenProcessToken(h, TOKEN_QUERY, token).Val==0)
|
|
{
|
|
this._kernel32.CloseHandle(h);
|
|
throw ('Failed to Query Process Token for pid: ' + pid);
|
|
}
|
|
|
|
var tsid = this._marshal.CreateVariable(4);
|
|
this._advapi.GetTokenInformation(token.Deref(), TokenSessionId, tsid, 4, bufferLength);
|
|
this._advapi.GetTokenInformation(token.Deref(), TokenUser, tokenuser, 0, bufferLength);
|
|
tokenuser = this._marshal.CreateVariable(bufferLength.toBuffer().readUInt32LE());
|
|
|
|
if (this._advapi.GetTokenInformation(token.Deref(), TokenUser, tokenuser, bufferLength.toBuffer().readUInt32LE(), bufferLength).Val == 0) { throw ('Internal Error'); }
|
|
if(this._advapi.LookupAccountSidW(0, tokenuser.Deref(), name, nameDomainLength, domain, nameDomainLength, sidtype).Val == 0)
|
|
{
|
|
throw ('Lookup Error');
|
|
}
|
|
else
|
|
{
|
|
name._size = 0; domain._size = 0;
|
|
ret = { name: name.Wide2UTF8, domain: domain.Wide2UTF8, tsid: tsid.toBuffer().readUInt32LE() };
|
|
}
|
|
|
|
this._kernel32.CloseHandle(token.Deref());
|
|
this._kernel32.CloseHandle(h);
|
|
return (ret);
|
|
};
|
|
|
|
this.getRawSessionAttribute = function getRawSessionAttribute(sessionId, attr)
|
|
{
|
|
var buffer = this._marshal.CreatePointer();
|
|
var bytesReturned = this._marshal.CreateVariable(4);
|
|
|
|
if (this._wts.WTSQuerySessionInformationW(0, sessionId, attr, buffer, bytesReturned).Val == 0)
|
|
{
|
|
throw ('Error calling WTSQuerySessionInformationW: ' + this._kernel32.GetLastError.Val);
|
|
}
|
|
|
|
var b = buffer.Deref().Deref(0, bytesReturned.toBuffer().readUInt32LE()).toBuffer();
|
|
var ret = Buffer.alloc(bytesReturned.toBuffer().readUInt32LE());
|
|
b.copy(ret);
|
|
this._wts.WTSFreeMemory(buffer.Deref());
|
|
return (ret);
|
|
}
|
|
this.getSessionAttribute = function getSessionAttribute(sessionId, attr)
|
|
{
|
|
var buffer = this._marshal.CreatePointer();
|
|
var bytesReturned = this._marshal.CreateVariable(4);
|
|
|
|
if (this._wts.WTSQuerySessionInformationW(0, sessionId, attr, buffer, bytesReturned).Val == 0)
|
|
{
|
|
throw ('Error calling WTSQuerySessionInformationW: ' + this._kernel32.GetLastError.Val);
|
|
}
|
|
|
|
var retVal = buffer.Deref().Wide2UTF8;
|
|
|
|
this._wts.WTSFreeMemory(buffer.Deref());
|
|
return (retVal);
|
|
};
|
|
this.consoleUid = function consoleUid()
|
|
{
|
|
var id = this._kernel32.WTSGetActiveConsoleSessionId().Val;
|
|
if(id==0xFFFFFFFF) {throw('Nobody logged in');}
|
|
return (id);
|
|
};
|
|
this.getUsername = function getUsername(uid)
|
|
{
|
|
return (this.getSessionAttribute(uid, this.InfoClass.WTSUserName));
|
|
}
|
|
this.getDomain = function getDomain(uid)
|
|
{
|
|
return (this.getSessionAttribute(uid, this.InfoClass.WTSDomainName));
|
|
}
|
|
this.Current = function Current(cb)
|
|
{
|
|
var retVal = {};
|
|
var pinfo = this._marshal.CreatePointer();
|
|
var count = this._marshal.CreateVariable(4);
|
|
if (this._wts.WTSEnumerateSessionsA(0, 0, 1, pinfo, count).Val == 0)
|
|
{
|
|
throw ('Error calling WTSEnumerateSessionsA: ' + this._kernel32.GetLastError().Val);
|
|
}
|
|
|
|
for (var i = 0; i < count.toBuffer().readUInt32LE() ; ++i)
|
|
{
|
|
var info = pinfo.Deref().Deref(i * (this._marshal.PointerSize == 4 ? 12 : 24), this._marshal.PointerSize == 4 ? 12 : 24);
|
|
var j = { SessionId: info.toBuffer().readUInt32LE() };
|
|
j.StationName = info.Deref(this._marshal.PointerSize == 4 ? 4 : 8, this._marshal.PointerSize).Deref().String;
|
|
j.State = this.SessionStates[info.Deref(this._marshal.PointerSize == 4 ? 8 : 16, 4).toBuffer().readUInt32LE()];
|
|
if (j.State == 'Active') {
|
|
j.Username = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSUserName);
|
|
j.Domain = this.getSessionAttribute(j.SessionId, this.InfoClass.WTSDomainName);
|
|
}
|
|
retVal[j.SessionId] = j;
|
|
}
|
|
|
|
this._wts.WTSFreeMemory(pinfo.Deref());
|
|
|
|
Object.defineProperty(retVal, 'Active', { value: showActiveOnly(retVal) });
|
|
if (cb) { cb(retVal); }
|
|
return (retVal);
|
|
};
|
|
|
|
if (!global._noMessagePump)
|
|
{
|
|
// We need to spin up a message pump, and fetch a window handle
|
|
var message_pump = require('win-message-pump');
|
|
this._messagepump = new message_pump({ filter: WM_WTSSESSION_CHANGE }); this._messagepump.parent = this;
|
|
this._messagepump.on('exit', function (code) { this.parent._wts.WTSUnRegisterSessionNotification(this.parent.hwnd); });
|
|
this._messagepump.on('hwnd', function (h)
|
|
{
|
|
this.parent.hwnd = h;
|
|
|
|
// We need to yield, and do this in the next event loop pass, becuase we don't want to call 'RegisterPowerSettingNotification'
|
|
// from the messagepump 'thread', because we are actually on the microstack thread, such that the message pump thread, is holding
|
|
// on a semaphore for us to return. If we call now, we may deadlock on Windows 7, becuase it will try to notify immediately
|
|
this.immediate = setImmediate(function (self)
|
|
{
|
|
// Now that we have a window handle, we can register it to receive Windows Messages
|
|
if (self.parent._wts) { self.parent._wts.WTSRegisterSessionNotification(self.parent.hwnd, NOTIFY_FOR_ALL_SESSIONS); }
|
|
self.parent._user32.ACDC_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_ACDC_POWER_SOURCE, 0);
|
|
self.parent._user32.BATT_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_BATTERY_PERCENTAGE_REMAINING, 0);
|
|
self.parent._user32.DISP_H = self.parent._user32.RegisterPowerSettingNotification(self.parent.hwnd, GUID_CONSOLE_DISPLAY_STATE, 0);
|
|
//console.log(self.parent._user32.ACDC_H.Val, self.parent._user32.BATT_H.Val, self.parent._user32.DISP_H.Val);
|
|
}, this);
|
|
});
|
|
this._messagepump.on('message', function (msg)
|
|
{
|
|
switch (msg.message)
|
|
{
|
|
case WM_WTSSESSION_CHANGE:
|
|
switch (msg.wparam)
|
|
{
|
|
case WTS_SESSION_LOCK:
|
|
this.parent.enumerateUsers().then(function (users)
|
|
{
|
|
if (users[msg.lparam]) { this.parent.emit('locked', users[msg.lparam]); }
|
|
});
|
|
break;
|
|
case WTS_SESSION_UNLOCK:
|
|
this.parent.enumerateUsers().then(function (users)
|
|
{
|
|
if (users[msg.lparam]) { this.parent.emit('unlocked', users[msg.lparam]); }
|
|
});
|
|
break;
|
|
case WTS_SESSION_LOGON:
|
|
case WTS_SESSION_LOGOFF:
|
|
this.parent.emit('changed');
|
|
break;
|
|
}
|
|
break;
|
|
case WM_POWERBROADCAST:
|
|
switch (msg.wparam)
|
|
{
|
|
default:
|
|
console.log('WM_POWERBROADCAST [UNKNOWN wparam]: ' + msg.wparam);
|
|
break;
|
|
case PBT_APMSUSPEND:
|
|
require('power-monitor').emit('sx', 'SLEEP');
|
|
break;
|
|
case PBT_APMRESUMEAUTOMATIC:
|
|
require('power-monitor').emit('sx', 'RESUME_NON_INTERACTIVE');
|
|
break;
|
|
case PBT_APMRESUMESUSPEND:
|
|
require('power-monitor').emit('sx', 'RESUME_INTERACTIVE');
|
|
break;
|
|
case PBT_APMPOWERSTATUSCHANGE:
|
|
require('power-monitor').emit('changed');
|
|
break;
|
|
case PBT_POWERSETTINGCHANGE:
|
|
var lparam = this.parent._marshal.CreatePointer(Buffer.from(msg.lparam_hex, 'hex'));
|
|
var data = lparam.Deref(20, lparam.Deref(16, 4).toBuffer().readUInt32LE(0)).toBuffer();
|
|
switch (lparam.Deref(0, 16).toBuffer().toString('hex'))
|
|
{
|
|
case GUID_ACDC_POWER_SOURCE.Deref(0, 16).toBuffer().toString('hex'):
|
|
switch (data.readUInt32LE(0))
|
|
{
|
|
case 0:
|
|
require('power-monitor').emit('acdc', 'AC');
|
|
break;
|
|
case 1:
|
|
require('power-monitor').emit('acdc', 'BATTERY');
|
|
break;
|
|
case 2:
|
|
require('power-monitor').emit('acdc', 'HOT');
|
|
break;
|
|
}
|
|
break;
|
|
case GUID_BATTERY_PERCENTAGE_REMAINING.Deref(0, 16).toBuffer().toString('hex'):
|
|
require('power-monitor').emit('batteryLevel', data.readUInt32LE(0));
|
|
break;
|
|
case GUID_CONSOLE_DISPLAY_STATE.Deref(0, 16).toBuffer().toString('hex'):
|
|
switch (data.readUInt32LE(0))
|
|
{
|
|
case 0:
|
|
require('power-monitor').emit('display', 'OFF');
|
|
break;
|
|
case 1:
|
|
require('power-monitor').emit('display', 'ON');
|
|
break;
|
|
case 2:
|
|
require('power-monitor').emit('display', 'DIMMED');
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
else if(process.platform == 'linux' || process.platform == 'freebsd')
|
|
{
|
|
Object.defineProperty(this, 'hasLoginCtl',
|
|
{
|
|
get: function ()
|
|
{
|
|
if (this._hasLoginCtl != null) { return (this._hasLoginCtl); }
|
|
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("whereis loginctl | awk '{ print $2 }'\nexit\n");
|
|
child.waitExit();
|
|
this._hasLoginCtl = child.stdout.str.trim() != "";
|
|
return (this._hasLoginCtl);
|
|
}
|
|
});
|
|
Object.defineProperty(this, "gdmUid", {
|
|
get: function ()
|
|
{
|
|
var ret = null;
|
|
var min = this.minUid();
|
|
var child;
|
|
if (process.platform == 'linux' || process.platform == 'freebsd')
|
|
{
|
|
if(this.hasLoginCtl)
|
|
{
|
|
var pwd = null;
|
|
var uids = [];
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
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.stdin.write("getent passwd | tr '\\n' '`' ");
|
|
child.stdin.write(" | awk '{ ");
|
|
child.stdin.write(' first="";');
|
|
child.stdin.write(' printf("{");');
|
|
child.stdin.write(' n=split($0, lines, "`");');
|
|
child.stdin.write(' for(i=1;i<n;++i)');
|
|
child.stdin.write(' {');
|
|
child.stdin.write(' split(lines[i],A,":");');
|
|
child.stdin.write(' printf "%s\\"%s\\": {\\"user\\":\\"%s\\", \\"desc\\":\\"%s\\"}", first, A[3], A[1], A[5];');
|
|
child.stdin.write(' first=",";');
|
|
child.stdin.write(" }");
|
|
child.stdin.write(' printf("}");');
|
|
child.stdin.write("}' ");
|
|
|
|
child.stdin.write('\nexit\n');
|
|
child.waitExit();
|
|
try
|
|
{
|
|
pwd = JSON.parse(child.stdout.str);
|
|
console.info1(JSON.stringify(pwd, null, 1));
|
|
}
|
|
catch(z)
|
|
{
|
|
}
|
|
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("loginctl list-sessions | tr '\\n' '`' | awk '{");
|
|
child.stdin.write('printf "[";');
|
|
child.stdin.write('del="";');
|
|
child.stdin.write('n=split($0, lines, "`");');
|
|
child.stdin.write('for(i=2;i<n;++i)');
|
|
child.stdin.write('{');
|
|
child.stdin.write(' split(lines[i], tok, " ");');
|
|
child.stdin.write(' if(tok[4]=="") { continue; }');
|
|
child.stdin.write(' printf "%s{\\"Username\\": \\"%s\\", \\"SessionId\\": \\"%s\\", \\"State\\": \\"Online\\", \\"uid\\": \\"%s\\"}", del, tok[3], tok[1], tok[2];');
|
|
child.stdin.write(' del=",";');
|
|
child.stdin.write('}');
|
|
child.stdin.write('printf "]";');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
try
|
|
{
|
|
var info1 = JSON.parse(child.stdout.str);
|
|
var i;
|
|
for (i = 0; i < info1.length; ++i) { uids.push(info1[i].uid); }
|
|
console.info1(JSON.stringify(uids));
|
|
}
|
|
catch(z)
|
|
{
|
|
}
|
|
|
|
if (pwd != null && uids.length > 0)
|
|
{
|
|
while(uids.length>0)
|
|
{
|
|
var tst = uids.pop();
|
|
if (pwd[tst].desc.indexOf('Display Manager') >= 0 || pwd[tst].user == 'gdm' || pwd[tst].user == 'lightdm' || pwd[tst].user == 'sddm')
|
|
{
|
|
if (parseInt(tst) < min)
|
|
{
|
|
return (parseInt(tst));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
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.stdin.write('getent passwd | grep "Gnome Display Manager" | ' + "tr '\\n' '`' | awk -F: '{ print $3 }'\nexit\n");
|
|
child.waitExit();
|
|
if (child.stdout.str.trim() != '' && (ret = parseInt(child.stdout.str.trim())) < min) { return (parseInt(child.stdout.str.trim())); }
|
|
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (c) { console.log(c.toString()); });
|
|
child.stdin.write('getent passwd | grep gdm | ' + "tr '\\n' '`' | awk -F'`' '" + '{ for(i=1;i<NF;++i) { split($i, f, ":"); if(f[3]+0<' + min + '+0) { print f[3]; break; } } }' + "'\nexit\n");
|
|
child.waitExit();
|
|
if (child.stdout.str.trim() != '' && (ret = parseInt(child.stdout.str.trim())) < min) { return (parseInt(child.stdout.str.trim())); }
|
|
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
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.stdin.write('getent passwd | grep "Light Display Manager" | ' + "tr '\\n' '`' | awk -F: '{ print $3 }'\nexit\n");
|
|
child.waitExit();
|
|
if (child.stdout.str.trim() != '' && (ret = parseInt(child.stdout.str.trim())) < min) { return (parseInt(child.stdout.str.trim())); }
|
|
|
|
return (0);
|
|
}
|
|
});
|
|
this.getUid = function getUid(username)
|
|
{
|
|
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("getent passwd \"" + username + "\" | awk -F: '{print $3}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
var ret = parseInt(child.stdout.str);
|
|
if (ret >= 0) { return (ret); }
|
|
throw ('username: ' + username + ' NOT FOUND');
|
|
};
|
|
|
|
function linux_Onchange_checkLoginCtl()
|
|
{
|
|
if (linux_Onchange_checkLoginCtl.counter > 10)
|
|
{
|
|
console.info1("emitting 'changed' because giving up");
|
|
require('user-sessions').emit('changed');
|
|
return;
|
|
}
|
|
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
|
|
child.stdin.write("loginctl list-sessions | tr '\\n' '`' | awk '{");
|
|
child.stdin.write('printf "[";');
|
|
child.stdin.write('del="";');
|
|
child.stdin.write('n=split($0, lines, "`");');
|
|
child.stdin.write('for(i=2;i<n;++i)');
|
|
child.stdin.write('{');
|
|
child.stdin.write(' split(lines[i], tok, " ");');
|
|
child.stdin.write(' if(tok[4]=="") { continue; }');
|
|
child.stdin.write(' printf "%s{\\"Username\\": \\"%s\\", \\"SessionId\\": \\"%s\\", \\"State\\": \\"Online\\", \\"uid\\": \\"%s\\"}", del, tok[3], tok[1], tok[2];');
|
|
child.stdin.write(' del=",";');
|
|
child.stdin.write('}');
|
|
child.stdin.write('printf "]";');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
var info1 = JSON.parse(child.stdout.str);
|
|
var sids = [];
|
|
var i;
|
|
for (i = 0; i < info1.length; ++i) { sids.push(info1[i].SessionId); }
|
|
|
|
console.info1('SIDs => ' + JSON.stringify(sids));
|
|
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("loginctl show-session -p State " + sids.join(' ') + " | grep State= | tr '\\n' '`' | awk -F'`' '{");
|
|
child.stdin.write(' for(n=1;n<NF;++n)');
|
|
child.stdin.write(' {');
|
|
child.stdin.write(' if($n=="State=active") { print n; break; }');
|
|
child.stdin.write(' }');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
|
|
if(child.stdout.str.trim() != '')
|
|
{
|
|
// There was an active session
|
|
console.info1('Active Sessions found');
|
|
linux_Onchange_checkLoginCtl.counter = 0;
|
|
linux_Onchange_checkLoginCtl.timer = null;
|
|
require('user-sessions').emit('changed');
|
|
}
|
|
else
|
|
{
|
|
// No sessions were active, so we need to try again
|
|
console.info1('No Active Sessions found, try again');
|
|
linux_Onchange_checkLoginCtl.counter++;
|
|
linux_Onchange_checkLoginCtl.timer = setTimeout(linux_Onchange_checkLoginCtl, 500);
|
|
}
|
|
}
|
|
|
|
|
|
this.Current = function Current(cb)
|
|
{
|
|
var ret = null;
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
|
|
if (process.platform == 'freebsd' || !this.hasLoginCtl)
|
|
{
|
|
child.stdin.write("who | tr '\\n' '`' | awk -F'`' '" + '{ printf "{"; for(a=1;a<NF;++a) { n=split($a, tok, " "); printf "%s\\"%s\\": \\"%s\\"", (a>1?",":""), tok[2], tok[1]; } printf "}"; }\'\nexit\n');
|
|
child.waitExit();
|
|
}
|
|
else
|
|
{
|
|
var min = this.minUid();
|
|
|
|
child.stdin.write("loginctl list-sessions | tr '\\n' '`' | awk '{");
|
|
child.stdin.write('printf "[";');
|
|
child.stdin.write('del="";');
|
|
child.stdin.write('n=split($0, lines, "`");');
|
|
child.stdin.write('for(i=1;i<n;++i)');
|
|
child.stdin.write('{');
|
|
child.stdin.write(' split(lines[i], tok, " ");');
|
|
child.stdin.write(' if((tok[2]+0)>=' + min + ')');
|
|
child.stdin.write(' {');
|
|
child.stdin.write(' if(tok[4]=="") { continue; }');
|
|
child.stdin.write(' station="Console";');
|
|
child.stdin.write(' if(tok[4]~/^pts\\//) { station=tok[4]; }');
|
|
child.stdin.write(' printf "%s{\\"Username\\": \\"%s\\", \\"Domain\\":\\"\\", \\"SessionId\\": \\"%s\\", \\"State\\": \\"Online\\", \\"uid\\": \\"%s\\", \\"StationName\\": \\"%s\\"}", del, tok[3], tok[1], tok[2], station;');
|
|
child.stdin.write(' del=",";');
|
|
child.stdin.write(' }');
|
|
child.stdin.write('}');
|
|
child.stdin.write('printf "]";');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
var info1 = JSON.parse(child.stdout.str);
|
|
var sids = [];
|
|
var i;
|
|
for (i = 0; i < info1.length; ++i) { sids.push(info1[i].SessionId); }
|
|
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("loginctl show-session -p State " + sids.join(' ') + " | grep State= | tr '\\n' '`' | awk -F'`' '{");
|
|
child.stdin.write(' for(n=1;n<NF;++n)');
|
|
child.stdin.write(' {');
|
|
child.stdin.write(' if($n=="State=active") { print n; break; }');
|
|
child.stdin.write(' }');
|
|
child.stdin.write(' if(n==NF) { print 0; }');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
i = parseInt(child.stdout.str.trim());
|
|
if (i > 0)
|
|
{
|
|
info1[i - 1].State = 'Active';
|
|
}
|
|
ret = info1;
|
|
}
|
|
|
|
if (ret == null)
|
|
{
|
|
try
|
|
{
|
|
ret = JSON.parse(child.stdout.str.trim());
|
|
for (var key in ret)
|
|
{
|
|
ret[key] = { Username: ret[key], SessionId: key, State: 'Active', uid: this.getUid(ret[key]) };
|
|
if (key.startsWith('pts/')) { delete ret[key]; }
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
}
|
|
}
|
|
|
|
var vids = this.virtualUids();
|
|
for (i in vids)
|
|
{
|
|
var u = this.getUsername(vids[i].uid);
|
|
ret.push({ Username: u, SessionId: vids[i].pid, State: 'Connected', uid: vids[i].uid, StationName: 'Xvfb-' + vids[i].uid });
|
|
}
|
|
|
|
Object.defineProperty(ret, 'Active', { value: showActiveOnly(ret) });
|
|
|
|
if (cb)
|
|
{
|
|
cb.call(this, ret);
|
|
}
|
|
}
|
|
|
|
if (process.platform == 'linux')
|
|
{
|
|
if (require('fs').watch)
|
|
{
|
|
this._linuxWatcher = require('fs').watch('/var/run/utmp');
|
|
this._linuxWatcher.on('change', function (a, b)
|
|
{
|
|
if (require('user-sessions').hasLoginCtl)
|
|
{
|
|
linux_Onchange_checkLoginCtl.counter = 0;
|
|
linux_Onchange_checkLoginCtl.timer = null;
|
|
linux_Onchange_checkLoginCtl();
|
|
}
|
|
else
|
|
{
|
|
require('user-sessions').emit('changed');
|
|
}
|
|
});
|
|
}
|
|
|
|
this.getUidConfig = function getUidConfig() {
|
|
var ret = {};
|
|
var cfg = require('fs').readFileSync('/etc/login.defs').toString().split('\n');
|
|
var tokens;
|
|
for (var i in cfg) {
|
|
tokens = columnParse(cfg[i], '\t'); //console.log(tokens);
|
|
if (tokens[0] == 'UID_MIN') { ret.MIN = parseInt(tokens[1]); }
|
|
if (tokens[0] == 'UID_MAX') { ret.MAX = parseInt(tokens[1]); }
|
|
if (ret.MIN != null && ret.MAX != null) { break; }
|
|
}
|
|
return (ret);
|
|
};
|
|
}
|
|
|
|
this.minUid = function minUid()
|
|
{
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("cat /etc/login.defs | grep UID_ | awk '{ if($1==\"UID_MIN\") { print $2; } }'\nexit\n");
|
|
child.waitExit();
|
|
return (parseInt(child.stdout.str.trim()) >= 0 ? parseInt(child.stdout.str.trim()) : 500);
|
|
}
|
|
this._users = function _users()
|
|
{
|
|
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("getent passwd | awk -F: '{ if($3>=0) { printf \"%s:%s\\n\", $1, $3; } }'\nexit\n");
|
|
child.waitExit();
|
|
|
|
var lines = child.stdout.str.split('\n');
|
|
var ret = {}, tokens;
|
|
for (var ln in lines)
|
|
{
|
|
tokens = lines[ln].split(':');
|
|
if (tokens[0]) { ret[tokens[0]] = tokens[1]; }
|
|
}
|
|
return (ret);
|
|
}
|
|
this._uids = function _uids() {
|
|
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("getent passwd | awk -F: '{ if($3>=0) { printf \"%s:%s\\n\", $1, $3; } }'\nexit\n");
|
|
child.waitExit();
|
|
|
|
var lines = child.stdout.str.split('\n');
|
|
var ret = {}, tokens;
|
|
for (var ln in lines) {
|
|
tokens = lines[ln].split(':');
|
|
if (tokens[0]) { ret[tokens[1]] = tokens[0]; }
|
|
}
|
|
return (ret);
|
|
}
|
|
this.loginUids = function loginUids()
|
|
{
|
|
var min = this.minUid();
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write('getent passwd | awk -F: \'{ if($3 >= ' + min + ') { a=split($7,b,"/"); if(b[a]!="nologin") { print $3; } }}\' | tr "\\n" "\\," | awk \'{ printf "[%s]", $0; }\'\nexit\n');
|
|
child.waitExit();
|
|
return (JSON.parse(child.stdout.str.trim().replace(',]',']')));
|
|
}
|
|
this.activeUids = function activeUids()
|
|
{
|
|
return (this.consoleUid({ active: true }));
|
|
};
|
|
this.virtualUids = function virtualUids()
|
|
{
|
|
var active = this.activeUids();
|
|
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("ps -e -o uid -o pid -o cmd | grep Xvfb | tr '\\n' '`' | awk '{");
|
|
child.stdin.write('printf "[";');
|
|
child.stdin.write('del="";');
|
|
child.stdin.write('n=split($0, lines, "`");');
|
|
child.stdin.write('for(i=1;i<n;++i)');
|
|
child.stdin.write('{');
|
|
child.stdin.write(' split(lines[i], tok, " ");');
|
|
child.stdin.write(' if((tok[3])=="Xvfb")');
|
|
child.stdin.write(' {');
|
|
child.stdin.write(' match(lines[i], /:[0-9]+/);');
|
|
child.stdin.write(' _display = substr(lines[i],RSTART,RLENGTH);');
|
|
child.stdin.write(' match(lines[i], /-auth .+/);');
|
|
child.stdin.write(' _auth = substr(lines[i],RSTART+6,RLENGTH-6);');
|
|
child.stdin.write(' printf("%s{\\"uid\\": %s, \\"display\\": \\"%s\\", \\"xauth\\": \\"%s\\", \\"pid\\": %s}", del, tok[1], _display, _auth, tok[2]);');
|
|
child.stdin.write(' del=",";');
|
|
child.stdin.write(' }');
|
|
child.stdin.write('}');
|
|
child.stdin.write('printf "]";');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
try
|
|
{
|
|
return(JSON.parse(child.stdout.str));
|
|
}
|
|
catch (x)
|
|
{
|
|
return ([]);
|
|
}
|
|
};
|
|
this.consoleUid = function consoleUid(options)
|
|
{
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
|
|
if (process.platform == 'freebsd' || !this.hasLoginCtl)
|
|
{
|
|
child.stdin.write("who | tr '\\n' '`' | awk -F'`' '{");
|
|
child.stdin.write(" for(i=1;i<NF;++i) ");
|
|
child.stdin.write(" { ");
|
|
child.stdin.write(' split($i,tok," "); x=split(tok[2],itm,"pts"); ');
|
|
if (process.platform != 'freebsd')
|
|
{
|
|
child.stdin.write(' if(x==1) ');
|
|
}
|
|
child.stdin.write(' { ');
|
|
child.stdin.write(' print tok[1]; ');
|
|
child.stdin.write(' break; ');
|
|
child.stdin.write(' }');
|
|
child.stdin.write(' }');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
if (child.stderr.str != '') { return (0); }
|
|
if (child.stdout.str.trim() != '')
|
|
{
|
|
try
|
|
{
|
|
return (this.getUid(child.stdout.str.trim()));
|
|
}
|
|
catch (e)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var min = this.minUid();
|
|
|
|
child.stdin.write("loginctl list-sessions | tr '\\n' '`' | awk '{");
|
|
child.stdin.write('printf "[";');
|
|
child.stdin.write('del="";');
|
|
child.stdin.write('n=split($0, lines, "`");');
|
|
child.stdin.write('for(i=1;i<n;++i)');
|
|
child.stdin.write('{');
|
|
child.stdin.write(' split(lines[i], tok, " ");');
|
|
child.stdin.write(' if((tok[2]+0)>=' + min + ')');
|
|
child.stdin.write(' {');
|
|
if (options && options.active == true)
|
|
{
|
|
child.stdin.write(' if(tok[4]=="") { continue; }');
|
|
}
|
|
else
|
|
{
|
|
child.stdin.write(' if(tok[4]=="" || tok[4]~/^pts\\//) { continue; }');
|
|
}
|
|
child.stdin.write(' printf "%s{\\"uid\\": \\"%s\\", \\"sid\\": \\"%s\\"}", del, tok[2], tok[1];');
|
|
child.stdin.write(' del=",";');
|
|
child.stdin.write(' }');
|
|
child.stdin.write('}');
|
|
child.stdin.write('printf "]";');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
|
|
console.info1(child.stdout.str);
|
|
var info1 = JSON.parse(child.stdout.str);
|
|
var sids = [];
|
|
var i;
|
|
for (i = 0; i < info1.length; ++i) { sids.push(info1[i].sid); }
|
|
console.info1('SIDS => ' + JSON.stringify(sids));
|
|
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("loginctl show-session -p State " + sids.join(' ') + " | grep State= | tr '\\n' '`' | awk -F'`' '{");
|
|
if (options && options.active == true)
|
|
{
|
|
child.stdin.write(' printf("[");');
|
|
child.stdin.write(' _first="";');
|
|
}
|
|
child.stdin.write(' for(n=1;n<NF;++n)');
|
|
child.stdin.write(' {');
|
|
if (options && options.active == true)
|
|
{
|
|
child.stdin.write(' if($n=="State=active")');
|
|
child.stdin.write(' {');
|
|
child.stdin.write(' printf("%s%s",_first,n);');
|
|
child.stdin.write(' _first=",";');
|
|
child.stdin.write(' }');
|
|
}
|
|
else
|
|
{
|
|
child.stdin.write(' if($n=="State=active") { print n; break; }');
|
|
}
|
|
child.stdin.write(' }');
|
|
if (options && options.active == true)
|
|
{
|
|
child.stdin.write(' printf("]");');
|
|
}
|
|
else
|
|
{
|
|
child.stdin.write(' if(n==NF) { print 0; }');
|
|
}
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
if (options && options.active == true)
|
|
{
|
|
try
|
|
{
|
|
var ret = JSON.parse(child.stdout.str);
|
|
for (var j=0;j<ret.length;++j)
|
|
{
|
|
ret[j] = parseInt(info1[ret[j] - 1].uid);
|
|
}
|
|
return (ret);
|
|
}
|
|
catch(xx)
|
|
{
|
|
return ([]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i = parseInt(child.stdout.str.trim());
|
|
if (i > 0)
|
|
{
|
|
return (parseInt(info1[i - 1].uid));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Before we say nobody is logged on, let's check to see if there is a GDM session
|
|
var gdm = this.gdmUid;
|
|
var info = require('monitor-info').getXInfo(gdm);
|
|
if (info == null || !info.xauthority || !info.display)
|
|
{
|
|
if (gdm == 0)
|
|
{
|
|
// Before we give up, lets see if there is an X session somewhere, probably from VNC
|
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.str = ''; child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("loginctl list-sessions | tr '\\n' '`' | awk '{");
|
|
child.stdin.write('printf "[";');
|
|
child.stdin.write('del="";');
|
|
child.stdin.write('n=split($0, lines, "`");');
|
|
child.stdin.write('for(i=1;i<n;++i)');
|
|
child.stdin.write('{');
|
|
child.stdin.write(' split(lines[i], tok, " ");');
|
|
child.stdin.write(' if((tok[2]+0)>=' + min + ')');
|
|
child.stdin.write(' {');
|
|
child.stdin.write(' printf "%s{\\"uid\\": \\"%s\\", \\"sid\\": \\"%s\\"}", del, tok[2], tok[1];');
|
|
child.stdin.write(' del=",";');
|
|
child.stdin.write(' }');
|
|
child.stdin.write('}');
|
|
child.stdin.write('printf "]";');
|
|
child.stdin.write("}'\nexit\n");
|
|
child.waitExit();
|
|
var info1 = JSON.parse(child.stdout.str);
|
|
var uids = [];
|
|
var i;
|
|
for (i = 0; i < info1.length; ++i) { uids.push(info1[i].uid); }
|
|
console.info1('UIDS => ' + JSON.stringify(sids));
|
|
|
|
while(uids.length>0)
|
|
{
|
|
var id = uids.pop();
|
|
info = require('monitor-info').getXInfo(id);
|
|
if(info!=null && info.xauthority != null && info.display != null)
|
|
{
|
|
return (parseInt(id));
|
|
}
|
|
}
|
|
}
|
|
|
|
throw ('nobody logged into console');
|
|
}
|
|
else
|
|
{
|
|
return (gdm);
|
|
}
|
|
}
|
|
|
|
this.getHomeFolder = function getHomeFolder(id)
|
|
{
|
|
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("getent passwd " + id + " | awk -F: '{print $6}'\nexit\n");
|
|
child.waitExit();
|
|
return (child.stdout.str.trim());
|
|
}
|
|
|
|
this.getUsername = function getUsername(uid)
|
|
{
|
|
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("getent passwd " + uid + " | awk -F: '{print $1}'\nexit\n");
|
|
child.waitExit();
|
|
if (child.stdout.str.length > 0) { return (child.stdout.str.trim()); }
|
|
throw ('uid: ' + uid + ' NOT FOUND');
|
|
};
|
|
this.getGroupname = function getGroupname(gid)
|
|
{
|
|
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("getent group " + gid + " | awk -F: '{print $1}'\nexit\n");
|
|
child.waitExit();
|
|
if (child.stdout.str.length > 0) { return (child.stdout.str.trim()); }
|
|
throw ('gid: ' + gid + ' NOT FOUND');
|
|
};
|
|
this.whoami = function whoami()
|
|
{
|
|
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("whoami\nexit\n");
|
|
child.waitExit();
|
|
return (child.stdout.str.trim());
|
|
};
|
|
this.getPids = function getPids(options)
|
|
{
|
|
var grep = '';
|
|
switch(typeof(options))
|
|
{
|
|
default:
|
|
throw ('Invalid type specified: ' + typeof (options));
|
|
break;
|
|
case 'number':
|
|
grep = ' | grep "' + this.getUsername(options) + '"';
|
|
break;
|
|
case 'string':
|
|
grep = ' | grep "' + options + '"';
|
|
break;
|
|
case 'object':
|
|
if (options.username) { grep = ' | grep "' + options.username + '"'; }
|
|
else if (options.uid != null) { grep = ' | grep "' + this.getUsername(options.uid) + '"'; }
|
|
if (options.grep)
|
|
{
|
|
grep += (' | grep "' + options.grep + '"');
|
|
}
|
|
break;
|
|
}
|
|
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
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.stdin.write('ps -e -o pid -o user -o cmd ' + grep + ' |' + " tr '\n' '`' | awk -F'`' '{ " + 'printf "["; for(i=1;i<NF;++i) { split($i, tok, " "); printf "%s%s",(i!=1?",":""), tok[1]; } printf "]"; }\'\nexit\n');
|
|
child.waitExit();
|
|
|
|
try
|
|
{
|
|
return (JSON.parse(child.stdout.str.trim()));
|
|
}
|
|
catch(ee)
|
|
{
|
|
return([]);
|
|
}
|
|
};
|
|
this.findEnvEntry = function findEnvEntry(options)
|
|
{
|
|
var broke = false;
|
|
var ret = {};
|
|
var pids = this.getPids(options);
|
|
|
|
var vals;
|
|
var j;
|
|
for(var i in pids)
|
|
{
|
|
broke = false;
|
|
ret = {};
|
|
vals = this.getEnvFromPid(pids[i]);
|
|
|
|
for (j in options.values)
|
|
{
|
|
if(vals[options.values[j]])
|
|
{
|
|
ret[options.values[j]] = vals[options.values[j]];
|
|
}
|
|
else
|
|
{
|
|
broke = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (broke)
|
|
{
|
|
return ({});
|
|
}
|
|
else
|
|
{
|
|
return (ret);
|
|
}
|
|
};
|
|
this.getEnvFromPid = function getEnvFromPid(pid)
|
|
{
|
|
var ret = {};
|
|
if (process.platform == 'linux')
|
|
{
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
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.stdin.write("cat /proc/" + pid + "/environ | tr '\\0' '\\t' |" + ' awk -F"\t" \'{ printf "{"; for(i=1;i<NF;++i) { if(i>1) {printf ",";} x=split($i, tok, "="); printf "\\"%s\\": \\"%s\\"", tok[1], substr($i, 2+length(tok[1])); } printf "}"; }\'');
|
|
child.stdin.write('\nexit\n');
|
|
child.waitExit();
|
|
|
|
try
|
|
{
|
|
return (JSON.parse(child.stdout.str.trim()));
|
|
}
|
|
catch(ee)
|
|
{
|
|
return ({});
|
|
}
|
|
}
|
|
else if (process.platform == 'freebsd')
|
|
{
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
|
child.stdin.write("procstat -e " + pid + " | grep " + pid + " | awk '{ $1=\"\"; $2=\"\"; print $0 }' | tr \"\\ \" \"\\n\"\nexit\n");
|
|
child.waitExit();
|
|
|
|
var env;
|
|
var tokens = child.stdout.str.trim().split('\n');
|
|
for(var i in tokens)
|
|
{
|
|
env = tokens[i].split('=');
|
|
ret[env[0]] = env[1];
|
|
}
|
|
}
|
|
return (ret);
|
|
};
|
|
this.findEnv = function findEnv(uid, env)
|
|
{
|
|
var uname = this.getUsername(uid);
|
|
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("ps " + (process.platform == 'freebsd' ? "-ax ":"") + "-e -o pid -o user | grep " + uname + " | awk '{ print $1 }'\nexit\n");
|
|
child.waitExit();
|
|
|
|
var lines = child.stdout.str.split('\n');
|
|
for (var n in lines)
|
|
{
|
|
var ln = lines[n].trim();
|
|
if (ln.length > 0)
|
|
{
|
|
var e = this.getEnvFromPid(ln);
|
|
if (e[env])
|
|
{
|
|
return (e[env]);
|
|
}
|
|
}
|
|
}
|
|
return (null);
|
|
};
|
|
}
|
|
else if(process.platform == 'darwin')
|
|
{
|
|
this.getUid = function getUid(username)
|
|
{
|
|
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("id " + username + " | awk '{ split($1, token, \"=\"); split(token[2], uid, \"(\"); print uid[1]; }'\nexit\n");
|
|
child.waitExit();
|
|
var ret = parseInt(child.stdout.str.trim());
|
|
child = null;
|
|
return (ret);
|
|
};
|
|
this.getGroupID = function getGroupID(uid)
|
|
{
|
|
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("id " + uid + " | awk '{ split($2, gid, \"=\"); if(gid[1]==\"gid\") { split(gid[2], gidnum, \"(\"); print gidnum[1]; } }'\nexit\n");
|
|
child.waitExit();
|
|
return (parseInt(child.stdout.str.trim()));
|
|
}
|
|
this.getUsername = function getUsername(uid)
|
|
{
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stderr.str = '';
|
|
child.stdout.str = '';
|
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("dscl . list /Users UniqueID | grep " + uid + " | awk '{ if($2==" + uid + "){ print $1 }}'\nexit\n");
|
|
child.waitExit();
|
|
var ret = child.stdout.str.trim();
|
|
child = null;
|
|
if(ret != '')
|
|
{
|
|
return (ret);
|
|
}
|
|
else
|
|
{
|
|
throw ('uid: ' + uid + ' not found');
|
|
}
|
|
};
|
|
this.getGroupname = function getGroupname(gid)
|
|
{
|
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
|
child.stderr.str = '';
|
|
child.stdout.str = '';
|
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("dscl . list /Groups PrimaryGroupID | grep " + gid + " | awk '{ if($2==" + gid + "){ print $1 }}'\nexit\n");
|
|
child.waitExit();
|
|
if(child.stdout.str.trim() != '')
|
|
{
|
|
return (child.stdout.str.trim());
|
|
}
|
|
else
|
|
{
|
|
throw ('gid: ' + gid + ' not found');
|
|
}
|
|
};
|
|
this.consoleUid = function consoleUid()
|
|
{
|
|
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("who | tr '\n' '\.' | awk '{ print $1 }'\nexit\n");
|
|
child.waitExit();
|
|
|
|
var ret = child.stdout.str.trim();
|
|
child = null;
|
|
if (ret != '')
|
|
{
|
|
return (this.getUid(ret));
|
|
}
|
|
throw ('nobody logged into console');
|
|
}
|
|
this.getHomeFolder = function getHomeFolder(user)
|
|
{
|
|
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("dscl . -read /Users/" + user + " | grep NFSHomeDirectory | awk -F: '{ print $2 }'\nexit\n");
|
|
child.waitExit();
|
|
if (child.stdout.str.trim() != '')
|
|
{
|
|
return (child.stdout.str.trim());
|
|
}
|
|
else
|
|
{
|
|
throw ('user: ' + user + ' not found');
|
|
}
|
|
};
|
|
this._users = function ()
|
|
{
|
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
|
child.stdout.str = '';
|
|
child.stderr.str = '';
|
|
child.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write('exit\n');
|
|
child.waitExit();
|
|
|
|
|
|
var lines = child.stdout.str.split('\n');
|
|
var tokens, i;
|
|
var users = {};
|
|
|
|
for (i = 0; i < lines.length; ++i) {
|
|
tokens = lines[i].split(' ');
|
|
if (tokens[0]) { users[tokens[0]] = tokens[tokens.length - 1]; }
|
|
}
|
|
|
|
return (users);
|
|
}
|
|
this._uids = function () {
|
|
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);
|
|
child.stdout.str = '';
|
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write('exit\n');
|
|
child.waitExit();
|
|
|
|
var lines = child.stdout.str.split('\n');
|
|
var tokens, i;
|
|
var users = {};
|
|
|
|
for (i = 0; i < lines.length; ++i) {
|
|
tokens = lines[i].split(' ');
|
|
if (tokens[0]) { users[tokens[tokens.length - 1]] = tokens[0]; }
|
|
}
|
|
|
|
return (users);
|
|
}
|
|
this._idTable = function()
|
|
{
|
|
var table = {};
|
|
var child = require('child_process').execFile('/usr/bin/id', ['id']);
|
|
child.stdout.str = '';
|
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.waitExit();
|
|
|
|
var lines = child.stdout.str.split('\n')[0].split(' ');
|
|
child = null;
|
|
for (var i = 0; i < lines.length; ++i) {
|
|
var types = lines[i].split('=');
|
|
var tokens = types[1].split(',');
|
|
table[types[0]] = {};
|
|
|
|
for (var j in tokens) {
|
|
var idarr = tokens[j].split('(');
|
|
var id = idarr[0];
|
|
var name = idarr[1].substring(0, idarr[1].length - 1).trim();
|
|
table[types[0]][name] = id;
|
|
table[types[0]][id] = name;
|
|
}
|
|
}
|
|
return (table);
|
|
}
|
|
this.Current = function (cb)
|
|
{
|
|
var users = {};
|
|
var table = this._idTable();
|
|
var child = require('child_process').execFile('/usr/bin/last', ['last']);
|
|
child.stdout.str = '';
|
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.waitExit();
|
|
|
|
var lines = child.stdout.str.split('\n');
|
|
for (var i = 0; i < lines.length && lines[i].length > 0; ++i)
|
|
{
|
|
if (!users[lines[i].split(' ')[0]])
|
|
{
|
|
try
|
|
{
|
|
users[lines[i].split(' ')[0]] = { Username: lines[i].split(' ')[0], State: lines[i].split('still logged in').length > 1 ? 'Active' : 'Inactive', uid: table.uid[lines[i].split(' ')[0]] };
|
|
}
|
|
catch(e)
|
|
{}
|
|
}
|
|
else
|
|
{
|
|
if(users[lines[i].split(' ')[0]].State != 'Active' && lines[i].split('still logged in').length > 1)
|
|
{
|
|
users[lines[i].split(' ')[0]].State = 'Active';
|
|
}
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(users, 'Active', { value: showActiveOnly(users) });
|
|
if (cb) { cb.call(this, users); }
|
|
}
|
|
}
|
|
|
|
if(process.platform != 'win32') // Linux, MacOS, FreeBSD
|
|
{
|
|
this.tty = function tty()
|
|
{
|
|
var child = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
|
child.stdout.str = ''; child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.stdin.write("tty | awk -F/ '{ printf \"\\x1e%s\\x1e\",$2; }'\nexit\n");
|
|
child.stdin.write("tty\nexit\n");
|
|
child.waitExit();
|
|
|
|
var val = child.stdout.str.split('\x1e');
|
|
return (val.length > 1 ? val[1] : 'root');
|
|
}
|
|
this.Self = function Self()
|
|
{
|
|
var child = require('child_process').execFile('/usr/bin/id', ['id', '-u']);
|
|
child.stdout.str = '';
|
|
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
|
|
child.waitExit();
|
|
var ret = parseInt(child.stdout.str);
|
|
child = null;
|
|
return (ret);
|
|
}
|
|
this.isRoot = function isRoot()
|
|
{
|
|
return (this.Self() == 0);
|
|
}
|
|
}
|
|
|
|
this.enumerateUsers = function enumerateUsers()
|
|
{
|
|
var promise = require('promise');
|
|
var p = new promise(function (res, rej)
|
|
{
|
|
this.__resolver = res;
|
|
this.__rejector = rej;
|
|
});
|
|
p.__handler = function __handler(users)
|
|
{
|
|
p.__resolver(users);
|
|
};
|
|
try
|
|
{
|
|
this.Current(p.__handler);
|
|
}
|
|
catch (e)
|
|
{
|
|
p.__rejector(e);
|
|
}
|
|
p.parent = this;
|
|
return (p);
|
|
}
|
|
}
|
|
function showActiveOnly(source)
|
|
{
|
|
var retVal = [];
|
|
var unique = {};
|
|
var usernames = [];
|
|
var tmp;
|
|
|
|
for (var i in source)
|
|
{
|
|
if (source[i].State == 'Active')
|
|
{
|
|
retVal.push(source[i]);
|
|
tmp = (source[i].Domain ? (source[i].Domain + '\\') : '') + source[i].Username;
|
|
if (!unique[tmp]) { unique[tmp] = tmp;}
|
|
}
|
|
}
|
|
|
|
for (var i in unique)
|
|
{
|
|
usernames.push(i);
|
|
}
|
|
|
|
Object.defineProperty(retVal, 'usernames', { value: usernames });
|
|
return (retVal);
|
|
}
|
|
function getTokens(str)
|
|
{
|
|
var columns = [];
|
|
var i;
|
|
|
|
columns.push(str.substring(0, (i=str.indexOf(' '))));
|
|
while (str[++i] == ' ');
|
|
columns.push(str.substring(i, (i=str.substring(i).indexOf(' ') + i)));
|
|
while (str[++i] == ' ');
|
|
columns.push(str.substring(i, (i=str.substring(i).indexOf(' ') + i)));
|
|
while (str[++i] == ' ');
|
|
var status = str.substring(i).trim();
|
|
columns.push(status);
|
|
|
|
return (columns);
|
|
}
|
|
|
|
module.exports = new UserSessions();
|