typescript-virtual-container 1.5.10 → 1.6.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 +236 -456
- package/dist/.tsbuildinfo +1 -1
- package/dist/Honeypot/index.d.ts +9 -0
- package/dist/Honeypot/index.js +57 -0
- package/dist/SSHMimic/exec.d.ts +4 -0
- package/dist/SSHMimic/exec.js +4 -0
- package/dist/SSHMimic/executor.d.ts +10 -1
- package/dist/SSHMimic/executor.js +18 -8
- package/dist/SSHMimic/hostKey.d.ts +5 -0
- package/dist/SSHMimic/hostKey.js +5 -0
- package/dist/SSHMimic/loginBanner.d.ts +7 -0
- package/dist/SSHMimic/loginBanner.js +4 -0
- package/dist/SSHMimic/loginFormat.d.ts +4 -0
- package/dist/SSHMimic/loginFormat.js +4 -0
- package/dist/SSHMimic/prompt.d.ts +9 -0
- package/dist/SSHMimic/prompt.js +9 -0
- package/dist/SSHMimic/scp.d.ts +18 -0
- package/dist/SSHMimic/scp.js +14 -0
- package/dist/VirtualFileSystem/binaryPack.d.ts +7 -3
- package/dist/VirtualFileSystem/binaryPack.js +32 -10
- package/dist/VirtualFileSystem/index.d.ts +29 -0
- package/dist/VirtualFileSystem/index.js +126 -5
- package/dist/VirtualFileSystem/internalTypes.d.ts +4 -0
- package/dist/VirtualFileSystem/journal.d.ts +10 -4
- package/dist/VirtualFileSystem/journal.js +12 -2
- package/dist/VirtualFileSystem/path.d.ts +23 -1
- package/dist/VirtualFileSystem/path.js +23 -3
- package/dist/VirtualPackageManager/index.js +1 -1
- package/dist/VirtualShell/index.d.ts +3 -0
- package/dist/VirtualShell/index.js +12 -3
- package/dist/VirtualUserManager/index.d.ts +20 -1
- package/dist/VirtualUserManager/index.js +52 -15
- package/dist/commands/bc.d.ts +5 -0
- package/dist/commands/bc.js +5 -0
- package/dist/commands/cat.js +2 -2
- package/dist/commands/chgrp.d.ts +7 -0
- package/dist/commands/chgrp.js +42 -0
- package/dist/commands/chown.d.ts +7 -0
- package/dist/commands/chown.js +79 -0
- package/dist/commands/cp.js +4 -3
- package/dist/commands/dd.d.ts +7 -0
- package/dist/commands/dd.js +60 -0
- package/dist/commands/declare.js +0 -2
- package/dist/commands/expr.d.ts +7 -0
- package/dist/commands/expr.js +63 -0
- package/dist/commands/fun.d.ts +5 -0
- package/dist/commands/fun.js +5 -1
- package/dist/commands/help.d.ts +5 -0
- package/dist/commands/help.js +5 -0
- package/dist/commands/helpers.d.ts +43 -0
- package/dist/commands/helpers.js +61 -0
- package/dist/commands/id.d.ts +5 -0
- package/dist/commands/id.js +5 -0
- package/dist/commands/ip.d.ts +1 -0
- package/dist/commands/ip.js +50 -23
- package/dist/commands/jobs.js +43 -9
- package/dist/commands/kill.d.ts +1 -0
- package/dist/commands/kill.js +13 -5
- package/dist/commands/last.js +1 -1
- package/dist/commands/ln.d.ts +5 -0
- package/dist/commands/ln.js +5 -0
- package/dist/commands/ls.d.ts +5 -0
- package/dist/commands/ls.js +19 -4
- package/dist/commands/lsb-release.js +1 -1
- package/dist/commands/man.d.ts +5 -0
- package/dist/commands/man.js +5 -0
- package/dist/commands/manuals-bundle.js +242 -0
- package/dist/commands/miscutils.d.ts +43 -0
- package/dist/commands/miscutils.js +233 -0
- package/dist/commands/mkdir.js +3 -2
- package/dist/commands/mv.js +4 -3
- package/dist/commands/netcat.d.ts +7 -0
- package/dist/commands/netcat.js +64 -0
- package/dist/commands/nice.d.ts +7 -0
- package/dist/commands/nice.js +22 -0
- package/dist/commands/nohup.d.ts +7 -0
- package/dist/commands/nohup.js +18 -0
- package/dist/commands/ping.d.ts +2 -1
- package/dist/commands/ping.js +46 -8
- package/dist/commands/procUtils.d.ts +13 -0
- package/dist/commands/procUtils.js +72 -0
- package/dist/commands/pwd.d.ts +5 -0
- package/dist/commands/pwd.js +5 -0
- package/dist/commands/python.js +0 -4
- package/dist/commands/read.js +0 -1
- package/dist/commands/registry.d.ts +37 -0
- package/dist/commands/registry.js +73 -0
- package/dist/commands/rm.js +3 -2
- package/dist/commands/runtime.d.ts +47 -1
- package/dist/commands/runtime.js +60 -5
- package/dist/commands/sh.d.ts +5 -0
- package/dist/commands/sh.js +5 -0
- package/dist/commands/stat.js +3 -2
- package/dist/commands/strace.js +0 -1
- package/dist/commands/sysinfo.d.ts +19 -0
- package/dist/commands/sysinfo.js +73 -0
- package/dist/commands/test.d.ts +5 -0
- package/dist/commands/test.js +5 -0
- package/dist/commands/textutils.d.ts +25 -0
- package/dist/commands/textutils.js +171 -0
- package/dist/commands/top.d.ts +7 -0
- package/dist/commands/top.js +54 -0
- package/dist/commands/touch.js +6 -2
- package/dist/commands/tr.d.ts +5 -0
- package/dist/commands/tr.js +5 -0
- package/dist/commands/w.js +1 -1
- package/dist/commands/which.d.ts +5 -0
- package/dist/commands/which.js +5 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +4 -0
- package/dist/modules/VirtualNetworkManager.d.ts +54 -0
- package/dist/modules/VirtualNetworkManager.js +144 -0
- package/dist/modules/linuxRootfs.d.ts +4 -3
- package/dist/modules/linuxRootfs.js +115 -74
- package/dist/modules/neofetch.d.ts +2 -0
- package/dist/modules/neofetch.js +3 -2
- package/dist/modules/pacmanGame.d.ts +2 -0
- package/dist/modules/pacmanGame.js +1 -0
- package/dist/modules/shellInteractive.d.ts +2 -0
- package/dist/modules/shellInteractive.js +2 -0
- package/dist/modules/shellRuntime.d.ts +7 -0
- package/dist/modules/shellRuntime.js +6 -0
- package/dist/modules/webTermRenderer.js +0 -7
- package/dist/types/commands.d.ts +1 -1
- package/dist/types/vfs.d.ts +8 -0
- package/dist/utils/argv.d.ts +22 -3
- package/dist/utils/argv.js +22 -3
- package/dist/utils/perfLogger.d.ts +10 -2
- package/dist/utils/perfLogger.js +7 -14
- package/dist/utils/shellSession.d.ts +35 -0
- package/dist/utils/shellSession.js +35 -0
- package/package.json +3 -2
- package/scripts/postinstall.js +42 -0
package/dist/commands/helpers.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
const PROTECTED_PREFIXES = ["/.virtual-env-js/.auth", "/etc/htpasswd"];
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a path string against the virtual file system.
|
|
5
|
+
* Supports `~` as shorthand for the home directory. If `inputPath` is
|
|
6
|
+
* absolute it is returned as-is; otherwise it is joined to `cwd`.
|
|
7
|
+
*
|
|
8
|
+
* @param cwd - The current working directory
|
|
9
|
+
* @param inputPath - The path string to resolve
|
|
10
|
+
* @param homeDir - The home directory to use for `~` expansion (defaults to `/root`)
|
|
11
|
+
* @returns The normalized absolute path
|
|
12
|
+
*/
|
|
3
13
|
export function resolvePath(cwd, inputPath, homeDir) {
|
|
4
14
|
if (!inputPath || inputPath.trim() === "") {
|
|
5
15
|
return cwd;
|
|
@@ -26,6 +36,14 @@ export function assertPathAccess(authUser, targetPath, operation) {
|
|
|
26
36
|
throw new Error(`${operation}: permission denied: ${targetPath}`);
|
|
27
37
|
}
|
|
28
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Strips the filename from a URL path, extracting the last path segment.
|
|
41
|
+
* Removes query strings and fragments first. Returns `"index.html"` when
|
|
42
|
+
* no segment is found.
|
|
43
|
+
*
|
|
44
|
+
* @param url - The URL or path string to process
|
|
45
|
+
* @returns The extracted filename, or "index.html" as a fallback
|
|
46
|
+
*/
|
|
29
47
|
export function stripUrlFilename(url) {
|
|
30
48
|
const cleaned = url.split("?")[0]?.split("#")[0] ?? url;
|
|
31
49
|
const lastPart = cleaned.split("/").filter(Boolean).pop();
|
|
@@ -47,6 +65,16 @@ function levenshtein(a, b) {
|
|
|
47
65
|
}
|
|
48
66
|
return dp[a.length][b.length];
|
|
49
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolves a path with readable error messages by attempting an exact match
|
|
70
|
+
* first, then falling back to case-insensitive matching, and finally to a
|
|
71
|
+
* Levenshtein-distance (≤1) fuzzy match against sibling entries.
|
|
72
|
+
*
|
|
73
|
+
* @param vfs - The virtual file system instance
|
|
74
|
+
* @param cwd - The current working directory
|
|
75
|
+
* @param inputPath - The path string to resolve
|
|
76
|
+
* @returns The best matching path (exact, case-insensitive, or fuzzy)
|
|
77
|
+
*/
|
|
50
78
|
export function resolveReadablePath(vfs, cwd, inputPath) {
|
|
51
79
|
const exactPath = resolvePath(cwd, inputPath);
|
|
52
80
|
if (vfs.exists(exactPath)) {
|
|
@@ -65,6 +93,39 @@ export function resolveReadablePath(vfs, cwd, inputPath) {
|
|
|
65
93
|
}
|
|
66
94
|
return exactPath;
|
|
67
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Returns the active package manager associated with the given shell.
|
|
98
|
+
*
|
|
99
|
+
* @param shell - The VirtualShell instance
|
|
100
|
+
* @returns The VirtualPackageManager, or undefined if none is configured
|
|
101
|
+
*/
|
|
68
102
|
export function getPackageManager(shell) {
|
|
69
103
|
return shell.packageManager;
|
|
70
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* POSIX-style permission check: does `authUser` have `want` access to `filePath`?
|
|
107
|
+
* `want` is a bitmask: 4=R_OK, 2=W_OK, 1=X_OK, 0=F_OK (check existence).
|
|
108
|
+
* Root bypasses all checks. Throws on EACCES.
|
|
109
|
+
*/
|
|
110
|
+
export function checkFilePermission(vfs, users, authUser, filePath, want) {
|
|
111
|
+
if (authUser === "root")
|
|
112
|
+
return;
|
|
113
|
+
if (want === 0)
|
|
114
|
+
return; // F_OK — just existence
|
|
115
|
+
assertPathAccess(authUser, filePath, "access");
|
|
116
|
+
const uid = users.getUid(authUser);
|
|
117
|
+
const gid = users.getGid(authUser);
|
|
118
|
+
if (!vfs.checkAccess(filePath, uid, gid, want)) {
|
|
119
|
+
const mode = vfs.stat(filePath).mode;
|
|
120
|
+
const permStr = (mode & 0o400 ? "r" : "-") +
|
|
121
|
+
(mode & 0o200 ? "w" : "-") +
|
|
122
|
+
(mode & 0o100 ? "x" : "-") +
|
|
123
|
+
(mode & 0o040 ? "r" : "-") +
|
|
124
|
+
(mode & 0o020 ? "w" : "-") +
|
|
125
|
+
(mode & 0o010 ? "x" : "-") +
|
|
126
|
+
(mode & 0o004 ? "r" : "-") +
|
|
127
|
+
(mode & 0o002 ? "w" : "-") +
|
|
128
|
+
(mode & 0o001 ? "x" : "-");
|
|
129
|
+
throw new Error(`access: permission denied (mode=${permStr})`);
|
|
130
|
+
}
|
|
131
|
+
}
|
package/dist/commands/id.d.ts
CHANGED
package/dist/commands/id.js
CHANGED
package/dist/commands/ip.d.ts
CHANGED
package/dist/commands/ip.js
CHANGED
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
const ADDR_OUTPUT = `1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
|
|
2
|
-
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
|
3
|
-
inet 127.0.0.1/8 scope host lo
|
|
4
|
-
valid_lft forever preferred_lft forever
|
|
5
|
-
inet6 ::1/128 scope host
|
|
6
|
-
valid_lft forever preferred_lft forever
|
|
7
|
-
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
|
|
8
|
-
link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
|
|
9
|
-
inet 10.0.0.2/24 brd 10.0.0.255 scope global eth0
|
|
10
|
-
valid_lft forever preferred_lft forever
|
|
11
|
-
inet6 fe80::42:aff:fe00:2/64 scope link
|
|
12
|
-
valid_lft forever preferred_lft forever`;
|
|
13
|
-
const ROUTE_OUTPUT = `default via 10.0.0.1 dev eth0
|
|
14
|
-
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2`;
|
|
15
|
-
const LINK_OUTPUT = `1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
|
|
16
|
-
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
|
17
|
-
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
|
|
18
|
-
link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff`;
|
|
19
1
|
/**
|
|
20
2
|
* Show/manipulate routing, network devices, interfaces and tunnels.
|
|
3
|
+
* Uses the shell's VirtualNetworkManager for dynamic output.
|
|
21
4
|
* @category network
|
|
22
5
|
* @params ["<object> <command>"]
|
|
23
6
|
*/
|
|
@@ -26,23 +9,67 @@ export const ipCommand = {
|
|
|
26
9
|
description: "Show/manipulate routing, network devices, interfaces",
|
|
27
10
|
category: "network",
|
|
28
11
|
params: ["<object> <command>"],
|
|
29
|
-
run: ({ args }) => {
|
|
12
|
+
run: ({ args, shell }) => {
|
|
13
|
+
const net = shell.network;
|
|
30
14
|
const obj = args[0]?.toLowerCase();
|
|
31
15
|
const cmd = args[1]?.toLowerCase() ?? "show";
|
|
32
16
|
if (!obj) {
|
|
33
17
|
return { stderr: "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\nOBJECT := { link | addr | route | neigh }", exitCode: 1 };
|
|
34
18
|
}
|
|
35
19
|
if (obj === "addr" || obj === "address" || obj === "a") {
|
|
36
|
-
|
|
20
|
+
if (cmd === "add") {
|
|
21
|
+
// ip addr add <ip>/<mask> dev <dev>
|
|
22
|
+
const ipArg = args.find((a) => a.includes("/"));
|
|
23
|
+
const devIdx = args.indexOf("dev");
|
|
24
|
+
const dev = devIdx !== -1 && devIdx + 1 < args.length ? args[devIdx + 1] : undefined;
|
|
25
|
+
if (ipArg && dev) {
|
|
26
|
+
const [ip, maskStr] = ipArg.split("/");
|
|
27
|
+
const mask = parseInt(maskStr ?? "24", 10);
|
|
28
|
+
net.setInterfaceIp(dev, ip ?? "0.0.0.0", mask);
|
|
29
|
+
}
|
|
30
|
+
return { exitCode: 0 };
|
|
31
|
+
}
|
|
32
|
+
if (cmd === "del") {
|
|
33
|
+
const devIdx = args.indexOf("dev");
|
|
34
|
+
const dev = devIdx !== -1 && devIdx + 1 < args.length ? args[devIdx + 1] : undefined;
|
|
35
|
+
if (dev)
|
|
36
|
+
net.setInterfaceIp(dev, "0.0.0.0", 0);
|
|
37
|
+
return { exitCode: 0 };
|
|
38
|
+
}
|
|
39
|
+
return { stdout: `${net.formatIpAddr()}\n`, exitCode: 0 };
|
|
37
40
|
}
|
|
38
41
|
if (obj === "route" || obj === "r" || obj === "ro") {
|
|
39
|
-
|
|
42
|
+
if (cmd === "add") {
|
|
43
|
+
const viaIdx = args.indexOf("via");
|
|
44
|
+
const devIdx = args.indexOf("dev");
|
|
45
|
+
const dest = args[1] !== "add" ? args[1] : args[2]; // ip route add <dest> ...
|
|
46
|
+
const gateway = viaIdx !== -1 ? args[viaIdx + 1] : "0.0.0.0";
|
|
47
|
+
const device = devIdx !== -1 ? args[devIdx + 1] : "eth0";
|
|
48
|
+
if (dest && dest !== "add")
|
|
49
|
+
net.addRoute(dest, gateway ?? "0.0.0.0", "255.255.255.0", device ?? "eth0");
|
|
50
|
+
return { exitCode: 0 };
|
|
51
|
+
}
|
|
52
|
+
if (cmd === "del") {
|
|
53
|
+
const dest = args[1] !== "del" ? args[1] : args[2];
|
|
54
|
+
if (dest && dest !== "del")
|
|
55
|
+
net.delRoute(dest);
|
|
56
|
+
return { exitCode: 0 };
|
|
57
|
+
}
|
|
58
|
+
return { stdout: `${net.formatIpRoute()}\n`, exitCode: 0 };
|
|
40
59
|
}
|
|
41
60
|
if (obj === "link" || obj === "l") {
|
|
42
|
-
|
|
61
|
+
if (cmd === "set") {
|
|
62
|
+
const dev = args[2]; // ip link set <dev> ...
|
|
63
|
+
if (args.includes("up") && dev)
|
|
64
|
+
net.setInterfaceState(dev, "UP");
|
|
65
|
+
if (args.includes("down") && dev)
|
|
66
|
+
net.setInterfaceState(dev, "DOWN");
|
|
67
|
+
return { exitCode: 0 };
|
|
68
|
+
}
|
|
69
|
+
return { stdout: `${net.formatIpLink()}\n`, exitCode: 0 };
|
|
43
70
|
}
|
|
44
71
|
if (obj === "neigh" || obj === "n") {
|
|
45
|
-
return { stdout:
|
|
72
|
+
return { stdout: `${net.formatIpNeigh()}\n`, exitCode: 0 };
|
|
46
73
|
}
|
|
47
74
|
if (["set", "add", "del", "flush", "change", "replace"].includes(cmd)) {
|
|
48
75
|
return { exitCode: 0 }; // silently succeed mutations
|
package/dist/commands/jobs.js
CHANGED
|
@@ -1,27 +1,61 @@
|
|
|
1
|
+
function parseJobspec(arg, procs) {
|
|
2
|
+
if (!arg) {
|
|
3
|
+
// Default to most recent background job
|
|
4
|
+
return procs.filter((p) => p.status !== "stopped").pop();
|
|
5
|
+
}
|
|
6
|
+
const pid = parseInt(arg.replace(/^%/, ""), 10);
|
|
7
|
+
return procs.find((p) => p.pid === pid);
|
|
8
|
+
}
|
|
1
9
|
export const jobsCommand = {
|
|
2
10
|
name: "jobs",
|
|
3
11
|
description: "List active jobs",
|
|
4
12
|
category: "shell",
|
|
5
13
|
params: [],
|
|
6
|
-
run: () =>
|
|
14
|
+
run: ({ shell }) => {
|
|
15
|
+
const procs = shell.users.listProcesses();
|
|
16
|
+
if (procs.length === 0)
|
|
17
|
+
return { stdout: "", exitCode: 0 };
|
|
18
|
+
const lines = procs.map((p, i) => {
|
|
19
|
+
const label = `[${i + 1}]`;
|
|
20
|
+
const status = p.status === "running" ? "running" : p.status === "done" ? "done" : "stopped";
|
|
21
|
+
return `${label} ${String(p.pid).padStart(5)} ${status.padEnd(8)} ${p.argv.join(" ")}`;
|
|
22
|
+
});
|
|
23
|
+
return { stdout: `${lines.join("\n")}\n`, exitCode: 0 };
|
|
24
|
+
},
|
|
7
25
|
};
|
|
8
26
|
export const bgCommand = {
|
|
9
27
|
name: "bg",
|
|
10
28
|
description: "Resume a suspended job in the background",
|
|
11
29
|
category: "shell",
|
|
12
30
|
params: ["[%jobspec]"],
|
|
13
|
-
run: ({ args }) =>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
31
|
+
run: ({ args, shell }) => {
|
|
32
|
+
const procs = shell.users.listProcesses();
|
|
33
|
+
const proc = parseJobspec(args[0], procs);
|
|
34
|
+
if (!proc) {
|
|
35
|
+
return { stderr: `bg: ${args[0] ?? "%1"}: no such job`, exitCode: 1 };
|
|
36
|
+
}
|
|
37
|
+
if (proc.status === "done") {
|
|
38
|
+
return { stderr: `bg: ${args[0]}: job has finished`, exitCode: 1 };
|
|
39
|
+
}
|
|
40
|
+
proc.status = "running";
|
|
41
|
+
return { stdout: `[${procs.indexOf(proc) + 1}] ${proc.pid} ${proc.argv.join(" ")} &\n`, exitCode: 0 };
|
|
42
|
+
},
|
|
17
43
|
};
|
|
18
44
|
export const fgCommand = {
|
|
19
45
|
name: "fg",
|
|
20
46
|
description: "Resume a suspended job in the foreground",
|
|
21
47
|
category: "shell",
|
|
22
48
|
params: ["[%jobspec]"],
|
|
23
|
-
run: ({ args }) =>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
49
|
+
run: ({ args, shell }) => {
|
|
50
|
+
const procs = shell.users.listProcesses();
|
|
51
|
+
const proc = parseJobspec(args[0], procs);
|
|
52
|
+
if (!proc) {
|
|
53
|
+
return { stderr: `fg: ${args[0] ?? "%1"}: no such job`, exitCode: 1 };
|
|
54
|
+
}
|
|
55
|
+
if (proc.status === "done") {
|
|
56
|
+
return { stderr: `fg: ${args[0]}: job has finished`, exitCode: 1 };
|
|
57
|
+
}
|
|
58
|
+
proc.status = "running";
|
|
59
|
+
return { stdout: `${proc.argv.join(" ")}\n`, exitCode: 0 };
|
|
60
|
+
},
|
|
27
61
|
};
|
package/dist/commands/kill.d.ts
CHANGED
package/dist/commands/kill.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Send a signal to a process by PID.
|
|
3
|
+
* Supports SIGTERM (default) and SIGKILL (-9). Aborts background processes.
|
|
3
4
|
* @category system
|
|
4
5
|
* @params ["[-9] <pid>"]
|
|
5
6
|
*/
|
|
@@ -8,11 +9,18 @@ export const killCommand = {
|
|
|
8
9
|
description: "Send signal to process",
|
|
9
10
|
category: "system",
|
|
10
11
|
params: ["[-9] <pid>"],
|
|
11
|
-
run: ({ args }) => {
|
|
12
|
-
const
|
|
13
|
-
if (!
|
|
12
|
+
run: ({ args, shell }) => {
|
|
13
|
+
const pidStr = args.find((a) => !a.startsWith("-"));
|
|
14
|
+
if (!pidStr)
|
|
14
15
|
return { stderr: "kill: no pid specified", exitCode: 1 };
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
const pid = parseInt(pidStr, 10);
|
|
17
|
+
if (Number.isNaN(pid)) {
|
|
18
|
+
return { stderr: `kill: invalid pid: ${pidStr}`, exitCode: 1 };
|
|
19
|
+
}
|
|
20
|
+
const found = shell.users.killProcess(pid);
|
|
21
|
+
if (!found) {
|
|
22
|
+
return { stderr: `kill: (${pid}) - No such process`, exitCode: 1 };
|
|
23
|
+
}
|
|
24
|
+
return { stdout: "", exitCode: 0 };
|
|
17
25
|
},
|
|
18
26
|
};
|
package/dist/commands/last.js
CHANGED
|
@@ -22,7 +22,7 @@ export const lastCommand = {
|
|
|
22
22
|
}).replace(",", "")}`;
|
|
23
23
|
lines.push(`${target.padEnd(10)} pts/0 ${(log.from ?? "browser").padEnd(16)} ${ds} still logged in`);
|
|
24
24
|
}
|
|
25
|
-
catch { }
|
|
25
|
+
catch { /* log entry may be corrupt */ }
|
|
26
26
|
}
|
|
27
27
|
lines.push("");
|
|
28
28
|
lines.push(`wtmp begins ${new Date().toDateString()}`);
|
package/dist/commands/ln.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { ShellModule } from "../types/commands";
|
|
2
|
+
/**
|
|
3
|
+
* Create links.
|
|
4
|
+
* @category files
|
|
5
|
+
* @params ["[-s] <target> <link_name>"]
|
|
6
|
+
*/
|
|
2
7
|
export declare const lnCommand: ShellModule;
|
|
3
8
|
/** Shell command: print the value of a symbolic link. */
|
|
4
9
|
export declare const readlinkCommand: ShellModule;
|
package/dist/commands/ln.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { ifFlag } from "./command-helpers";
|
|
2
2
|
import { assertPathAccess, resolvePath } from "./helpers";
|
|
3
|
+
/**
|
|
4
|
+
* Create links.
|
|
5
|
+
* @category files
|
|
6
|
+
* @params ["[-s] <target> <link_name>"]
|
|
7
|
+
*/
|
|
3
8
|
export const lnCommand = {
|
|
4
9
|
name: "ln",
|
|
5
10
|
description: "Create links",
|
package/dist/commands/ls.d.ts
CHANGED
package/dist/commands/ls.js
CHANGED
|
@@ -145,13 +145,26 @@ function longListing(vfs, dir, items) {
|
|
|
145
145
|
});
|
|
146
146
|
const wNlink = Math.max(...rows.map((r) => r.nlink.length));
|
|
147
147
|
const wSize = Math.max(...rows.map((r) => r.size.length));
|
|
148
|
-
const owner = "root";
|
|
149
|
-
const group = "root";
|
|
150
148
|
const total = items.length * 8;
|
|
151
|
-
const lines = rows.map((r) =>
|
|
149
|
+
const lines = rows.map((r, i) => {
|
|
150
|
+
const st = (() => { try {
|
|
151
|
+
return vfs.stat(`${base}/${items[i]}`);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
} })();
|
|
156
|
+
const uidStr = st && "uid" in st ? String(st.uid) : "0";
|
|
157
|
+
const gidStr = st && "gid" in st ? String(st.gid) : "0";
|
|
158
|
+
return `${r.perms} ${r.nlink.padStart(wNlink)} ${uidStr} ${gidStr} ${r.size.padStart(wSize)} ${r.date} ${r.label}`;
|
|
159
|
+
});
|
|
152
160
|
return `total ${total}\n${lines.join("\n")}`;
|
|
153
161
|
}
|
|
154
162
|
// ─── command ─────────────────────────────────────────────────────────────────
|
|
163
|
+
/**
|
|
164
|
+
* List directory contents.
|
|
165
|
+
* @category navigation
|
|
166
|
+
* @params ["[-la] [path]"]
|
|
167
|
+
*/
|
|
155
168
|
export const lsCommand = {
|
|
156
169
|
name: "ls",
|
|
157
170
|
description: "List directory contents",
|
|
@@ -181,8 +194,10 @@ export const lsCommand = {
|
|
|
181
194
|
const label = isLink
|
|
182
195
|
? `${colorize(name, color)} -> ${readlinkTarget(shell.vfs, target)}`
|
|
183
196
|
: colorize(name, color);
|
|
197
|
+
const uidStr = "uid" in st ? String(st.uid) : "0";
|
|
198
|
+
const gidStr = "gid" in st ? String(st.gid) : "0";
|
|
184
199
|
return {
|
|
185
|
-
stdout: `${perms} 1
|
|
200
|
+
stdout: `${perms} 1 ${uidStr} ${gidStr} ${size} ${formatDate(st.updatedAt)} ${label}\n`,
|
|
186
201
|
exitCode: 0,
|
|
187
202
|
};
|
|
188
203
|
}
|
|
@@ -30,7 +30,7 @@ export const lsbReleaseCommand = {
|
|
|
30
30
|
.trim();
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
catch { }
|
|
33
|
+
catch { /* /etc/os-release may not exist */ }
|
|
34
34
|
const all = ifFlag(args, ["-a", "--all"]);
|
|
35
35
|
const showId = ifFlag(args, ["-i", "--id"]);
|
|
36
36
|
const showDesc = ifFlag(args, ["-d", "--description"]);
|
package/dist/commands/man.d.ts
CHANGED
package/dist/commands/man.js
CHANGED
|
@@ -2,6 +2,11 @@ import { MANUALS } from "./manuals-bundle";
|
|
|
2
2
|
const MANUAL_ALIASES = {
|
|
3
3
|
gunzip: "gzip",
|
|
4
4
|
};
|
|
5
|
+
/**
|
|
6
|
+
* Interface to the system reference manuals.
|
|
7
|
+
* @category shell
|
|
8
|
+
* @params ["<command>"]
|
|
9
|
+
*/
|
|
5
10
|
export const manCommand = {
|
|
6
11
|
name: "man",
|
|
7
12
|
description: "Interface to the system reference manuals",
|