aboutsummaryrefslogtreecommitdiff
path: root/modules/ext/shell.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-09-29 15:56:27 +0200
committerAgando <roduccomm@gmail.com>2026-09-29 15:56:27 +0200
commitdde918a235ff8eac41f6d205e954dc4a4daa5b01 (patch)
treea58da7664e938d6d4d0fca0974932139e8b8584c /modules/ext/shell.js
parent0e454aecf55d862b7618ebd1c98ca9fd71a15817 (diff)
newOS4 v4.6.15: reentrant print-capture stack, AI tail -f block, read-only sed in safeRead, security test harness (21 checks)
Diffstat (limited to 'modules/ext/shell.js')
-rw-r--r--modules/ext/shell.js20
1 files changed, 11 insertions, 9 deletions
diff --git a/modules/ext/shell.js b/modules/ext/shell.js
index 80bc841..9966e0f 100644
--- a/modules/ext/shell.js
+++ b/modules/ext/shell.js
@@ -366,9 +366,8 @@ class ShellModule {
}
// > or >> — capture output, write to file
- const originalPrint = this.terminal.print.bind(this.terminal);
let output = '';
- this.terminal.print = (text, type) => { output += text + '\n'; };
+ this.terminal._pushPrintCapture(buf => { output += buf; });
let cmdOk = true;
try {
@@ -386,13 +385,12 @@ class ShellModule {
fs.writeFile('__pipebuf__', pipeInput);
}
if (i < pipeParts.length - 1) {
- const captPrint = this.terminal.print.bind(this.terminal);
let capt = '';
- this.terminal.print = (t, ty) => { capt += t + '\n'; };
+ this.terminal._pushPrintCapture(buf => { capt += buf; });
try {
await this.terminal.dispatchCommand(pCmd, pArgs);
} finally {
- this.terminal.print = captPrint;
+ this.terminal._popPrintCapture();
}
pipeInput = capt.trim();
} else {
@@ -410,14 +408,18 @@ class ShellModule {
}
} catch(e) {
cmdOk = false;
- // Restore print before showing the error
- this.terminal.print = originalPrint;
+ // Pop capture before showing the error
+ this.terminal._popPrintCapture();
this.terminal.print('Error: ' + e.message, 'error');
redirectInfo.exitOk = false;
return;
} finally {
- // Always restore print — critical: without this, terminal is permanently broken
- this.terminal.print = originalPrint;
+ // Always pop capture — critical: without this, terminal output stays captured
+ // (empty stack = normal DOM printing, so pop is idempotent-safe when already popped)
+ if (this.terminal._printCaptureStack && this.terminal._printCaptureStack.length > 0) {
+ // popped in catch path for error case; success path pops here
+ this.terminal._popPrintCapture();
+ }
}
const captured = output.trimEnd();