Files
grunt-bg-shell/tasks/child-process.coffee
2013-10-16 18:00:13 +02:00

112 lines
2.2 KiB
CoffeeScript

util = require 'util'
spawn = require('child_process').spawn
exports.execCmd = (command, options, callback)->
util._extend(
encoding: "utf8"
timeout: 0
maxBuffer: 200 * 1024
killSignal: "SIGTERM"
cwd: null
env: null
,
options
)
unless options.maxBuffer > 0 and isFinite options.maxBuffer
options.maxBuffer = false
if process.platform is "win32"
file = "cmd.exe"
args = ["/s", "/c", "\"" + command + "\""]
options.windowsVerbatimArguments = true
else
file = "/bin/sh"
args = ["-c", command]
child = spawn(file, args,
cwd: options.cwd
env: options.env
stdio: [process.stdin]
windowsVerbatimArguments: !!options.windowsVerbatimArguments
)
stdout = null
stderr = null
killed = false
exited = false
timeoutId = null
err = null
exithandler = (code, signal) ->
return if exited
exited = true
if timeoutId
clearTimeout timeoutId
return unless callback
if err
callback err, stdout, stderr
else if code is 0 and signal is null
callback null, stdout, stderr
else
e = new Error "Command failed: " + (stderr || command)
e.killed = child.killed or killed
e.code = code
e.signal = signal
callback e, stdout, stderr
errorhandler = (e) ->
err = e
child.stdout.destroy()
child.stderr.destroy()
exithandler()
kill = ->
child.stdout.destroy()
child.stderr.destroy()
killed = true
try
child.kill options.killSignal
catch e
err = e
exithandler()
if options.timeout > 0
timeoutId = setTimeout kill, options.timeout
child.stdout.setEncoding options.encoding
child.stderr.setEncoding options.encoding
if options.maxBuffer
stdout = ''
stderr = ''
child.stdout.addListener "data", (chunk) ->
stdout += chunk
if stdout.length > options.maxBuffer
err = new Error("stdout maxBuffer exceeded.")
kill()
child.stderr.addListener "data", (chunk) ->
stderr += chunk
if stderr.length > options.maxBuffer
err = new Error("stderr maxBuffer exceeded.")
kill()
child.addListener "close", exithandler
child.addListener "error", errorhandler
child