| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 | 
							- 'use strict';
 
- var fs = require('fs');
 
- var LRU = require('lru-cache');
 
- var resolveCommand = require('./resolveCommand');
 
- var isWin = process.platform === 'win32';
 
- var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 });  // Cache just for 30sec
 
- function readShebang(command) {
 
-     var buffer;
 
-     var fd;
 
-     var match;
 
-     var shebang;
 
-     // Check if it is in the cache first
 
-     if (shebangCache.has(command)) {
 
-         return shebangCache.get(command);
 
-     }
 
-     // Read the first 150 bytes from the file
 
-     buffer = new Buffer(150);
 
-     try {
 
-         fd = fs.openSync(command, 'r');
 
-         fs.readSync(fd, buffer, 0, 150, 0);
 
-         fs.closeSync(fd);
 
-     } catch (e) { /* empty */ }
 
-     // Check if it is a shebang
 
-     match = buffer.toString().trim().match(/#!(.+)/i);
 
-     if (match) {
 
-         shebang = match[1].replace(/\/usr\/bin\/env\s+/i, '');   // Remove /usr/bin/env
 
-     }
 
-     // Store the shebang in the cache
 
-     shebangCache.set(command, shebang);
 
-     return shebang;
 
- }
 
- function escapeArg(arg, quote) {
 
-     // Convert to string
 
-     arg = '' + arg;
 
-     // If we are not going to quote the argument,
 
-     // escape shell metacharacters, including double and single quotes:
 
-     if (!quote) {
 
-         arg = arg.replace(/([\(\)%!\^<>&|;,"'\s])/g, '^$1');
 
-     } else {
 
-         // Sequence of backslashes followed by a double quote:
 
-         // double up all the backslashes and escape the double quote
 
-         arg = arg.replace(/(\\*)"/g, '$1$1\\"');
 
-         // Sequence of backslashes followed by the end of the string
 
-         // (which will become a double quote later):
 
-         // double up all the backslashes
 
-         arg = arg.replace(/(\\*)$/, '$1$1');
 
-         // All other backslashes occur literally
 
-         // Quote the whole thing:
 
-         arg = '"' + arg + '"';
 
-     }
 
-     return arg;
 
- }
 
- function escapeCommand(command) {
 
-     // Do not escape if this command is not dangerous..
 
-     // We do this so that commands like "echo" or "ifconfig" work
 
-     // Quoting them, will make them unaccessible
 
-     return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArg(command, true);
 
- }
 
- function parse(command, args, options) {
 
-     var shebang;
 
-     var applyQuotes;
 
-     var file;
 
-     var original;
 
-     // Normalize arguments, similar to nodejs
 
-     if (args && !Array.isArray(args)) {
 
-         options = args;
 
-         args = null;
 
-     }
 
-     args = args ? args.slice(0) : [];  // Clone array to avoid changing the original
 
-     options = options || {};
 
-     original = command;
 
-     if (isWin) {
 
-         // Detect & add support for shebangs
 
-         file = resolveCommand(command);
 
-         file = file || resolveCommand(command, true);
 
-         shebang = file && readShebang(file);
 
-         if (shebang) {
 
-             args.unshift(file);
 
-             command = shebang;
 
-         }
 
-         // Escape command & arguments
 
-         applyQuotes = command !== 'echo';  // Do not quote arguments for the special "echo" command
 
-         command = escapeCommand(command);
 
-         args = args.map(function (arg) {
 
-             return escapeArg(arg, applyQuotes);
 
-         });
 
-         // Use cmd.exe
 
-         args = ['/s', '/c', '"' + command + (args.length ? ' ' + args.join(' ') : '') + '"'];
 
-         command = process.env.comspec || 'cmd.exe';
 
-         // Tell node's spawn that the arguments are already escaped
 
-         options.windowsVerbatimArguments = true;
 
-     }
 
-     return {
 
-         command: command,
 
-         args: args,
 
-         options: options,
 
-         file: file,
 
-         original: original,
 
-     };
 
- }
 
- module.exports = parse;
 
 
  |