termbeam 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +76 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termbeam",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Beam your terminal to any device — mobile-optimized web terminal with multi-session support",
5
5
  "main": "src/server.js",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const os = require('os');
2
+ const fs = require('fs');
2
3
  const path = require('path');
3
4
  const crypto = require('crypto');
4
5
  const log = require('./logger');
@@ -76,7 +77,10 @@ function getWindowsAncestors(startPid, maxDepth = 4) {
76
77
  if (cols.length <= Math.max(nameIdx, pidIdx, ppidIdx)) continue;
77
78
  const pid = parseInt(cols[pidIdx], 10);
78
79
  if (Number.isFinite(pid)) {
79
- processes.set(pid, { name: cols[nameIdx].trim().toLowerCase(), ppid: parseInt(cols[ppidIdx], 10) });
80
+ processes.set(pid, {
81
+ name: cols[nameIdx].trim().toLowerCase(),
82
+ ppid: parseInt(cols[ppidIdx], 10),
83
+ });
80
84
  }
81
85
  }
82
86
 
@@ -97,6 +101,47 @@ function getWindowsAncestors(startPid, maxDepth = 4) {
97
101
  return names;
98
102
  }
99
103
 
104
+ /**
105
+ * Check if a process name is a known Unix shell by comparing against
106
+ * /etc/shells entries and a hardcoded fallback list.
107
+ */
108
+ function isKnownShell(name) {
109
+ if (!name || name.includes(' ')) return false;
110
+ const basename = path.basename(name);
111
+ const knownNames = new Set([
112
+ 'sh',
113
+ 'bash',
114
+ 'zsh',
115
+ 'fish',
116
+ 'dash',
117
+ 'ksh',
118
+ 'csh',
119
+ 'tcsh',
120
+ 'ash',
121
+ 'mksh',
122
+ 'elvish',
123
+ 'nu',
124
+ 'pwsh',
125
+ 'xonsh',
126
+ 'ion',
127
+ ]);
128
+ if (knownNames.has(basename)) return true;
129
+
130
+ // Check against /etc/shells
131
+ try {
132
+ const content = fs.readFileSync('/etc/shells', 'utf8');
133
+ for (const line of content.split('\n')) {
134
+ const entry = line.trim();
135
+ if (entry && !entry.startsWith('#')) {
136
+ if (entry === name || path.basename(entry) === basename) return true;
137
+ }
138
+ }
139
+ } catch {
140
+ // /etc/shells not available — rely on knownNames
141
+ }
142
+ return false;
143
+ }
144
+
100
145
  function getDefaultShell() {
101
146
  const { execFileSync } = require('child_process');
102
147
  const ppid = process.ppid;
@@ -137,8 +182,14 @@ function getDefaultShell() {
137
182
  const comm = result.trim();
138
183
  if (comm) {
139
184
  const shell = comm.startsWith('-') ? comm.slice(1) : comm;
140
- log.debug(`Detected parent shell: ${shell}`);
141
- return shell;
185
+ log.debug(`Detected parent process: ${shell}`);
186
+ // Validate it's a real shell by checking against /etc/shells and common names.
187
+ // When run via npx, the parent is "node" or "npm exec ..." — not a shell.
188
+ if (isKnownShell(shell)) {
189
+ log.debug(`Using detected shell: ${shell}`);
190
+ return shell;
191
+ }
192
+ log.debug(`Parent process "${shell}" is not a known shell, falling back`);
142
193
  }
143
194
  } catch (err) {
144
195
  log.debug(`Could not detect parent shell: ${err.message}`);
@@ -157,10 +208,16 @@ function parseArgs() {
157
208
  // Resolve log level early (env + args) so shell detection logs are visible
158
209
  let logLevel = process.env.TERMBEAM_LOG_LEVEL || 'info';
159
210
  for (const arg of process.argv.slice(2)) {
160
- if (arg.startsWith('--log-level=')) { logLevel = arg.split('=')[1]; break; }
211
+ if (arg.startsWith('--log-level=')) {
212
+ logLevel = arg.split('=')[1];
213
+ break;
214
+ }
161
215
  }
162
216
  for (let i = 2; i < process.argv.length; i++) {
163
- if (process.argv[i] === '--log-level' && process.argv[i + 1]) { logLevel = process.argv[i + 1]; break; }
217
+ if (process.argv[i] === '--log-level' && process.argv[i + 1]) {
218
+ logLevel = process.argv[i + 1];
219
+ break;
220
+ }
164
221
  }
165
222
  log.setLevel(logLevel);
166
223
 
@@ -227,7 +284,19 @@ function parseArgs() {
227
284
  const { getVersion } = require('./version');
228
285
  const version = getVersion();
229
286
 
230
- return { port, host, password, useTunnel, persistedTunnel, shell, shellArgs, cwd, defaultShell, version, logLevel };
287
+ return {
288
+ port,
289
+ host,
290
+ password,
291
+ useTunnel,
292
+ persistedTunnel,
293
+ shell,
294
+ shellArgs,
295
+ cwd,
296
+ defaultShell,
297
+ version,
298
+ logLevel,
299
+ };
231
300
  }
232
301
 
233
- module.exports = { parseArgs, printHelp };
302
+ module.exports = { parseArgs, printHelp, isKnownShell };