Completed node.js wmiir convenience library.
// wmiir controller module | |
// Adam R. Nelson | |
// August 2013 | |
var spawn = require('child_process').spawn; | |
// Spawns and returns a child process that runs `wmiir read`. | |
// The callback takes two parameters: (err, line). | |
// It is called once for each line in the file read. | |
// - err is any error that occurred, or null if no error occurred. | |
// - line is the last line read from the file. | |
exports.read = function(path, callback) { | |
// Start the process. | |
var child = spawn('wmiir', ['read', path]); | |
// Record the error stream, so that any error messages that wmiir produces | |
// can be passed on to the callback. | |
var stderr=""; | |
child.stderr.on('data', function(chunk) {stderr += chunk;}); | |
// If there's an error, pass it to the callback. | |
child.on('error', function(err) {if (callback) callback(err);}); | |
// Read from the process's stdout until a newline is encountered, then pass | |
// the line to the callback. | |
var line=""; | |
function handleData(chunk) { | |
try { | |
// Data from stdout is usually returned in the form of a Buffer, | |
// not a String. Make sure to convert it. | |
if (chunk instanceof Buffer) | |
chunk = chunk.toString(); | |
// If a newline is encountered, call the callback with everything | |
// that was read up until the newline. | |
var newline = chunk.indexOf('\n'); | |
if (newline > -1) { | |
if (callback) callback(null, line + chunk.slice(0, newline)); | |
line = ""; | |
var remaining = chunk.slice(newline+1); | |
if (remaining.length > 0) | |
handleData(remaining); | |
} else { | |
// Otherwise, store the output for later. | |
line += chunk; | |
} | |
} catch (e) { | |
if (callback) callback(e); | |
callback = null; | |
child.kill(); | |
} | |
} | |
child.stdout.on('data', handleData); | |
// If the process exits with a nonzero exit code, throw an error with the | |
// content of stderr, which should contain a message. | |
child.on('exit', function(code, signal) { | |
if (code !== 0) { | |
if (callback) callback(new Error(stderr)); | |
} | |
// Also, make sure to return the last line read, if there was one. | |
else if (line !== "") { | |
if (callback) callback(null, line); | |
} | |
}); | |
// Return the child process, as a handle in case we need to kill it. | |
return child; | |
}; | |
// Spawns and returns a child process that runs `wmiir write`. | |
// The given data is sent to this process's stdin. | |
// The callback takes one parameter: (err). | |
// - err is any error that occurred, or null if no error occurred. | |
exports.write = function(path, data, callback) { | |
// Some of this is the same as `read`, so I'll only comment the parts that | |
// are different. | |
var child = spawn('wmiir', ['write', path]); | |
var stderr=""; | |
child.stderr.on('data', function(line) {stderr += line;}); | |
child.on('error', function(err) {if (callback) callback(err);}); | |
child.on('exit', function(code, signal) { | |
if (code === 0) { | |
// If the process exits normally, execute the callback. | |
if (callback) callback(null); | |
} else { | |
if (callback) callback(new Error(stderr)); | |
} | |
}); | |
// Write the data to the file. | |
// This closes stdin, which should also terminate the child process. | |
child.stdin.end(data); | |
return child; | |
}; | |
// Spawns and returns a child process that runs `wmiir ls`. | |
// The callback takes two parameters: (err, results). | |
// - err is any error that occurred, or null if no error occurred. | |
// - results is the full output from the process's stdout. | |
exports.ls = function(path, callback) { | |
var child = spawn('wmiir', ['ls', path]); | |
var stdout = "", stderr=""; | |
child.stdout.on('data', function(chunk) {stdout += chunk;}); | |
child.stderr.on('data', function(chunk) {stderr += chunk;}); | |
child.on('error', function(err) {if (callback) callback(err);}); | |
child.on('exit', function(code, signal) { | |
if (code === 0) { | |
if (callback) callback(null, stdout); | |
} else { | |
if (callback) callback(new Error(stderr)); | |
} | |
}); | |
return child; | |
}; | |
// Spawns and returns a child process that runs `wmiir create`. | |
// The given data is sent to this process's stdin. | |
// The callback takes one parameter: (err). | |
// - err is any error that occurred, or null if no error occurred. | |
exports.create = function(path, data, callback) { | |
var child = spawn('wmiir', ['create', path]); | |
var stderr=""; | |
child.stderr.on('data', function(chunk) {stderr += chunk;}); | |
child.on('error', function(err) {if (callback) callback(err);}); | |
child.on('exit', function(code, signal) { | |
if (code === 0) { | |
if (callback) callback(null); | |
} else { | |
if (callback) callback(new Error(stderr)); | |
} | |
}); | |
child.stdin.end(data); | |
return child; | |
}; | |
// Spawns and returns a child process that runs `wmiir remove`. | |
// The callback takes one parameter: (err). | |
// - err is any error that occurred, or null if no error occurred. | |
exports.remove = function(path, callback) { | |
var child = spawn('wmiir', ['remove', path]); | |
var stderr=""; | |
child.stderr.on('data', function(chunk) {stderr += chunk;}); | |
child.on('error', function(err) {if (callback) callback(err);}); | |
child.on('exit', function(code, signal) { | |
if (code === 0) { | |
if (callback) callback(null); | |
} else { | |
if (callback) callback(new Error(stderr)); | |
} | |
}); | |
return child; | |
}; | |
// Uses `wmiir setsid` to spawn a process that is not connected to the running | |
// wmii instance (in other words, it does not die when wmii is killed). Does | |
// not take a callback or return a handle to this process. | |
exports.setsid = function(/* varargs */) { | |
var args = Array.prototype.slice.call(arguments); | |
spawn('wmiir', ['setsid', '-f'].concat(args), {env: process.env}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment