Initial commit
[yaffs-website] / node_modules / grunt-contrib-sass / node_modules / cross-spawn / index.js
1 var fs = require('fs');
2 var path = require('path');
3 var cp = require('child_process');
4 var LRU = require('lru-cache');
5
6 var isWin = process.platform === 'win32';
7 var shebangCache = LRU({ max: 50, maxAge: 30 * 1000 });
8
9 function readShebang(command) {
10     var buffer;
11     var fd;
12     var match;
13     var shebang;
14
15     // Resolve command to an absolute path if it contains /
16     if (command.indexOf(path.sep) !== -1) {
17         command = path.resolve(command);
18     }
19
20     // Check if its resolved in the cache
21     shebang = shebangCache.get(command);
22     if (shebang) {
23         return shebang;
24     }
25
26     // Read the first 150 bytes from the file
27     buffer = new Buffer(150);
28
29     try {
30         fd = fs.openSync(command, 'r');
31         fs.readSync(fd, buffer, 0, 150, 0);
32     } catch (e) {}
33
34     // Check if it is a shebang
35     match = buffer.toString().trim().match(/\#\!\/usr\/bin\/env ([^\r\n]+)/i);
36     shebang = match && match[1];
37
38     // Store the shebang in the cache
39     shebangCache.set(command, shebang);
40
41     return shebang;
42 }
43
44 function escapeArg(arg, quote) {
45     // Convert to string
46     arg = '' + arg;
47
48     // If we are not going to quote the argument,
49     // escape shell metacharacters, including double and single quotes:
50     if (!quote) {
51         arg = arg.replace(/([\(\)%!\^<>&|;,"' ])/g, '^$1');
52     } else {
53         // Sequence of backslashes followed by a double quote:
54         // double up all the backslashes and escape the double quote
55         arg = arg.replace(/(\\*)"/gi, '$1$1\\"');
56
57         // Sequence of backslashes followed by the end of the string
58         // (which will become a double quote later):
59         // double up all the backslashes
60         arg = arg.replace(/(\\*)$/, '$1$1');
61
62         // All other backslashes occur literally
63
64         // Quote the whole thing:
65         arg = '"' + arg + '"';
66     }
67
68     return arg;
69 }
70
71 function escapeCommand(command) {
72     // Do not escape if this command is not dangerous..
73     // We do this so that commands like "echo" or "ifconfig" work
74     // Quoting them, will make them unnaccessible
75     return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArg(command, true);
76 }
77
78 function spawn(command, args, options) {
79     var applyQuotes;
80     var shebang;
81
82     args = args || [];
83     options = options || {};
84
85     // Use node's spawn if not on windows
86     if (!isWin) {
87         return cp.spawn(command, args, options);
88     }
89
90     // Detect & add support for shebangs
91     shebang = readShebang(command);
92     if (shebang) {
93         args.unshift(command);
94         command = shebang;
95     }
96
97     // Escape command & arguments
98     applyQuotes = command !== 'echo';  // Do not quote arguments for the special "echo" command
99     command = escapeCommand(command);
100     args = args.map(function (arg) {
101         return escapeArg(arg, applyQuotes);
102     });
103
104     // Use cmd.exe
105     args = ['/s', '/c', '"' + command + (args.length ? ' ' + args.join(' ') : '') + '"'];
106     command = process.env.comspec || 'cmd.exe';
107
108     // Tell node's spawn that the arguments are already escaped
109     options.windowsVerbatimArguments = true;
110
111     return cp.spawn(command, args, options);
112 }
113
114 module.exports = spawn;
115 module.exports.spawn = spawn;