@ai-ecoverse/slicc-kernel 1.54.9 → 1.55.0
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/README.md +3 -2
- package/dist/kernel-worker.js +146 -51
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node.js +146 -51
- package/dist/node.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ The user database, `/etc/passwd` and `/etc/group` (see [Users](#users)):
|
|
|
88
88
|
|
|
89
89
|
| | |
|
|
90
90
|
| --- | --- |
|
|
91
|
-
| `add({ name, home?, groups?, umask? })` | adds a user and resolves with `{ name, uid, gid, home, shell, groups, umask? }`. It's idempotent: an existing name resolves with its entry and changes nothing but the remembered `umask`. The new user gets the lowest free id from 1000 up, a private group of the same id and name, membership of `users` and of each group in `groups` (such as `sudo`), `home` (default `/home/<name>`, created), and `/bin/bash`. `umask` is the umask its processes start with; the kernel keeps it in memory, so pass it again after a reload. A name must match `[a-z_][a-z0-9_.-]*`; a group that doesn't exist rejects with `ENOENT` |
|
|
91
|
+
| `add({ name, home?, groups?, umask? })` | adds a user and resolves with `{ name, uid, gid, home, shell, groups, umask? }`. It's idempotent: an existing name resolves with its entry and changes nothing but the remembered `umask`. The new user gets the lowest free id from 1000 up, a private group of the same id and name, membership of `users` and of each group in `groups` (such as `sudo`), `home` (default `/home/<name>`, created), its pnpm home `~/.local/share/pnpm` (`0700`, `0750` for a `scoop-` user) and `~/.config/pnpm/config.yaml` with `minimumReleaseAge: 1440` (pnpm skips releases less than a day old), each only if missing, which an `add` of an existing user also does, and `/bin/bash`. `umask` is the umask its processes start with; the kernel keeps it in memory, so pass it again after a reload. A name must match `[a-z_][a-z0-9_.-]*`; a group that doesn't exist rejects with `ENOENT` |
|
|
92
92
|
| `remove(name, { keepHome }?)` | removes the user, its private group and its group memberships, and deletes its home unless `keepHome` is set. A home outside `/home/<dir>` is never deleted. Resolves `false` for an unknown name; system accounts (ids below 1000 or above 60000) reject with `EPERM` |
|
|
93
93
|
| `list()` | every user, as `add` returns them |
|
|
94
94
|
|
|
@@ -490,7 +490,8 @@ Lowering a soft resource limit (`ulimit -S -n 64`) still fails with `EPERM` in E
|
|
|
490
490
|
Every process has credentials in the kernel, as on Linux: real, effective and saved user and group ids, and supplementary groups. A process gets them from the user it was started as (`run`, `openTerminal`, a client's `spawn`, or the client's own user; root by default) and keeps its parent's across fork, spawn and exec. Setuid and setgid bits are never honoured on exec. Files aren't checked against the credentials yet; they decide who may signal whom, and what `/proc` and `ps` show.
|
|
491
491
|
|
|
492
492
|
- **The database:** `/etc/passwd` and `/etc/group` are real files. On first start the kernel writes them when they're missing, with `root` (uid 0, home `/root`, created `0700`) and `nobody` (65534), and the groups `root`, `sudo` (27), `users` (100) and `nogroup` (65534); files already there are kept as they are. The kernel reads them for every lookup, so an edit counts at once. [`kernel.users`](#kernelusers) adds and removes users.
|
|
493
|
-
- **Environment:** a process started as a user gets `HOME`, `USER`, `LOGNAME`, `PNPM_HOME` and `PATH`. A user's `PNPM_HOME` is `~/.local/share/pnpm`; root's
|
|
493
|
+
- **Environment:** a process started as a user gets `HOME`, `USER`, `LOGNAME`, `PNPM_HOME`, `NPM_CONFIG_PREFIX` and `PATH`. A user's `PNPM_HOME` is `~/.local/share/pnpm` and its npm prefix `~/.local`; root's are `/usr/local/share/pnpm` (or the embedder's `env.PNPM_HOME`) and `/usr/local`. `PATH` is `$PNPM_HOME/bin:/usr/local/bin:/usr/bin:/bin`.
|
|
494
|
+
- **Commands per user:** root's global packages (`pnpm add -g` as root) are commands every user finds in `/usr/bin`. A user's own global packages are commands for that user only: they show up in the user's `~/.local/share/pnpm/bin`, first on its `PATH`, and a program the user starts finds them by name before the system's; another user, root included, doesn't. A user's packages can map file suffixes (`binfmt`) for that user too. The kernel picks up an install, a removal and a new user as they happen.
|
|
494
495
|
- **Changing credentials:** POSIX `setresuid`/`setresgid` rules. Root (effective uid 0) may set any id and the group list; anyone else may only swap among their own real, effective and saved ids, and gets `EPERM` otherwise.
|
|
495
496
|
- **Signals:** a process may signal another if its effective uid is 0, or if its real or effective uid is the target's real or saved uid; otherwise `kill` fails with `EPERM`. A group kill signals the members it may, and fails with `EPERM` only when it may signal none.
|
|
496
497
|
- **Visibility:** a process that isn't root sees only processes whose real or effective uid is its effective uid, in `/proc` and in `ps`, like Linux's `hidepid=2`; so does a client bound to a user.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -661,7 +661,7 @@ var OpfsFs = class {
|
|
|
661
661
|
const parent = await this.locate(parentOf2(path), true);
|
|
662
662
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
663
663
|
await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
|
|
664
|
-
this.touch(parent.path);
|
|
664
|
+
this.touch(parent.path, `${parent.path === "/" ? "" : parent.path}/${baseOf(path)}`);
|
|
665
665
|
}
|
|
666
666
|
async rm(path, options = {}) {
|
|
667
667
|
let found;
|
|
@@ -2385,6 +2385,7 @@ var LAST_UID = 6e4;
|
|
|
2385
2385
|
var USERS_GROUP = "users";
|
|
2386
2386
|
var HOME_DIR = /^\/home\/[^/]+$/;
|
|
2387
2387
|
var SYSTEM_PNPM_HOME = "/usr/local/share/pnpm";
|
|
2388
|
+
var PNPM_CONFIG = "minimumReleaseAge: 1440\n";
|
|
2388
2389
|
var isId = (text) => text !== void 0 && /^\d+$/.test(text);
|
|
2389
2390
|
function lines(text) {
|
|
2390
2391
|
return text.split("\n").filter((line, i, all) => line !== "" || i < all.length - 1);
|
|
@@ -2440,6 +2441,7 @@ function userEnv(account, system) {
|
|
|
2440
2441
|
USER: account.name,
|
|
2441
2442
|
LOGNAME: account.name,
|
|
2442
2443
|
PNPM_HOME: pnpm,
|
|
2444
|
+
NPM_CONFIG_PREFIX: account.uid === 0 ? "/usr/local" : `${account.home}/.local`,
|
|
2443
2445
|
PATH: `${pnpm}/bin:/usr/local/bin:/usr/bin:/bin`
|
|
2444
2446
|
};
|
|
2445
2447
|
}
|
|
@@ -2464,6 +2466,18 @@ var UserDb = class {
|
|
|
2464
2466
|
group: parseGroup(await this.read(GROUP, DEFAULT_GROUP))
|
|
2465
2467
|
};
|
|
2466
2468
|
}
|
|
2469
|
+
async provision(row) {
|
|
2470
|
+
const pnpm = `${row.home}/.local/share/pnpm`;
|
|
2471
|
+
if (!await this.fs.exists(pnpm)) {
|
|
2472
|
+
await this.fs.mkdir(pnpm, { recursive: true });
|
|
2473
|
+
await this.fs.chmod(pnpm, row.name.startsWith("scoop-") ? 488 : 448);
|
|
2474
|
+
}
|
|
2475
|
+
const config = `${row.home}/.config/pnpm/config.yaml`;
|
|
2476
|
+
if (!await this.fs.exists(config)) {
|
|
2477
|
+
await this.fs.mkdir(`${row.home}/.config/pnpm`, { recursive: true });
|
|
2478
|
+
await this.fs.writeFile(config, PNPM_CONFIG);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2467
2481
|
async commit(passwd, group, then) {
|
|
2468
2482
|
const before = [await this.read(PASSWD, DEFAULT_PASSWD), await this.read(GROUP, DEFAULT_GROUP)];
|
|
2469
2483
|
try {
|
|
@@ -2537,6 +2551,7 @@ var UserDb = class {
|
|
|
2537
2551
|
const groups = parsed(group);
|
|
2538
2552
|
const found = users.find((r) => r.name === name2);
|
|
2539
2553
|
if (found) {
|
|
2554
|
+
if (found.uid >= FIRST_UID && found.uid <= LAST_UID) await this.provision(found);
|
|
2540
2555
|
remember();
|
|
2541
2556
|
return this.account(found, groups);
|
|
2542
2557
|
}
|
|
@@ -2555,6 +2570,7 @@ var UserDb = class {
|
|
|
2555
2570
|
const fresh = !await this.fs.exists(home);
|
|
2556
2571
|
await this.fs.mkdir(home, { recursive: true });
|
|
2557
2572
|
try {
|
|
2573
|
+
await this.provision(row);
|
|
2558
2574
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
2559
2575
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
2560
2576
|
} catch (err) {
|
|
@@ -5558,17 +5574,22 @@ async function followLinks(fs, path) {
|
|
|
5558
5574
|
}
|
|
5559
5575
|
return current;
|
|
5560
5576
|
}
|
|
5561
|
-
function withCommandDirs(fs, names) {
|
|
5577
|
+
function withCommandDirs(fs, names, userDir = async () => void 0) {
|
|
5562
5578
|
async function children2(path) {
|
|
5563
5579
|
if (path === "/") return ["bin", "usr"];
|
|
5564
5580
|
if (path === "/usr") return ["bin"];
|
|
5565
5581
|
if (path === "/bin" || path === "/usr/bin") return [...await names()];
|
|
5566
|
-
|
|
5582
|
+
const own = await userDir(path);
|
|
5583
|
+
return own?.size ? [...own] : void 0;
|
|
5567
5584
|
}
|
|
5568
5585
|
async function virtual(path) {
|
|
5569
5586
|
if (path === "/usr" || path === "/bin" || path === "/usr/bin") return synthetic(true, path);
|
|
5570
5587
|
const name2 = COMMAND.exec(path)?.[1];
|
|
5571
|
-
|
|
5588
|
+
if (name2 !== void 0) return (await names()).has(name2) ? synthetic(false, path) : void 0;
|
|
5589
|
+
if ((await userDir(path))?.size) return synthetic(true, path);
|
|
5590
|
+
const slash = path.lastIndexOf("/");
|
|
5591
|
+
const own = await userDir(path.slice(0, slash));
|
|
5592
|
+
return own?.has(path.slice(slash + 1)) ? synthetic(false, path) : void 0;
|
|
5572
5593
|
}
|
|
5573
5594
|
async function linked(path) {
|
|
5574
5595
|
return await virtual(path) ?? virtual(await followLinks(fs, path));
|
|
@@ -12919,8 +12940,11 @@ var Launcher = class {
|
|
|
12919
12940
|
createWorker;
|
|
12920
12941
|
modulesDir;
|
|
12921
12942
|
env;
|
|
12922
|
-
|
|
12923
|
-
|
|
12943
|
+
catalogs = /* @__PURE__ */ new Map();
|
|
12944
|
+
ownCatalogs = /* @__PURE__ */ new Map();
|
|
12945
|
+
binfmts = /* @__PURE__ */ new Map();
|
|
12946
|
+
scopes;
|
|
12947
|
+
unwatchScopes = () => void 0;
|
|
12924
12948
|
warned = /* @__PURE__ */ new Set();
|
|
12925
12949
|
compiled = /* @__PURE__ */ new Map();
|
|
12926
12950
|
processes = /* @__PURE__ */ new Map();
|
|
@@ -13000,7 +13024,11 @@ var Launcher = class {
|
|
|
13000
13024
|
ca: this.ca
|
|
13001
13025
|
});
|
|
13002
13026
|
enableCdp(this.net, this.cdp);
|
|
13003
|
-
const fs = withCommandDirs(
|
|
13027
|
+
const fs = withCommandDirs(
|
|
13028
|
+
this.base,
|
|
13029
|
+
async () => new Set((await this.commands()).keys()),
|
|
13030
|
+
(dir) => this.userCommandDir(dir)
|
|
13031
|
+
);
|
|
13004
13032
|
this.nodes = new VfsNodes(fs, (path) => this.released(path));
|
|
13005
13033
|
this.nodes.keepsOnDisk = true;
|
|
13006
13034
|
this.openFiles.add(this.nodes);
|
|
@@ -13018,35 +13046,99 @@ var Launcher = class {
|
|
|
13018
13046
|
this.fs = this.unlinked.wrap(keepingOpen(fs, this.nodes));
|
|
13019
13047
|
this.users = new UserDb(this.fs);
|
|
13020
13048
|
void this.unlinked.sweep("/");
|
|
13021
|
-
this.watchers.watch(
|
|
13022
|
-
this.
|
|
13023
|
-
|
|
13049
|
+
this.watchers.watch(
|
|
13050
|
+
[this.modulesDir, this.pnpmHome],
|
|
13051
|
+
{ recursive: true },
|
|
13052
|
+
() => this.resetCatalogs()
|
|
13053
|
+
);
|
|
13054
|
+
this.watchers.watch([PASSWD], { recursive: false }, () => {
|
|
13055
|
+
this.scopes = void 0;
|
|
13056
|
+
this.resetCatalogs();
|
|
13024
13057
|
});
|
|
13025
13058
|
}
|
|
13026
13059
|
setRoutes(table) {
|
|
13027
13060
|
this.routes.set(table);
|
|
13028
13061
|
}
|
|
13029
|
-
commands() {
|
|
13030
|
-
|
|
13031
|
-
|
|
13062
|
+
commands(scope = "") {
|
|
13063
|
+
let found = this.catalogs.get(scope);
|
|
13064
|
+
if (!found) {
|
|
13065
|
+
found = this.roots(scope).then((roots) => scanCommands(this.base, roots));
|
|
13066
|
+
this.catalogs.set(scope, found);
|
|
13067
|
+
}
|
|
13068
|
+
return found;
|
|
13032
13069
|
}
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13070
|
+
ownCommands(scope) {
|
|
13071
|
+
let found = this.ownCatalogs.get(scope);
|
|
13072
|
+
if (!found) {
|
|
13073
|
+
found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.base, roots)).then((commands) => new Set(commands.keys()));
|
|
13074
|
+
this.ownCatalogs.set(scope, found);
|
|
13075
|
+
}
|
|
13076
|
+
return found;
|
|
13077
|
+
}
|
|
13078
|
+
interpreters(scope = "") {
|
|
13079
|
+
let found = this.binfmts.get(scope);
|
|
13080
|
+
if (!found) {
|
|
13081
|
+
found = this.roots(scope).then(
|
|
13082
|
+
(roots) => scanBinfmts(this.base, roots, (message3) => {
|
|
13083
|
+
if (this.warned.has(message3)) return;
|
|
13084
|
+
this.warned.add(message3);
|
|
13085
|
+
console.warn(message3);
|
|
13086
|
+
})
|
|
13087
|
+
);
|
|
13088
|
+
this.binfmts.set(scope, found);
|
|
13089
|
+
}
|
|
13090
|
+
return found;
|
|
13042
13091
|
}
|
|
13043
|
-
async roots() {
|
|
13044
|
-
|
|
13092
|
+
async roots(scope = "") {
|
|
13093
|
+
const system = [this.modulesDir, ...await pnpmGlobalRoots(this.base, this.pnpmHome)];
|
|
13094
|
+
return scope ? [...await pnpmGlobalRoots(this.base, scope), ...system] : system;
|
|
13095
|
+
}
|
|
13096
|
+
resetCatalogs() {
|
|
13097
|
+
this.catalogs.clear();
|
|
13098
|
+
this.ownCatalogs.clear();
|
|
13099
|
+
this.binfmts.clear();
|
|
13100
|
+
}
|
|
13101
|
+
userScopes() {
|
|
13102
|
+
this.scopes ??= this.users.list().then(
|
|
13103
|
+
(accounts) => {
|
|
13104
|
+
const users = accounts.filter((account) => account.uid !== 0);
|
|
13105
|
+
const homes = users.map((account) => pnpmHomeOf(account, this.pnpmHome));
|
|
13106
|
+
this.unwatchScopes();
|
|
13107
|
+
this.unwatchScopes = this.watchers.watch(
|
|
13108
|
+
homes,
|
|
13109
|
+
{ recursive: true },
|
|
13110
|
+
() => this.resetCatalogs()
|
|
13111
|
+
);
|
|
13112
|
+
return {
|
|
13113
|
+
byUid: new Map(users.map((account, i) => [account.uid, homes[i]])),
|
|
13114
|
+
byBin: new Map(homes.map((home) => [`${home}/bin`, home]))
|
|
13115
|
+
};
|
|
13116
|
+
},
|
|
13117
|
+
() => ({ byUid: /* @__PURE__ */ new Map(), byBin: /* @__PURE__ */ new Map() })
|
|
13118
|
+
);
|
|
13119
|
+
return this.scopes;
|
|
13120
|
+
}
|
|
13121
|
+
async userCommandDir(dir) {
|
|
13122
|
+
const scope = (await this.userScopes()).byBin.get(dir);
|
|
13123
|
+
return scope === void 0 ? void 0 : this.ownCommands(scope);
|
|
13124
|
+
}
|
|
13125
|
+
async scopeOf(uid) {
|
|
13126
|
+
return (await this.userScopes()).byUid.get(uid) ?? "";
|
|
13127
|
+
}
|
|
13128
|
+
async commandAt(file, scope) {
|
|
13129
|
+
const system = COMMAND2.exec(file)?.[1];
|
|
13130
|
+
if (system !== void 0) return (await this.commands()).get(system);
|
|
13131
|
+
if (!file.includes("/")) return (await this.commands(scope)).get(file);
|
|
13132
|
+
const slash = file.lastIndexOf("/");
|
|
13133
|
+
const owner = (await this.userScopes()).byBin.get(file.slice(0, slash));
|
|
13134
|
+
if (owner === void 0 || !(await this.ownCommands(owner)).has(file.slice(slash + 1))) {
|
|
13135
|
+
return void 0;
|
|
13136
|
+
}
|
|
13137
|
+
return (await this.commands(owner)).get(file.slice(slash + 1));
|
|
13045
13138
|
}
|
|
13046
|
-
async resolve(file, argv0, cwd) {
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
const command = (await this.commands()).get(name2);
|
|
13139
|
+
async resolve(file, argv0, cwd, scope = "") {
|
|
13140
|
+
if (!file.includes("/") || COMMAND2.test(file)) {
|
|
13141
|
+
const command = await this.commandAt(file, scope);
|
|
13050
13142
|
return command && !command.script ? targetOf(command) : void 0;
|
|
13051
13143
|
}
|
|
13052
13144
|
const path = this.fs.resolvePath(cwd, file);
|
|
@@ -13057,6 +13149,8 @@ var Launcher = class {
|
|
|
13057
13149
|
const byPath = !COMMAND2.test(path) && (await this.commands()).get(linked)?.argv0Path === true;
|
|
13058
13150
|
return target && byPath ? { ...target, argv0: path } : target;
|
|
13059
13151
|
}
|
|
13152
|
+
const own = await this.commandAt(glue, scope);
|
|
13153
|
+
if (own) return own.script ? void 0 : targetOf(own);
|
|
13060
13154
|
const head = await this.head(glue);
|
|
13061
13155
|
if (!head) return void 0;
|
|
13062
13156
|
if (isWasm(head)) {
|
|
@@ -13079,45 +13173,45 @@ var Launcher = class {
|
|
|
13079
13173
|
return void 0;
|
|
13080
13174
|
}
|
|
13081
13175
|
}
|
|
13082
|
-
async scriptCommand(file) {
|
|
13083
|
-
const
|
|
13084
|
-
|
|
13085
|
-
const command =
|
|
13176
|
+
async scriptCommand(file, cwd, scope) {
|
|
13177
|
+
const direct = !file.includes("/") || COMMAND2.test(file);
|
|
13178
|
+
const at = direct ? file : await followLinks(this.base, this.fs.resolvePath(cwd, file));
|
|
13179
|
+
const command = await this.commandAt(at, scope);
|
|
13086
13180
|
return command?.script ? command : void 0;
|
|
13087
13181
|
}
|
|
13088
|
-
async interpreted(file, argv, cwd, depth = 0) {
|
|
13089
|
-
const command = await this.scriptCommand(file);
|
|
13182
|
+
async interpreted(file, argv, cwd, scope, depth = 0) {
|
|
13183
|
+
const command = await this.scriptCommand(file, cwd, scope);
|
|
13090
13184
|
const script = command?.script ?? this.fs.resolvePath(cwd, file);
|
|
13091
13185
|
const head = await this.head(script);
|
|
13092
13186
|
if (!head) return void 0;
|
|
13093
|
-
const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(), script);
|
|
13187
|
+
const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(scope), script);
|
|
13094
13188
|
const words = shebang(head) ?? (binfmt ? [binfmt] : void 0);
|
|
13095
13189
|
if (!words) return void 0;
|
|
13096
13190
|
if (baseName(words[0]) === "env") words.shift();
|
|
13097
13191
|
const [interp, ...rest2] = words;
|
|
13098
13192
|
const arg = rest2.join(" ");
|
|
13099
13193
|
const passed = [...arg ? [arg] : [], command ? script : file, ...argv.slice(1)];
|
|
13100
|
-
const found = interp ? await this.resolve(interp, interp, cwd) : void 0;
|
|
13194
|
+
const found = interp ? await this.resolve(interp, interp, cwd, scope) : void 0;
|
|
13101
13195
|
if (!found) {
|
|
13102
|
-
if (!interp || depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp)) {
|
|
13196
|
+
if (!interp || depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp, cwd, scope)) {
|
|
13103
13197
|
return void 0;
|
|
13104
13198
|
}
|
|
13105
|
-
const inner = await this.interpreted(interp, [interp, ...passed], cwd, depth + 1);
|
|
13199
|
+
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
13106
13200
|
return inner && { ...inner, target: withScriptEnv(inner.target, command) };
|
|
13107
13201
|
}
|
|
13108
13202
|
const target = withScriptEnv(found, command);
|
|
13109
13203
|
return { target, args: [...target.prefix ?? [], ...passed] };
|
|
13110
13204
|
}
|
|
13111
|
-
async plan(file, argv, cwd) {
|
|
13112
|
-
const direct = await this.resolve(file, argv[0] ?? file, cwd);
|
|
13205
|
+
async plan(file, argv, cwd, scope) {
|
|
13206
|
+
const direct = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
13113
13207
|
if (direct) return { target: direct, args: [...direct.prefix ?? [], ...argv.slice(1)] };
|
|
13114
|
-
return this.interpreted(file, argv, cwd);
|
|
13208
|
+
return this.interpreted(file, argv, cwd, scope);
|
|
13115
13209
|
}
|
|
13116
|
-
async unrunnable(file, cwd) {
|
|
13210
|
+
async unrunnable(file, cwd, scope) {
|
|
13117
13211
|
const path = this.fs.resolvePath(cwd, file);
|
|
13118
13212
|
const head = await this.base.readFileBuffer(path).catch(() => null);
|
|
13119
13213
|
if (!head || head[0] === 35 && head[1] === 33) return "ENOENT";
|
|
13120
|
-
return binfmtOf(await this.interpreters(), path) ? "ENOENT" : "ENOEXEC";
|
|
13214
|
+
return binfmtOf(await this.interpreters(scope), path) ? "ENOENT" : "ENOEXEC";
|
|
13121
13215
|
}
|
|
13122
13216
|
module(path) {
|
|
13123
13217
|
return this.base.stat(path).then((st) => {
|
|
@@ -13327,10 +13421,11 @@ var Launcher = class {
|
|
|
13327
13421
|
}
|
|
13328
13422
|
spawner(ppid, report) {
|
|
13329
13423
|
return async (req, fds) => {
|
|
13330
|
-
const
|
|
13424
|
+
const scope = await this.scopeOf(this.credOf(ppid).euid);
|
|
13425
|
+
const planned = await this.plan(req.file, req.argv, req.cwd, scope);
|
|
13331
13426
|
if (!planned) {
|
|
13332
13427
|
await fds.closeAll();
|
|
13333
|
-
throw new SpawnError(await this.unrunnable(req.file, req.cwd));
|
|
13428
|
+
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
13334
13429
|
}
|
|
13335
13430
|
const exec = req.exec ? { exec: true } : {};
|
|
13336
13431
|
const deciding = req.exec ? void 0 : this.undecided(ppid);
|
|
@@ -13632,18 +13727,18 @@ var Launcher = class {
|
|
|
13632
13727
|
...account.umask !== void 0 ? { umask: account.umask } : {}
|
|
13633
13728
|
};
|
|
13634
13729
|
}
|
|
13635
|
-
async starting(argv, dir) {
|
|
13636
|
-
this.
|
|
13637
|
-
|
|
13730
|
+
async starting(argv, dir, account) {
|
|
13731
|
+
this.resetCatalogs();
|
|
13732
|
+
const scope = account.uid === 0 ? "" : pnpmHomeOf(account, this.pnpmHome);
|
|
13638
13733
|
const start2 = dir ?? "/";
|
|
13639
13734
|
const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
|
|
13640
13735
|
const [file = ""] = argv;
|
|
13641
13736
|
await this.base.mkdir(cwd, { recursive: true });
|
|
13642
|
-
return { cwd, file, planned: await this.plan(file, argv, cwd) };
|
|
13737
|
+
return { cwd, file, planned: await this.plan(file, argv, cwd, scope) };
|
|
13643
13738
|
}
|
|
13644
13739
|
async openTerminal(argv, options) {
|
|
13645
13740
|
const account = await this.account(options.user);
|
|
13646
|
-
const { cwd, file, planned } = await this.starting(argv, options.cwd);
|
|
13741
|
+
const { cwd, file, planned } = await this.starting(argv, options.cwd, account);
|
|
13647
13742
|
if (!planned) throw new Error(`${file}: command not found`);
|
|
13648
13743
|
let leader = 0;
|
|
13649
13744
|
const tty = new KernelTty(
|
|
@@ -13686,7 +13781,7 @@ var Launcher = class {
|
|
|
13686
13781
|
}
|
|
13687
13782
|
async run(argv, options = {}) {
|
|
13688
13783
|
const account = await this.account(options.user);
|
|
13689
|
-
const { cwd, file, planned } = await this.starting(argv, options.cwd);
|
|
13784
|
+
const { cwd, file, planned } = await this.starting(argv, options.cwd, account);
|
|
13690
13785
|
const env = this.environment(cwd, options.env, account);
|
|
13691
13786
|
const out = [];
|
|
13692
13787
|
const err = [];
|