UNPKG

spawn-wrap

Version:

Wrap all spawned Node.js child processes by adding environs and arguments ahead of the main JavaScript file argument.

119 lines (87 loc) 4.55 kB
New approach: - `spawn('sh', ...)` Find the `-c` arg. Parse, and split up by `&&`, `||`, `;`, `&`, and `|`, expanding each bit. The parsing doesn't have to be complete, since it's not designed for security. Just handling quotes and escapes is probably enough. If someone sneaks in a `$VAR` that expands to a node shebang, oh well. If we DO want to make it work for security use cases, then it would perhaps be good to be able to detect these situations and throw an error or something. Then spawn the exploded command line. When we explode it, we need to do the same thing with looking up env and shebang results. However, if there are multiple parts, we can't change the actual thing that gets executed (ie, it must still be executed by calling `sh`, just with the exploded command line). `cmd` is basically the same, but the escapes are different, and we're looking for the `/c` argument rather than `-c`. In the short term, probably we should just explicitly not support windows, by printing a warning and doing nothing if run in Windows. This may be a case where explicit non-support is better than poor or partial support. Each portion of the sh command line looks like: `(key=val )*(command)( args)*` - `spawn('.../node', ...)` Inject the args before the main, if it has a main file, and call spawn with that. - `spawn('other', ...)` Check if it's a shebang file. If so, explode it to the resulting cli: `$interpreter $file`. In most cases, this will result in `env <envpairs> node <nodeoptions> $file` Note that a shebang is strictly space-delimited arguments. Quotes and escapes are not allowed here, which makes it much simpler. We can simply resolve this to `shebangLine.trim().split(/\s+/)`. If that first item is `env` then handle it just like a `spawn(env)`. - `spawn('env', ...)` An env command line is done by looking up the resulting thingy with `which()`, and then resolving it further if it's a shebangK - Always treat `bash`, `ksh`, and `zsh` the same as `sh`, since they have similar cli string behavior. ---- Different ways to spawn things: 1. `spawn('node', ...)` easiest. inject the args, add the envPairs 2. `spawn('sh', ['-c', 'X=y /path/to/node blah'])` Parse '-c' arg just like a exec line. Windows flavor: `spawn('cmd', ['/s', '/c', '"' + command + '"'])` replace `('sh', ['-c', '/path/to/node <inject args> blah'])` I think if we do this right, we don't have to do exec() maybe? 3. `spawn('sh', ['-c', '/usr/bin/env x=y node blah blah'])` This is the hard one, because the indirection capabilities are endless. `sh` can spawn `bash` which spawns `env` and so on. A. replace with `spawn('/usr/bin/env', ['x=y', 'node', '...'])` WARNING: requires writing a sh-compatible command line parser. Splitting based on spaces won't work. Eg: `sh -c 'command "long space"'` B. Write a node program that wraps cli commands, sort of like the wrap-main.js file. This will let us the just prepend it to the `sh -c` arg, and it can interpret the rest. C. Maybe we just have our own `node` and `iojs` scripts (and `node.cmd` and `iojs.cmd` for win32 peops), and we put those in a bin folder that we always prepend to the PATH environ. Then it almost doesn't *matter* what shebangs or whatever get run, because `which node` will always return that thing. Something to consider. (Also, that fakey `node` script cannot be a node program, obviously, because the shell won't know where to find it!) **OOPS!** no that won't work because how does the fake node shell script know what to inject to our wrap-main.js file? Computers are terrible. 4. `spawn('shebangscript', ['arg'])` resolve shebangscript using which() read first line of script `#!/some/interpreter some=args` -> `spawn('/some/interpreter', ['some=args', '$file'])` then handle appropriately 5. `spawn('/usr/bin/env', ['x=y', 'node', '$file'])` becomes case (1), `spawn('node', ['$file')`, but with the `x=y` appended to the envPairs list 6. `spawn('sh', ['-c', 'shebangscript arg'])` 7. `exec('/path/to/node blah blah')` becomes `spawn('sh', ['-c', '/path/to/node blah blah'])` 8. `exec('/usr/bin/env node blah blah')` becomes `spawn('sh', ['-c', '/usr/bin/env node blah blah'])` 9. `exec('sh -c "shebangscript arg"')` becomes `spawn('sh', ['-c', 'sh -c "shebangscript arg"'])` This is a dark pit of oblivion.