UNPKG

9.55 kBJavaScriptView Raw
1'use strict';
2// @ts-check
3// ==================================================================================
4// users.js
5// ----------------------------------------------------------------------------------
6// Description: System Information - library
7// for Node.js
8// Copyright: (c) 2014 - 2020
9// Author: Sebastian Hildebrandt
10// ----------------------------------------------------------------------------------
11// License: MIT
12// ==================================================================================
13// 11. Users/Sessions
14// ----------------------------------------------------------------------------------
15
16const exec = require('child_process').exec;
17const util = require('./util');
18
19let _platform = process.platform;
20
21const _linux = (_platform === 'linux');
22const _darwin = (_platform === 'darwin');
23const _windows = (_platform === 'win32');
24const _freebsd = (_platform === 'freebsd');
25const _openbsd = (_platform === 'openbsd');
26const _netbsd = (_platform === 'netbsd');
27const _sunos = (_platform === 'sunos');
28
29let _winDateFormat = {
30 dateFormat: '',
31 dateSeperator: '',
32 timeFormat: '',
33 timeSeperator: '',
34 amDesignator: '',
35 pmDesignator: ''
36};
37
38// --------------------------
39// array of users online = sessions
40
41function getWinCulture() {
42 return new Promise((resolve) => {
43 process.nextTick(() => {
44 if (!_winDateFormat.dateFormat) {
45 util.powerShell('(get-culture).DateTimeFormat')
46 .then(data => {
47 let lines = data.toString().split('\r\n');
48 _winDateFormat.dateFormat = util.getValue(lines, 'ShortDatePattern', ':');
49 _winDateFormat.dateSeperator = util.getValue(lines, 'DateSeparator', ':');
50 _winDateFormat.timeFormat = util.getValue(lines, 'ShortTimePattern', ':');
51 _winDateFormat.timeSeperator = util.getValue(lines, 'TimeSeparator', ':');
52 _winDateFormat.amDesignator = util.getValue(lines, 'AMDesignator', ':');
53 _winDateFormat.pmDesignator = util.getValue(lines, 'PMDesignator', ':');
54
55 resolve(_winDateFormat);
56 })
57 .catch(() => {
58 resolve(_winDateFormat);
59 });
60 } else {
61 resolve(_winDateFormat);
62 }
63 });
64 });
65}
66
67function parseUsersLinux(lines, phase) {
68 let result = [];
69 let result_who = [];
70 let result_w = {};
71 let w_first = true;
72 let w_header = [];
73 let w_pos = [];
74 let who_line = {};
75
76 let is_whopart = true;
77 lines.forEach(function (line) {
78 if (line === '---') {
79 is_whopart = false;
80 } else {
81 let l = line.replace(/ +/g, ' ').split(' ');
82
83 // who part
84 if (is_whopart) {
85 result_who.push({
86 user: l[0],
87 tty: l[1],
88 date: l[2],
89 time: l[3],
90 ip: (l && l.length > 4) ? l[4].replace(/\(/g, '').replace(/\)/g, '') : ''
91 });
92 } else {
93 // w part
94 if (w_first) { // header
95 w_header = l;
96 w_header.forEach(function (item) {
97 w_pos.push(line.indexOf(item));
98 });
99 w_first = false;
100 } else {
101 // split by w_pos
102 result_w.user = line.substring(w_pos[0], w_pos[1] - 1).trim();
103 result_w.tty = line.substring(w_pos[1], w_pos[2] - 1).trim();
104 result_w.ip = line.substring(w_pos[2], w_pos[3] - 1).replace(/\(/g, '').replace(/\)/g, '').trim();
105 result_w.command = line.substring(w_pos[7], 1000).trim();
106 // find corresponding 'who' line
107 who_line = result_who.filter(function (obj) {
108 return (obj.user.substring(0, 8).trim() === result_w.user && obj.tty === result_w.tty);
109 });
110 if (who_line.length === 1) {
111 result.push({
112 user: who_line[0].user,
113 tty: who_line[0].tty,
114 date: who_line[0].date,
115 time: who_line[0].time,
116 ip: who_line[0].ip,
117 command: result_w.command
118 });
119 }
120 }
121 }
122 }
123 });
124 if (result.length === 0 && phase === 2) {
125 return result_who;
126 } else {
127 return result;
128 }
129}
130
131function parseUsersDarwin(lines) {
132 let result = [];
133 let result_who = [];
134 let result_w = {};
135 let who_line = {};
136
137 let is_whopart = true;
138 lines.forEach(function (line) {
139 if (line === '---') {
140 is_whopart = false;
141 } else {
142 let l = line.replace(/ +/g, ' ').split(' ');
143
144 // who part
145 if (is_whopart) {
146 result_who.push({
147 user: l[0],
148 tty: l[1],
149 date: ('' + new Date().getFullYear()) + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(l[2].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + l[3]).slice(-2),
150 time: l[4],
151 });
152 } else {
153 // w part
154 // split by w_pos
155 result_w.user = l[0];
156 result_w.tty = l[1];
157 result_w.ip = (l[2] !== '-') ? l[2] : '';
158 result_w.command = l.slice(5, 1000).join(' ');
159 // find corresponding 'who' line
160 who_line = result_who.filter(function (obj) {
161 return (obj.user === result_w.user && (obj.tty.substring(3, 1000) === result_w.tty || obj.tty === result_w.tty));
162 });
163 if (who_line.length === 1) {
164 result.push({
165 user: who_line[0].user,
166 tty: who_line[0].tty,
167 date: who_line[0].date,
168 time: who_line[0].time,
169 ip: result_w.ip,
170 command: result_w.command
171 });
172 }
173 }
174 }
175 });
176 return result;
177}
178
179function parseUsersWin(lines, culture) {
180
181 let result = [];
182 const header = lines[0];
183 const headerDelimiter = [];
184 if (header) {
185 const start = (header[0] === ' ') ? 1 : 0;
186 headerDelimiter.push(start - 1);
187 let nextSpace = 0;
188 for (let i = start + 1; i < header.length; i++) {
189 if (header[i] === ' ' && ((header[i - 1] === ' ') || (header[i - 1] === '.'))) {
190 nextSpace = i;
191 } else {
192 if (nextSpace) {
193 headerDelimiter.push(nextSpace);
194 nextSpace = 0;
195 }
196 }
197 }
198 for (let i = 1; i < lines.length; i++) {
199 if (lines[i].trim()) {
200 const user = lines[i].substring(headerDelimiter[0] + 1, headerDelimiter[1]).trim() || '';
201 const tty = lines[i].substring(headerDelimiter[1] + 1, headerDelimiter[2] - 2).trim() || '';
202 const dateTime = util.parseDateTime(lines[i].substring(headerDelimiter[5] + 1, 2000).trim(), culture) || '';
203 result.push({
204 user: user,
205 tty: tty,
206 date: dateTime.date,
207 time: dateTime.time,
208 ip: '',
209 command: ''
210 });
211 }
212 }
213 }
214 return result;
215}
216
217function users(callback) {
218
219 return new Promise((resolve) => {
220 process.nextTick(() => {
221 let result = [];
222
223 // linux
224 if (_linux) {
225 exec('who --ips; echo "---"; w | tail -n +2', function (error, stdout) {
226 if (!error) {
227 // lines / split
228 let lines = stdout.toString().split('\n');
229 result = parseUsersLinux(lines, 1);
230 if (result.length === 0) {
231 exec('who; echo "---"; w | tail -n +2', function (error, stdout) {
232 if (!error) {
233 // lines / split
234 lines = stdout.toString().split('\n');
235 result = parseUsersLinux(lines, 2);
236 }
237 if (callback) { callback(result); }
238 resolve(result);
239 });
240 } else {
241 if (callback) { callback(result); }
242 resolve(result);
243 }
244 } else {
245 if (callback) { callback(result); }
246 resolve(result);
247 }
248 });
249 }
250 if (_freebsd || _openbsd || _netbsd) {
251 exec('who; echo "---"; w -ih', function (error, stdout) {
252 if (!error) {
253 // lines / split
254 let lines = stdout.toString().split('\n');
255 result = parseUsersDarwin(lines);
256 }
257 if (callback) { callback(result); }
258 resolve(result);
259 });
260 }
261 if (_sunos) {
262 exec('who; echo "---"; w -h', function (error, stdout) {
263 if (!error) {
264 // lines / split
265 let lines = stdout.toString().split('\n');
266 result = parseUsersDarwin(lines);
267 }
268 if (callback) { callback(result); }
269 resolve(result);
270 });
271 }
272
273 if (_darwin) {
274 exec('who; echo "---"; w -ih', function (error, stdout) {
275 if (!error) {
276 // lines / split
277 let lines = stdout.toString().split('\n');
278 result = parseUsersDarwin(lines);
279 }
280 if (callback) { callback(result); }
281 resolve(result);
282 });
283 }
284 if (_windows) {
285 try {
286 exec('query user', util.execOptsWin, function (error, stdout) {
287 if (stdout) {
288 // lines / split
289 let lines = stdout.toString().split('\r\n');
290 getWinCulture()
291 .then(culture => {
292 result = parseUsersWin(lines, culture);
293 if (callback) { callback(result); }
294 resolve(result);
295 });
296 } else {
297 if (callback) { callback(result); }
298 resolve(result);
299 }
300 });
301 } catch (e) {
302 if (callback) { callback(result); }
303 resolve(result);
304 }
305 }
306
307 });
308 });
309}
310
311exports.users = users;