termbeam 1.0.2 → 1.0.4

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 +3 -2
  2. package/src/cli.js +47 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termbeam",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
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": {
@@ -14,7 +14,8 @@
14
14
  "prepare": "husky",
15
15
  "format": "prettier --write .",
16
16
  "lint": "node --check src/*.js bin/*.js",
17
- "prepublishOnly": "npm test"
17
+ "prepublishOnly": "npm test",
18
+ "postinstall": "node -e \"try{const p=require('path'),fs=require('fs'),d=p.join(__dirname,'node_modules','node-pty','prebuilds');if(fs.existsSync(d)){for(const a of fs.readdirSync(d)){const s=p.join(d,a,'spawn-helper');try{fs.chmodSync(s,0o755)}catch{}}}}catch{}\""
18
19
  },
19
20
  "keywords": [
20
21
  "terminal",
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');
@@ -100,6 +101,47 @@ function getWindowsAncestors(startPid, maxDepth = 4) {
100
101
  return names;
101
102
  }
102
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
+
103
145
  function getDefaultShell() {
104
146
  const { execFileSync } = require('child_process');
105
147
  const ppid = process.ppid;
@@ -141,13 +183,13 @@ function getDefaultShell() {
141
183
  if (comm) {
142
184
  const shell = comm.startsWith('-') ? comm.slice(1) : comm;
143
185
  log.debug(`Detected parent process: ${shell}`);
144
- // Validate it looks like a real shell (single token, no spaces)
145
- // When run via npx, comm can be "npm exec ..." which is not a shell
146
- if (!shell.includes(' ') && !shell.startsWith('npm') && !shell.startsWith('node')) {
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)) {
147
189
  log.debug(`Using detected shell: ${shell}`);
148
190
  return shell;
149
191
  }
150
- log.debug(`Parent process "${shell}" is not a shell, falling back`);
192
+ log.debug(`Parent process "${shell}" is not a known shell, falling back`);
151
193
  }
152
194
  } catch (err) {
153
195
  log.debug(`Could not detect parent shell: ${err.message}`);
@@ -257,4 +299,4 @@ function parseArgs() {
257
299
  };
258
300
  }
259
301
 
260
- module.exports = { parseArgs, printHelp };
302
+ module.exports = { parseArgs, printHelp, isKnownShell };