122 lines
3.5 KiB
JavaScript
122 lines
3.5 KiB
JavaScript
|
var Zmodem = require('./zmodem');
|
|||
|
|
|||
|
module.exports = {
|
|||
|
/**
|
|||
|
* Return an array with the given number of random octet values.
|
|||
|
*
|
|||
|
* @param {Array} count - The number of octet values to return.
|
|||
|
*
|
|||
|
* @returns {Array} The octet values.
|
|||
|
*/
|
|||
|
get_random_octets(count) {
|
|||
|
if (!(count > 0)) throw( "Must be positive, not " + count );
|
|||
|
|
|||
|
var octets = [];
|
|||
|
|
|||
|
//This assigns backwards both for convenience and so that
|
|||
|
//the initial assignment allocates the needed size.
|
|||
|
while (count) {
|
|||
|
octets[count - 1] = Math.floor( Math.random() * 256 );
|
|||
|
count--;
|
|||
|
}
|
|||
|
|
|||
|
return octets;
|
|||
|
},
|
|||
|
|
|||
|
//This is meant NOT to do UTF-8 stuff since it handles \xXX.
|
|||
|
string_to_octets(string) {
|
|||
|
return string.split("").map( (c) => c.charCodeAt(0) );
|
|||
|
},
|
|||
|
|
|||
|
make_temp_dir() {
|
|||
|
return require('tmp').dirSync().name;
|
|||
|
},
|
|||
|
|
|||
|
make_temp_file(size) {
|
|||
|
const fs = require('fs');
|
|||
|
const tmp = require('tmp');
|
|||
|
|
|||
|
var tmpobj = tmp.fileSync();
|
|||
|
var content = Array(size).fill("x").join("");
|
|||
|
fs.writeSync( tmpobj.fd, content );
|
|||
|
fs.writeSync( tmpobj.fd, "=THE_END" );
|
|||
|
fs.closeSync( tmpobj.fd );
|
|||
|
|
|||
|
return tmpobj.name;
|
|||
|
},
|
|||
|
|
|||
|
make_empty_temp_file() {
|
|||
|
const fs = require('fs');
|
|||
|
const tmp = require('tmp');
|
|||
|
|
|||
|
var tmpobj = tmp.fileSync();
|
|||
|
fs.closeSync( tmpobj.fd );
|
|||
|
|
|||
|
return tmpobj.name;
|
|||
|
},
|
|||
|
|
|||
|
exec_lrzsz_steps(t, binpath, z_args, steps) {
|
|||
|
const spawn = require('child_process').spawn;
|
|||
|
|
|||
|
var child;
|
|||
|
|
|||
|
var zsession;
|
|||
|
var zsentry = new Zmodem.Sentry( {
|
|||
|
to_terminal: Object,
|
|||
|
on_detect: (d) => { zsession = d.confirm() },
|
|||
|
on_retract: console.error.bind(console),
|
|||
|
sender: (d) => {
|
|||
|
child.stdin.write( new Buffer(d) );
|
|||
|
},
|
|||
|
} );
|
|||
|
|
|||
|
var step = 0;
|
|||
|
var inputs = [];
|
|||
|
|
|||
|
child = spawn(binpath, z_args);
|
|||
|
console.log("child PID:", child.pid);
|
|||
|
|
|||
|
child.on("error", console.error.bind(console));
|
|||
|
|
|||
|
child.stdin.on("close", () => console.log(`# PID ${child.pid} STDIN closed`));
|
|||
|
child.stdout.on("close", () => console.log(`# PID ${child.pid} STDOUT closed`));
|
|||
|
child.stderr.on("close", () => console.log(`# PID ${child.pid} STDERR closed`));
|
|||
|
|
|||
|
//We can’t just pipe this on through because there can be lone CR
|
|||
|
//bytes which screw up TAP::Harness.
|
|||
|
child.stderr.on("data", (d) => {
|
|||
|
d = d.toString().replace(/\r\n?/g, "\n");
|
|||
|
if (d.substr(-1) !== "\n") d += "\n";
|
|||
|
process.stderr.write(`STDERR: ${d}`);
|
|||
|
});
|
|||
|
|
|||
|
child.stdout.on("data", (d) => {
|
|||
|
//console.log(`STDOUT from PID ${child.pid}`, d);
|
|||
|
inputs.push( Array.from(d) );
|
|||
|
|
|||
|
zsentry.consume( Array.from(d) );
|
|||
|
|
|||
|
if (zsession) {
|
|||
|
if ( steps[step] ) {
|
|||
|
if ( steps[step](zsession, child) ) {
|
|||
|
step++;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
console.log(`End of task list; closing PID ${child.pid}’s STDIN`);
|
|||
|
child.stdin.end();
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
var exit_promise = new Promise( (res, rej) => {
|
|||
|
child.on("exit", (code, signal) => {
|
|||
|
console.log(`# "${binpath}" exit: code ${code}, signal ${signal}`);
|
|||
|
res([code, signal]);
|
|||
|
} );
|
|||
|
} );
|
|||
|
|
|||
|
return exit_promise.then( () => { return inputs } );
|
|||
|
},
|
|||
|
};
|