4 var path = require("path")
6 , COLON = process.platform === "win32" ? ";" : ":"
10 if (process.platform == "win32") {
11 // On windows, there is no good way to check that a file is executable
12 isExe = function isExe () { return true }
14 isExe = function isExe (mod, uid, gid) {
15 //console.error(mod, uid, gid);
16 //console.error("isExe?", (mod & 0111).toString(8))
17 var ret = (mod & 0001)
18 || (mod & 0010) && process.getgid && gid === process.getgid()
19 || (mod & 0010) && process.getuid && 0 === process.getuid()
20 || (mod & 0100) && process.getuid && uid === process.getuid()
21 || (mod & 0100) && process.getuid && 0 === process.getuid()
22 //console.error("isExe?", ret)
29 function which (cmd, cb) {
30 if (isAbsolute(cmd)) return cb(null, cmd)
31 var pathEnv = (process.env.PATH || "").split(COLON)
33 if (process.platform === "win32") {
34 pathEnv.push(process.cwd())
35 pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
36 if (cmd.indexOf(".") !== -1) pathExt.unshift("")
38 //console.error("pathEnv", pathEnv)
40 if (i === l) return cb(new Error("not found: "+cmd))
41 var p = path.resolve(pathEnv[i], cmd)
42 ;(function E (ii, ll) {
43 if (ii === ll) return F(i + 1, l)
45 //console.error(p + ext)
46 fs.stat(p + ext, function (er, stat) {
50 isExe(stat.mode, stat.uid, stat.gid)) {
51 //console.error("yes, exe!", p + ext)
52 return cb(null, p + ext)
60 function whichSync (cmd) {
61 if (isAbsolute(cmd)) return cmd
62 var pathEnv = (process.env.PATH || "").split(COLON)
64 if (process.platform === "win32") {
65 pathEnv.push(process.cwd())
66 pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
67 if (cmd.indexOf(".") !== -1) pathExt.unshift("")
69 for (var i = 0, l = pathEnv.length; i < l; i ++) {
70 var p = path.join(pathEnv[i], cmd)
71 for (var j = 0, ll = pathExt.length; j < ll; j ++) {
72 var cur = p + pathExt[j]
74 try { stat = fs.statSync(cur) } catch (ex) {}
77 isExe(stat.mode, stat.uid, stat.gid)) return cur
80 throw new Error("not found: "+cmd)
83 var isAbsolute = process.platform === "win32" ? absWin : absUnix
86 if (absUnix(p)) return true
87 // pull off the device/UNC bit from a windows path.
88 // from node's lib/path.js
90 /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
91 , result = splitDeviceRe.exec(p)
92 , device = result[1] || ''
93 , isUnc = device && device.charAt(1) !== ':'
94 , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
99 function absUnix (p) {
100 return p.charAt(0) === "/" || p === ""