'use strict';

var path = require('path');
var fs = require('fs');
var util = require('util');
var os = require('os');
var rimraf = require('rimraf').sync;
var hasNative = require('./lib/has-native.js');

// Try to load execSync which lets us synchronously invoke a command
// Fallback to invoking the command using child_process and busy
// waiting for an output file
var nativeExec, cp;
if (hasNative) {
  nativeExec = require('execSync').run;
} else {
  cp = require('child_process');
  console.warn('native module could not be found so busy waiting will be used for spawn-sync');
}

function invoke(cmd) {
  var logFileDir = path.normalize(path.join(os.tmpdir(), String(process.pid)));
  // location to keep flag for busy waiting fallback
  var finished = path.join(logFileDir, "finished");
  var code;

  if (nativeExec) {
    return nativeExec(cmd);
  }

  if (fs.existsSync(finished)) {
    fs.unlinkSync(finished);
  }
  cmd = cmd + '; echo $? > ' + finished;
  cp.exec(cmd);

  while (!fs.existsSync(finished)) {
    // busy wait
  }
  try {
    code = fs.readFileSync(finished);
    fs.unlinkSync(finished);
  } catch (ex) { }

  //fallback to a 0 if the code is NaN or undefined
  return parseInt(code, 10) || 0;
}


module.exports = spawn;
function spawn(cmd, args, options) {
  options = options || {};
  var logFileDir = path.normalize(path.join(os.tmpdir(), String(process.pid)));
  rimraf(logFileDir);
  fs.mkdirSync(logFileDir);
  var stdout = path.join(logFileDir, "stdout");
  var stderr = path.join(logFileDir, "stderr");
  if (fs.existsSync(stdout)) {
    fs.unlinkSync(stdout);
  }
  if (fs.existsSync(stderr)) {
    fs.unlinkSync(stderr);
  }

  // node.js script to read input into the command pipeline
  var read = path.normalize(__dirname + '/read.js');
  // location to store input for stdin
  var input = path.join(logFileDir, 'input');

  if (args && args.length) {
    cmd += ' ' + args.join(' ')
  }
  cmd = cmd + ' > ' + stdout + ' 2> ' + stderr;
  if (options.input) {
    fs.writeFileSync(input, options.input, {encoding: options.encoding});
    cmd = util.format('node %s %s | %s', read, input, cmd);
  }
  var exitCode = invoke(cmd);
  var res = {
    status: exitCode,
    stdout: fs.readFileSync(stdout),
    stderr: fs.readFileSync(stderr)
  };
  if (options.input) {
    fs.unlinkSync(input);
  }
  try {
    fs.unlinkSync(stdout);
    fs.unlinkSync(stderr);
    rimraf(logFileDir);
  } catch (ex) {
    // don't fail completely if a file just seems to be locked
    console.warn(ex.stack || ex.message || ex);
  }
  return res;
}

'use strict';

var path = require('path');
var fs = require('fs');
var util = require('util');
var os = require('os');
var rimraf = require('rimraf').sync;
var hasNative = require('./lib/has-native.js');

// Try to load execSync which lets us synchronously invoke a command
// Fallback to invoking the command using child_process and busy
// waiting for an output file
var nativeExec, cp;
if (hasNative) {
  nativeExec = require('execSync').run;
} else {
  cp = require('child_process');
  console.warn('native module could not be found so busy waiting will be used for spawn-sync');
}

function invoke(cmd) {
  var logFileDir = path.normalize(path.join(os.tmpdir(), String(process.pid)));
  // location to keep flag for busy waiting fallback
  var finished = path.join(logFileDir, "finished");
  var code;

  if (nativeExec) {
    return nativeExec(cmd);
  }

  if (fs.existsSync(finished)) {
    fs.unlinkSync(finished);
  }
  if (process.platform === 'win32') {
    cmd = cmd + '& echo %errorlevel% > ' + finished;
  } else {
    cmd = cmd + '; echo $? > ' + finished;
  }
  cp.exec(cmd);

  while (!fs.existsSync(finished)) {
    // busy wait
  }
  try {
    code = fs.readFileSync(finished);
    fs.unlinkSync(finished);
  } catch (ex) { }

  //fallback to a 0 if the code is NaN or undefined
  return parseInt(code, 10) || 0;
}


module.exports = spawn;
function spawn(cmd, args, options) {
  options = options || {};
  var logFileDir = path.normalize(path.join(os.tmpdir(), String(process.pid)));
  rimraf(logFileDir);
  fs.mkdirSync(logFileDir);
  var stdout = path.join(logFileDir, "stdout");
  var stderr = path.join(logFileDir, "stderr");
  if (fs.existsSync(stdout)) {
    fs.unlinkSync(stdout);
  }
  if (fs.existsSync(stderr)) {
    fs.unlinkSync(stderr);
  }

  // node.js script to read input into the command pipeline
  var read = path.normalize(__dirname + '/read.js');
  // location to store input for stdin
  var input = path.join(logFileDir, 'input');

  if (args && args.length) {
    cmd += ' ' + args.join(' ')
  }
  cmd = cmd + ' > ' + stdout + ' 2> ' + stderr;
  if (options.input) {
    fs.writeFileSync(input, options.input, {encoding: options.encoding});
    cmd = util.format('node %s %s | %s', read, input, cmd);
  }
  var exitCode = invoke(cmd);
  var res = {
    status: exitCode,
    stdout: fs.readFileSync(stdout),
    stderr: fs.readFileSync(stderr)
  };
  if (options.input) {
    fs.unlinkSync(input);
  }
  try {
    fs.unlinkSync(stdout);
    fs.unlinkSync(stderr);
    rimraf(logFileDir);
  } catch (ex) {
    // don't fail completely if a file just seems to be locked
    console.warn(ex.stack || ex.message || ex);
  }
  return res;
}

Fix for running on windows