1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | const exec = require('child_process').exec;
|
17 | const util = require('./util');
|
18 |
|
19 | let _platform = process.platform;
|
20 |
|
21 | const _linux = (_platform === 'linux');
|
22 | const _darwin = (_platform === 'darwin');
|
23 | const _windows = (_platform === 'win32');
|
24 | const _freebsd = (_platform === 'freebsd');
|
25 | const _openbsd = (_platform === 'openbsd');
|
26 | const _netbsd = (_platform === 'netbsd');
|
27 | const _sunos = (_platform === 'sunos');
|
28 |
|
29 | let _winDateFormat = {
|
30 | dateFormat: '',
|
31 | dateSeperator: '',
|
32 | timeFormat: '',
|
33 | timeSeperator: '',
|
34 | amDesignator: '',
|
35 | pmDesignator: ''
|
36 | };
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | function 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 |
|
67 | function 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 |
|
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 |
|
94 | if (w_first) {
|
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 |
|
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 |
|
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 |
|
131 | function 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 |
|
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 |
|
154 |
|
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 |
|
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 |
|
179 | function 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 |
|
217 | function users(callback) {
|
218 |
|
219 | return new Promise((resolve) => {
|
220 | process.nextTick(() => {
|
221 | let result = [];
|
222 |
|
223 |
|
224 | if (_linux) {
|
225 | exec('who --ips; echo "---"; w | tail -n +2', function (error, stdout) {
|
226 | if (!error) {
|
227 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
311 | exports.users = users;
|