121 lines
3.5 KiB
JavaScript
121 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 } );
|
||
},
|
||
};
|