@poe-platform/safe-bash 0.1.157 → 0.1.158
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/safe-bash/browser.js +274 -228
- package/dist/safe-bash/browser.js.map +4 -4
- package/dist/safe-bash/commands/apply-patch/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/apply-patch/shared.js +4 -2
- package/dist/safe-bash/commands/apply-patch/shared.js.map +1 -1
- package/dist/safe-bash/commands/archive/create.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/create.js +2 -1
- package/dist/safe-bash/commands/archive/create.js.map +1 -1
- package/dist/safe-bash/commands/archive/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/index.js +2 -1
- package/dist/safe-bash/commands/archive/index.js.map +1 -1
- package/dist/safe-bash/commands/basic.d.ts.map +1 -1
- package/dist/safe-bash/commands/basic.js +5 -4
- package/dist/safe-bash/commands/basic.js.map +1 -1
- package/dist/safe-bash/commands/column/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/column/internal.js +2 -1
- package/dist/safe-bash/commands/column/internal.js.map +1 -1
- package/dist/safe-bash/commands/diff-patch/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/diff-patch/shared.js +3 -2
- package/dist/safe-bash/commands/diff-patch/shared.js.map +1 -1
- package/dist/safe-bash/commands/du/budget.d.ts.map +1 -1
- package/dist/safe-bash/commands/du/budget.js +2 -1
- package/dist/safe-bash/commands/du/budget.js.map +1 -1
- package/dist/safe-bash/commands/execution.d.ts.map +1 -1
- package/dist/safe-bash/commands/execution.js +4 -3
- package/dist/safe-bash/commands/execution.js.map +1 -1
- package/dist/safe-bash/commands/expr/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/expr/index.js +5 -3
- package/dist/safe-bash/commands/expr/index.js.map +1 -1
- package/dist/safe-bash/commands/filesystem.d.ts.map +1 -1
- package/dist/safe-bash/commands/filesystem.js +10 -9
- package/dist/safe-bash/commands/filesystem.js.map +1 -1
- package/dist/safe-bash/commands/find.d.ts.map +1 -1
- package/dist/safe-bash/commands/find.js +3 -2
- package/dist/safe-bash/commands/find.js.map +1 -1
- package/dist/safe-bash/commands/html-to-markdown/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/html-to-markdown/index.js +2 -1
- package/dist/safe-bash/commands/html-to-markdown/index.js.map +1 -1
- package/dist/safe-bash/commands/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/internal.js +2 -1
- package/dist/safe-bash/commands/internal.js.map +1 -1
- package/dist/safe-bash/commands/network/shared.js +2 -2
- package/dist/safe-bash/commands/network/shared.js.map +1 -1
- package/dist/safe-bash/commands/node/host.d.ts.map +1 -1
- package/dist/safe-bash/commands/node/host.js +4 -2
- package/dist/safe-bash/commands/node/host.js.map +1 -1
- package/dist/safe-bash/commands/safejs/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/safejs/index.js +2 -1
- package/dist/safe-bash/commands/safejs/index.js.map +1 -1
- package/dist/safe-bash/commands/search/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/search/shared.js +2 -1
- package/dist/safe-bash/commands/search/shared.js.map +1 -1
- package/dist/safe-bash/commands/split/split.d.ts.map +1 -1
- package/dist/safe-bash/commands/split/split.js +3 -2
- package/dist/safe-bash/commands/split/split.js.map +1 -1
- package/dist/safe-bash/commands/structured/jq.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/jq.js +5 -4
- package/dist/safe-bash/commands/structured/jq.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/shared.js +2 -1
- package/dist/safe-bash/commands/text-programs/shared.js.map +1 -1
- package/dist/safe-bash/commands/time-env/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/time-env/shared.js +2 -1
- package/dist/safe-bash/commands/time-env/shared.js.map +1 -1
- package/dist/safe-bash/commands/tree/io.d.ts.map +1 -1
- package/dist/safe-bash/commands/tree/io.js +2 -8
- package/dist/safe-bash/commands/tree/io.js.map +1 -1
- package/dist/safe-bash/commands/which/which.d.ts.map +1 -1
- package/dist/safe-bash/commands/which/which.js +3 -1
- package/dist/safe-bash/commands/which/which.js.map +1 -1
- package/dist/safe-bash/escaping.d.ts +4 -0
- package/dist/safe-bash/escaping.d.ts.map +1 -0
- package/dist/safe-bash/escaping.js +47 -0
- package/dist/safe-bash/escaping.js.map +1 -0
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +58 -57
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/dist/safe-bash/shell/shell.d.ts.map +1 -1
- package/dist/safe-bash/shell/shell.js +7 -6
- package/dist/safe-bash/shell/shell.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { writeDiagnostic } from "../escaping.js";
|
|
1
2
|
import { cancelTurn, monotonicNow, registerYieldCheckpoint, scheduleTurn, yieldTurn } from "../contracts/yield.js";
|
|
2
3
|
import { ACCESS_MODES, FsError, composeMiddleware, createBytePipe, pipeBytes, resolvePath, toByteSource, validateExitCode, writeText, } from "../contracts/index.js";
|
|
3
4
|
import { concatShellValues, shellValueByteLength, shellValueBytes, shellValueFromBytes, shellValueText } from "../contracts/value.js";
|
|
@@ -1283,7 +1284,7 @@ export class Runtime {
|
|
|
1283
1284
|
this.outcomeFrame.report = undefined;
|
|
1284
1285
|
}
|
|
1285
1286
|
diagnostic(io, text) {
|
|
1286
|
-
return
|
|
1287
|
+
return writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${io.diagnosticLine ?? 1}: ${text}\n`);
|
|
1287
1288
|
}
|
|
1288
1289
|
writeVariable(state, name, value, origin = "assignment") {
|
|
1289
1290
|
if (arrayStore(state)?.get(name))
|
|
@@ -2227,7 +2228,7 @@ export class Runtime {
|
|
|
2227
2228
|
throw error;
|
|
2228
2229
|
this.clearOutcomeReport();
|
|
2229
2230
|
if (error instanceof HereDocumentSyntaxError) {
|
|
2230
|
-
await
|
|
2231
|
+
await writeDiagnostic(io.stderr, error.diagnostic);
|
|
2231
2232
|
if (command.kind !== "simple" && command.kind !== "subshell" && command.kind !== "arithmetic" && command.kind !== "conditional")
|
|
2232
2233
|
this.errexit(1, state, io);
|
|
2233
2234
|
return 1;
|
|
@@ -2241,7 +2242,7 @@ export class Runtime {
|
|
|
2241
2242
|
if (error instanceof NounsetFailure || error instanceof ParameterExpansionFailure) {
|
|
2242
2243
|
const detail = error instanceof ParameterExpansionFailure ? diagnostic ?? message(error) : message(error);
|
|
2243
2244
|
try {
|
|
2244
|
-
await
|
|
2245
|
+
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${detail}\n`);
|
|
2245
2246
|
}
|
|
2246
2247
|
catch (reason) {
|
|
2247
2248
|
this.signal.throwIfAborted();
|
|
@@ -2253,10 +2254,10 @@ export class Runtime {
|
|
|
2253
2254
|
throw completedExit(error instanceof ParameterExpansionFailure && !state.isolated ? 127 : 1);
|
|
2254
2255
|
}
|
|
2255
2256
|
if (error instanceof ArrayFailure)
|
|
2256
|
-
await
|
|
2257
|
+
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic ?? message(error)}\n`);
|
|
2257
2258
|
else {
|
|
2258
2259
|
try {
|
|
2259
|
-
await
|
|
2260
|
+
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic ?? message(error)}\n`);
|
|
2260
2261
|
}
|
|
2261
2262
|
catch {
|
|
2262
2263
|
this.signal.throwIfAborted();
|
|
@@ -2312,7 +2313,7 @@ export class Runtime {
|
|
|
2312
2313
|
for (const word of hereDocumentWords(document, line, byteLocale(state.variables), warnings, this.budget.parsing)) {
|
|
2313
2314
|
this.signal.throwIfAborted();
|
|
2314
2315
|
for (const warning of warnings.splice(0))
|
|
2315
|
-
await
|
|
2316
|
+
await writeDiagnostic(io.stderr, `shell: warning: ${warning}\n`);
|
|
2316
2317
|
if (++words % 128 === 0)
|
|
2317
2318
|
await yieldTurn(this.signal);
|
|
2318
2319
|
const part = (await this.word(word, state, io, false)).join("");
|
|
@@ -2324,7 +2325,7 @@ export class Runtime {
|
|
|
2324
2325
|
}
|
|
2325
2326
|
finally {
|
|
2326
2327
|
for (const warning of warnings.splice(0))
|
|
2327
|
-
await
|
|
2328
|
+
await writeDiagnostic(io.stderr, `shell: warning: ${warning}\n`);
|
|
2328
2329
|
}
|
|
2329
2330
|
return value;
|
|
2330
2331
|
}
|
|
@@ -3124,10 +3125,10 @@ export class Runtime {
|
|
|
3124
3125
|
else {
|
|
3125
3126
|
if (command && flag !== "p") {
|
|
3126
3127
|
await this.diagnostic({ ...io, ...context }, `command: -${flag}: invalid option`);
|
|
3127
|
-
await
|
|
3128
|
+
await writeDiagnostic(context.stderr, "command: usage: command [-pVv] command [arg ...]\n");
|
|
3128
3129
|
}
|
|
3129
3130
|
else
|
|
3130
|
-
await
|
|
3131
|
+
await writeDiagnostic(context.stderr, `${context.command}: ${option}: unsupported option\n`);
|
|
3131
3132
|
return 2;
|
|
3132
3133
|
}
|
|
3133
3134
|
}
|
|
@@ -3181,7 +3182,7 @@ export class Runtime {
|
|
|
3181
3182
|
}
|
|
3182
3183
|
if (!matches.length) {
|
|
3183
3184
|
if (mode === "describe")
|
|
3184
|
-
await
|
|
3185
|
+
await writeDiagnostic(context.stderr, `${io.scriptName ?? "shell"}: line ${io.diagnosticLine ?? 1}: ${context.command}: ${name}: not found\n`);
|
|
3185
3186
|
continue;
|
|
3186
3187
|
}
|
|
3187
3188
|
found++;
|
|
@@ -3283,7 +3284,7 @@ export class Runtime {
|
|
|
3283
3284
|
}
|
|
3284
3285
|
const flags = option.slice(1);
|
|
3285
3286
|
if (!flags.length || [...flags].some(flag => !(option[0] === "-" ? "cseB" : "eB").includes(flag))) {
|
|
3286
|
-
await
|
|
3287
|
+
await writeDiagnostic(context.stderr, `${context.command}: ${option}: unsupported option; supported flags are -c, -s, -e, +e, -B, +B and +/-o braceexpand\n`);
|
|
3287
3288
|
return 2;
|
|
3288
3289
|
}
|
|
3289
3290
|
commandString ||= option.includes("c");
|
|
@@ -3297,7 +3298,7 @@ export class Runtime {
|
|
|
3297
3298
|
return this.scriptFile(context, state, io, args[0], args.slice(1), false, errexit, loadedSource, braceexpand);
|
|
3298
3299
|
const source = commandString ? args.shift() : undefined;
|
|
3299
3300
|
if (commandString && source === undefined) {
|
|
3300
|
-
await
|
|
3301
|
+
await writeDiagnostic(context.stderr, `${context.command}: -c: option requires an argument\n`);
|
|
3301
3302
|
return 2;
|
|
3302
3303
|
}
|
|
3303
3304
|
const arg0 = commandString ? args.shift() ?? context.command : context.command;
|
|
@@ -3317,14 +3318,14 @@ export class Runtime {
|
|
|
3317
3318
|
const line = source.slice(0, error.offset).split("\n").length;
|
|
3318
3319
|
const prefix = `${io.scriptName ?? "shell"}:${commandString ? " -c:" : ""}`;
|
|
3319
3320
|
if (error.unclosedQuote)
|
|
3320
|
-
await
|
|
3321
|
+
await writeDiagnostic(io.stderr, `${prefix} line ${offset + error.unclosedQuote.line}: unexpected EOF while looking for matching \`${error.unclosedQuote.quote}'\n`);
|
|
3321
3322
|
else if (error.offset >= source.length && !/Unterminated|nesting|Unsupported/u.test(error.reason)) {
|
|
3322
3323
|
const context = error.incompleteCommand ? ` from \`${error.incompleteCommand.name}' command on line ${offset + error.incompleteCommand.line}` : "";
|
|
3323
|
-
await
|
|
3324
|
+
await writeDiagnostic(io.stderr, `${prefix} line ${offset + source.split("\n").length + Number(!source.endsWith("\n"))}: syntax error: unexpected end of file${context}\n`);
|
|
3324
3325
|
}
|
|
3325
3326
|
else {
|
|
3326
3327
|
const token = /^[;&|()<>]|^[^\s;&|()<>]+/u.exec(source.slice(error.offset))?.[0] ?? "newline";
|
|
3327
|
-
await
|
|
3328
|
+
await writeDiagnostic(io.stderr, `${prefix} line ${offset + line}: syntax error near unexpected token \`${token}'\n${prefix} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'\n`);
|
|
3328
3329
|
}
|
|
3329
3330
|
return error.exitCode;
|
|
3330
3331
|
}
|
|
@@ -3337,7 +3338,7 @@ export class Runtime {
|
|
|
3337
3338
|
this.signal.throwIfAborted();
|
|
3338
3339
|
const unit = parseShellUnit(source, position, byteLocale(state.variables), this.budget.parsing, lineIndex);
|
|
3339
3340
|
for (const warning of unit.script.warnings ?? [])
|
|
3340
|
-
await
|
|
3341
|
+
await writeDiagnostic(io.stderr, `${io.scriptName}: warning: ${warning}\n`);
|
|
3341
3342
|
if (unit.script.lists.length) {
|
|
3342
3343
|
const result = await this.runUnit(unit.script, state, io);
|
|
3343
3344
|
status = result.exitCode;
|
|
@@ -3385,7 +3386,7 @@ export class Runtime {
|
|
|
3385
3386
|
const unit = eof ? parseShellUnit(source, 0, byteLocale(state.variables), this.budget.parsing, lineIndex) : parseShellInputUnit(source, byteLocale(state.variables), this.budget.parsing, lineIndex);
|
|
3386
3387
|
if (unit) {
|
|
3387
3388
|
for (const warning of unit.script.warnings ?? [])
|
|
3388
|
-
await
|
|
3389
|
+
await writeDiagnostic(io.stderr, `${io.scriptName}: warning: ${warning}\n`);
|
|
3389
3390
|
if (unit.script.lists.length) {
|
|
3390
3391
|
const result = await this.runUnit(unit.script, state, unitIO);
|
|
3391
3392
|
status = result.exitCode;
|
|
@@ -3555,7 +3556,7 @@ export class Runtime {
|
|
|
3555
3556
|
return { exitCode: await runtime.scriptFile(forwarded, state, childIO, command, forwarded.args, true) };
|
|
3556
3557
|
if (definition)
|
|
3557
3558
|
return definition.execute(forwarded);
|
|
3558
|
-
await
|
|
3559
|
+
await writeDiagnostic(forwarded.stderr, `env: ${command}: command not found\n`);
|
|
3559
3560
|
return { exitCode: 127 };
|
|
3560
3561
|
}, undefined, options.stdin !== context.stdin ? options.stdin : undefined, scope);
|
|
3561
3562
|
return { exitCode };
|
|
@@ -3660,7 +3661,7 @@ export class Runtime {
|
|
|
3660
3661
|
if (!(error instanceof ShellSyntaxError))
|
|
3661
3662
|
throw error;
|
|
3662
3663
|
const line = source.slice(0, error.offset).split("\n").length;
|
|
3663
|
-
await
|
|
3664
|
+
await writeDiagnostic(context.stderr, `${target}: line ${line}: syntax error: ${error.reason}\n`);
|
|
3664
3665
|
return error.exitCode;
|
|
3665
3666
|
}
|
|
3666
3667
|
const child = this.processState(context, state, target, args);
|
|
@@ -3672,7 +3673,7 @@ export class Runtime {
|
|
|
3672
3673
|
let status = 0;
|
|
3673
3674
|
for (const unit of units) {
|
|
3674
3675
|
for (const warning of unit.warnings ?? [])
|
|
3675
|
-
await
|
|
3676
|
+
await writeDiagnostic(context.stderr, `${target}: warning: ${warning}\n`);
|
|
3676
3677
|
if (!unit.lists.length)
|
|
3677
3678
|
continue;
|
|
3678
3679
|
const result = await this.runUnit(unit, child, childIO);
|
|
@@ -3692,7 +3693,7 @@ export class Runtime {
|
|
|
3692
3693
|
this.signal.throwIfAborted();
|
|
3693
3694
|
const unit = parseShellUnit(source, position, byteLocale(state.variables), this.budget.parsing, lineIndex);
|
|
3694
3695
|
for (const warning of unit.script.warnings ?? [])
|
|
3695
|
-
await
|
|
3696
|
+
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: warning: ${warning}\n`);
|
|
3696
3697
|
if (unit.script.lists.length) {
|
|
3697
3698
|
status = await this.script(unit.script, state, io);
|
|
3698
3699
|
executed = true;
|
|
@@ -3716,7 +3717,7 @@ export class Runtime {
|
|
|
3716
3717
|
args.shift();
|
|
3717
3718
|
else if (args[0]?.startsWith("-") && args[0] !== "-") {
|
|
3718
3719
|
await this.diagnostic(io, `eval: -${args[0][1]}: invalid option`);
|
|
3719
|
-
await
|
|
3720
|
+
await writeDiagnostic(io.stderr, "eval: usage: eval [arg ...]\n");
|
|
3720
3721
|
if (special)
|
|
3721
3722
|
throw new Flow("exit", 2);
|
|
3722
3723
|
return 2;
|
|
@@ -3760,7 +3761,7 @@ export class Runtime {
|
|
|
3760
3761
|
const filename = args.shift();
|
|
3761
3762
|
if (filename === undefined) {
|
|
3762
3763
|
await this.diagnostic(io, `${context.command}: filename argument required`);
|
|
3763
|
-
await
|
|
3764
|
+
await writeDiagnostic(io.stderr, `${context.command}: usage: ${context.command} [-p path] filename [arguments]\n`);
|
|
3764
3765
|
if (special)
|
|
3765
3766
|
throw new Flow("exit", 2);
|
|
3766
3767
|
return 2;
|
|
@@ -4011,7 +4012,7 @@ export class Runtime {
|
|
|
4011
4012
|
valid = false;
|
|
4012
4013
|
}
|
|
4013
4014
|
if (!valid) {
|
|
4014
|
-
await
|
|
4015
|
+
await writeDiagnostic(stderr, "set: unsupported shell option; supported forms are +/- e/u/B clusters, -- arguments and terminal o with braceexpand, pipefail, errexit or nounset\n");
|
|
4015
4016
|
return 1;
|
|
4016
4017
|
}
|
|
4017
4018
|
index++;
|
|
@@ -4106,11 +4107,11 @@ export class Runtime {
|
|
|
4106
4107
|
const offset = context.args[0] === "--" ? 1 : 0;
|
|
4107
4108
|
if (!offset && context.args[0]?.startsWith("-") && context.args[0] !== "-") {
|
|
4108
4109
|
await this.diagnostic(context, `getopts: -${context.args[0][1]}: invalid option`);
|
|
4109
|
-
await
|
|
4110
|
+
await writeDiagnostic(context.stderr, "getopts: usage: getopts optstring name [arg ...]\n");
|
|
4110
4111
|
return 2;
|
|
4111
4112
|
}
|
|
4112
4113
|
if (context.args.length - offset < 2) {
|
|
4113
|
-
await
|
|
4114
|
+
await writeDiagnostic(context.stderr, "getopts: usage: getopts optstring name [arg ...]\n");
|
|
4114
4115
|
return 2;
|
|
4115
4116
|
}
|
|
4116
4117
|
const optstring = context.args[offset];
|
|
@@ -4144,7 +4145,7 @@ export class Runtime {
|
|
|
4144
4145
|
state.getopts.cursor = result.state;
|
|
4145
4146
|
if (result.diagnostic) {
|
|
4146
4147
|
const explanation = result.diagnostic.kind === "unknown-option" ? "illegal option" : "option requires an argument";
|
|
4147
|
-
await
|
|
4148
|
+
await writeDiagnostic(context.stderr, `${state.arg0 ?? context.scriptName ?? "shell"}: ${explanation} -- ${result.diagnostic.option}\n`);
|
|
4148
4149
|
}
|
|
4149
4150
|
this.signal.throwIfAborted();
|
|
4150
4151
|
this.writeVariable(state, "OPTIND", String(result.optind), "getopts");
|
|
@@ -4161,12 +4162,12 @@ export class Runtime {
|
|
|
4161
4162
|
const name = stackHooks?.name ?? "cd";
|
|
4162
4163
|
this.signal.throwIfAborted();
|
|
4163
4164
|
if (args.length > 1) {
|
|
4164
|
-
await
|
|
4165
|
+
await writeDiagnostic(context.stderr, `${name}: too many arguments\n`);
|
|
4165
4166
|
return 1;
|
|
4166
4167
|
}
|
|
4167
4168
|
const target = args[0] === "-" ? state.variables.OLDPWD : (args[0] ?? state.variables.HOME);
|
|
4168
4169
|
if (target === undefined) {
|
|
4169
|
-
await
|
|
4170
|
+
await writeDiagnostic(context.stderr, `${name}: ${args[0] === "-" ? "OLDPWD" : "HOME"} not set\n`);
|
|
4170
4171
|
return 1;
|
|
4171
4172
|
}
|
|
4172
4173
|
let selected;
|
|
@@ -4387,7 +4388,7 @@ export class Runtime {
|
|
|
4387
4388
|
unset = true;
|
|
4388
4389
|
else {
|
|
4389
4390
|
await this.diagnostic(context, `shopt: ${option.startsWith("--") ? option : `-${flag}`}: unsupported option`);
|
|
4390
|
-
await
|
|
4391
|
+
await writeDiagnostic(context.stderr, "shopt: usage: shopt [-pqsu] [--] [dotglob ...]\n");
|
|
4391
4392
|
return 2;
|
|
4392
4393
|
}
|
|
4393
4394
|
}
|
|
@@ -4432,19 +4433,19 @@ export class Runtime {
|
|
|
4432
4433
|
const option = incoming.args[offset++];
|
|
4433
4434
|
const target = option.slice(2) || incoming.args[offset++];
|
|
4434
4435
|
if (target === undefined) {
|
|
4435
|
-
await
|
|
4436
|
+
await writeDiagnostic(context.stderr, "printf: -v: option requires an argument\n");
|
|
4436
4437
|
return 2;
|
|
4437
4438
|
}
|
|
4438
4439
|
const bracket = target.indexOf("[");
|
|
4439
4440
|
name = bracket < 0 ? target : target.slice(0, bracket);
|
|
4440
4441
|
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name) || bracket >= 0 && !target.endsWith("]")) {
|
|
4441
|
-
await
|
|
4442
|
+
await writeDiagnostic(context.stderr, `printf: '${target}': not a valid identifier\n`);
|
|
4442
4443
|
return 2;
|
|
4443
4444
|
}
|
|
4444
4445
|
index = undefined;
|
|
4445
4446
|
if (bracket >= 0) {
|
|
4446
4447
|
if (target[bracket + 1] === "'" || target[bracket + 1] === '"') {
|
|
4447
|
-
await
|
|
4448
|
+
await writeDiagnostic(context.stderr, `printf: '${target}': unsupported indexed-array subscript\n`);
|
|
4448
4449
|
return 2;
|
|
4449
4450
|
}
|
|
4450
4451
|
try {
|
|
@@ -4454,11 +4455,11 @@ export class Runtime {
|
|
|
4454
4455
|
this.signal.throwIfAborted();
|
|
4455
4456
|
if (!(error instanceof ShellSyntaxError))
|
|
4456
4457
|
throw error;
|
|
4457
|
-
await
|
|
4458
|
+
await writeDiagnostic(context.stderr, `printf: '${target}': unsupported indexed-array subscript\n`);
|
|
4458
4459
|
return 2;
|
|
4459
4460
|
}
|
|
4460
4461
|
if (numericIndex(index) === undefined) {
|
|
4461
|
-
await
|
|
4462
|
+
await writeDiagnostic(context.stderr, "printf: index outside 0..2147483647\n");
|
|
4462
4463
|
return 2;
|
|
4463
4464
|
}
|
|
4464
4465
|
}
|
|
@@ -4466,7 +4467,7 @@ export class Runtime {
|
|
|
4466
4467
|
const arguments_ = incoming.slice(offset);
|
|
4467
4468
|
const format = arguments_.args[0] === "--" ? arguments_.args[1] : arguments_.args[0];
|
|
4468
4469
|
if (format === undefined || arguments_.args[0] !== "--" && format.startsWith("-")) {
|
|
4469
|
-
await
|
|
4470
|
+
await writeDiagnostic(context.stderr, "printf: usage: printf [-v var] format [arguments]\n");
|
|
4470
4471
|
return 2;
|
|
4471
4472
|
}
|
|
4472
4473
|
const allocation = this.budget.values.scope();
|
|
@@ -4496,13 +4497,13 @@ export class Runtime {
|
|
|
4496
4497
|
this.signal.throwIfAborted();
|
|
4497
4498
|
if (!(error instanceof UsageError))
|
|
4498
4499
|
throw error;
|
|
4499
|
-
await
|
|
4500
|
+
await writeDiagnostic(context.stderr, `printf: ${error.message}\n`);
|
|
4500
4501
|
status = 1;
|
|
4501
4502
|
}
|
|
4502
4503
|
const value = concatShellValues(chunks, allocation);
|
|
4503
4504
|
this.signal.throwIfAborted();
|
|
4504
4505
|
if (state.readonlyVariables?.has(name)) {
|
|
4505
|
-
await
|
|
4506
|
+
await writeDiagnostic(context.stderr, `printf: ${name}: readonly variable\n`);
|
|
4506
4507
|
return 1;
|
|
4507
4508
|
}
|
|
4508
4509
|
if (index || arrayStore(state)?.get(name)) {
|
|
@@ -4525,7 +4526,7 @@ export class Runtime {
|
|
|
4525
4526
|
text = undefined;
|
|
4526
4527
|
}
|
|
4527
4528
|
if (text === undefined) {
|
|
4528
|
-
await
|
|
4529
|
+
await writeDiagnostic(context.stderr, "printf: indexed variables do not support non-UTF-8 bytes\n");
|
|
4529
4530
|
return 1;
|
|
4530
4531
|
}
|
|
4531
4532
|
if (index)
|
|
@@ -4564,7 +4565,7 @@ export class Runtime {
|
|
|
4564
4565
|
return this.directoryStackBuiltin(context, state, diagnose);
|
|
4565
4566
|
if (command === "pwd") {
|
|
4566
4567
|
if (args.some((arg) => arg !== "-L" && arg !== "-P")) {
|
|
4567
|
-
await
|
|
4568
|
+
await writeDiagnostic(stderr, "pwd: invalid option\n");
|
|
4568
4569
|
return 2;
|
|
4569
4570
|
}
|
|
4570
4571
|
const path = args.at(-1) === "-P" ? await this.fs.realpath(state.cwd, { signal: this.signal }) : state.cwd;
|
|
@@ -4607,7 +4608,7 @@ export class Runtime {
|
|
|
4607
4608
|
continue;
|
|
4608
4609
|
}
|
|
4609
4610
|
if (/^[+-]/u.test(option)) {
|
|
4610
|
-
await
|
|
4611
|
+
await writeDiagnostic(stderr, "set: unsupported shell option; supported forms are +/- e/u clusters, -- arguments and terminal o with pipefail, errexit or nounset\n");
|
|
4611
4612
|
if (state.profile === "sh" && suppressSpecial)
|
|
4612
4613
|
return 2;
|
|
4613
4614
|
throw new Flow("exit", 2);
|
|
@@ -4621,7 +4622,7 @@ export class Runtime {
|
|
|
4621
4622
|
}
|
|
4622
4623
|
if (args.length)
|
|
4623
4624
|
return 0;
|
|
4624
|
-
await
|
|
4625
|
+
await writeDiagnostic(stderr, "set: supported forms are +/- e/u clusters, -- arguments and terminal o with pipefail, errexit or nounset\n");
|
|
4625
4626
|
return 2;
|
|
4626
4627
|
}
|
|
4627
4628
|
if (command === "shift") {
|
|
@@ -4637,13 +4638,13 @@ export class Runtime {
|
|
|
4637
4638
|
if (command === "local") {
|
|
4638
4639
|
const options = localDeclarationOptions(declarationArgs, this.signal);
|
|
4639
4640
|
if (options.error !== undefined) {
|
|
4640
|
-
await
|
|
4641
|
+
await writeDiagnostic(stderr, `local: ${options.error}: unsupported option\n`);
|
|
4641
4642
|
return 2;
|
|
4642
4643
|
}
|
|
4643
4644
|
indexedLocal = options.indexed;
|
|
4644
4645
|
declarationArgs.splice(0, options.offset);
|
|
4645
4646
|
if (indexedLocal && declarationArgs.length === 0) {
|
|
4646
|
-
await
|
|
4647
|
+
await writeDiagnostic(stderr, "local: -a requires a variable name\n");
|
|
4647
4648
|
return 2;
|
|
4648
4649
|
}
|
|
4649
4650
|
}
|
|
@@ -4653,14 +4654,14 @@ export class Runtime {
|
|
|
4653
4654
|
if (option === "--")
|
|
4654
4655
|
break;
|
|
4655
4656
|
if (option !== "-p") {
|
|
4656
|
-
await
|
|
4657
|
+
await writeDiagnostic(stderr, `readonly: ${option}: unsupported option\n`);
|
|
4657
4658
|
return 2;
|
|
4658
4659
|
}
|
|
4659
4660
|
}
|
|
4660
4661
|
}
|
|
4661
4662
|
const locals = state.locals.at(-1);
|
|
4662
4663
|
if (command === "local" && !locals) {
|
|
4663
|
-
await
|
|
4664
|
+
await writeDiagnostic(stderr, "local: not in a function\n");
|
|
4664
4665
|
return 1;
|
|
4665
4666
|
}
|
|
4666
4667
|
let status = 0;
|
|
@@ -4942,7 +4943,7 @@ export class Runtime {
|
|
|
4942
4943
|
continue;
|
|
4943
4944
|
}
|
|
4944
4945
|
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name)) {
|
|
4945
|
-
await
|
|
4946
|
+
await writeDiagnostic(stderr, `unset: ${name}: not a valid identifier\n`);
|
|
4946
4947
|
status = 1;
|
|
4947
4948
|
continue;
|
|
4948
4949
|
}
|
|
@@ -4990,7 +4991,7 @@ export class Runtime {
|
|
|
4990
4991
|
delimiter = new TextEncoder().encode(value)[0] ?? 0;
|
|
4991
4992
|
else if (exact && (!/^[ \t]*[+-]?\d+[ \t]*$/u.test(value) || !Number.isSafeInteger(Number(value)) || Number(value) < 0)) {
|
|
4992
4993
|
const diagnosticIO = context;
|
|
4993
|
-
await
|
|
4994
|
+
await writeDiagnostic(stderr, `${diagnosticIO.scriptName ?? "shell"}: line ${diagnosticIO.diagnosticLine ?? 1}: read: ${value}: invalid ${/^[+-]?0[xX]/u.test(value) ? "hex " : ""}number\n`);
|
|
4994
4995
|
return 1;
|
|
4995
4996
|
}
|
|
4996
4997
|
else if (!exact && (!/^\d+$/u.test(value) || !Number.isSafeInteger(Number(value))))
|
|
@@ -5007,11 +5008,11 @@ export class Runtime {
|
|
|
5007
5008
|
const invalidName = names.find(name => !/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name));
|
|
5008
5009
|
if (exact && !invalid && invalidName !== undefined) {
|
|
5009
5010
|
const diagnosticIO = context;
|
|
5010
|
-
await
|
|
5011
|
+
await writeDiagnostic(stderr, `${diagnosticIO.scriptName ?? "shell"}: line ${diagnosticIO.diagnosticLine ?? 1}: read: \`${invalidName}': not a valid identifier\n`);
|
|
5011
5012
|
return 1;
|
|
5012
5013
|
}
|
|
5013
5014
|
if (invalid || names.some((name) => !/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name))) {
|
|
5014
|
-
await
|
|
5015
|
+
await writeDiagnostic(stderr, "read: invalid variable name or unsupported option\n");
|
|
5015
5016
|
return 2;
|
|
5016
5017
|
}
|
|
5017
5018
|
const input = context.stdin instanceof ShellInput ? context.stdin : new ShellInput(context.stdin, this.budget, this.signal);
|
|
@@ -5070,15 +5071,15 @@ export class Runtime {
|
|
|
5070
5071
|
}
|
|
5071
5072
|
if (command === "exit" || command === "return") {
|
|
5072
5073
|
if (command === "return" && state.functionDepth === 0 && !state.sourceDepth) {
|
|
5073
|
-
await
|
|
5074
|
+
await writeDiagnostic(stderr, "return: not in a function\n");
|
|
5074
5075
|
return 1;
|
|
5075
5076
|
}
|
|
5076
5077
|
if (args.length > 1) {
|
|
5077
|
-
await
|
|
5078
|
+
await writeDiagnostic(stderr, `${command}: too many arguments\n`);
|
|
5078
5079
|
return 1;
|
|
5079
5080
|
}
|
|
5080
5081
|
if (args[0] !== undefined && !/^[+-]?\d+$/u.test(args[0])) {
|
|
5081
|
-
await
|
|
5082
|
+
await writeDiagnostic(stderr, `${command}: ${args[0]}: numeric argument required\n`);
|
|
5082
5083
|
throw completedExit(2, command);
|
|
5083
5084
|
}
|
|
5084
5085
|
const status = args[0] === undefined ? state.status : Number((BigInt(args[0]) % 256n + 256n) % 256n);
|
|
@@ -5087,11 +5088,11 @@ export class Runtime {
|
|
|
5087
5088
|
if (command === "break" || command === "continue") {
|
|
5088
5089
|
const levels = args[0] === undefined ? 1 : Number(args[0]);
|
|
5089
5090
|
if (args.length > 1 || !Number.isSafeInteger(levels) || levels < 1) {
|
|
5090
|
-
await
|
|
5091
|
+
await writeDiagnostic(stderr, `${command}: invalid loop count\n`);
|
|
5091
5092
|
return 1;
|
|
5092
5093
|
}
|
|
5093
5094
|
if (!state.loopDepth) {
|
|
5094
|
-
await
|
|
5095
|
+
await writeDiagnostic(stderr, `${command}: only meaningful in a loop\n`);
|
|
5095
5096
|
return 0;
|
|
5096
5097
|
}
|
|
5097
5098
|
throw completedExit(0, command, Math.min(levels, state.loopDepth));
|
|
@@ -5145,7 +5146,7 @@ export class Runtime {
|
|
|
5145
5146
|
if (part.kind === "failed-substitution") {
|
|
5146
5147
|
if (state.depth >= this.budget.limits.maxSubstitutionDepth)
|
|
5147
5148
|
this.budget.fail("maxSubstitutionDepth");
|
|
5148
|
-
await
|
|
5149
|
+
await writeDiagnostic(io.stderr, part.diagnostic);
|
|
5149
5150
|
state.status = state.substitutionStatus = 2;
|
|
5150
5151
|
return "";
|
|
5151
5152
|
}
|
|
@@ -5200,7 +5201,7 @@ export class Runtime {
|
|
|
5200
5201
|
state.status = state.substitutionStatus;
|
|
5201
5202
|
const bytes = capture.bytes();
|
|
5202
5203
|
if (bytes.includes(0))
|
|
5203
|
-
await
|
|
5204
|
+
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${warningLine}: warning: command substitution: ignored null byte in input\n`);
|
|
5204
5205
|
let length = 0;
|
|
5205
5206
|
for (const byte of bytes)
|
|
5206
5207
|
if (byte !== 0)
|