1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
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 } );
},
};
|