mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import { existsSync, readFileSync } from "node:fs";
|
|
import { homedir } from "node:os";
|
|
import { join } from "node:path";
|
|
|
|
export type EffectiveSshConfig = Map<string, string[]>;
|
|
|
|
export function parseSshG(text: string): EffectiveSshConfig {
|
|
const values: EffectiveSshConfig = new Map();
|
|
for (const line of text.split(/\r?\n/)) {
|
|
const separator = line.indexOf(" ");
|
|
if (separator < 1) continue;
|
|
const key = line.slice(0, separator).trim().toLowerCase();
|
|
const value = line.slice(separator + 1).trim();
|
|
if (!key || !value) continue;
|
|
const current = values.get(key) ?? [];
|
|
current.push(value);
|
|
values.set(key, current);
|
|
}
|
|
return values;
|
|
}
|
|
|
|
export function resolveOpenSshAlias(alias: string): EffectiveSshConfig {
|
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(alias)) throw new Error(`invalid SSH alias: ${alias}`);
|
|
const output = execFileSync("ssh", ["-G", "--", alias], {
|
|
encoding: "utf8",
|
|
stdio: ["ignore", "pipe", "pipe"],
|
|
});
|
|
return parseSshG(output);
|
|
}
|
|
|
|
export function effectiveValue(config: EffectiveSshConfig, key: string): string | undefined {
|
|
return config.get(key.toLowerCase())?.at(-1);
|
|
}
|
|
|
|
export function effectiveValues(config: EffectiveSshConfig, key: string): string[] {
|
|
return config.get(key.toLowerCase()) ?? [];
|
|
}
|
|
|
|
export function effectiveIdentityAgent(
|
|
config: EffectiveSshConfig,
|
|
env: NodeJS.ProcessEnv = process.env,
|
|
): string | undefined {
|
|
const configured = effectiveValue(config, "identityagent")?.replace(/^"|"$/g, "");
|
|
if (!configured || configured.toLowerCase() === "none") return undefined;
|
|
if (configured === "SSH_AUTH_SOCK" || configured === "$SSH_AUTH_SOCK" || configured === "${SSH_AUTH_SOCK}") {
|
|
return env.SSH_AUTH_SOCK;
|
|
}
|
|
return configured;
|
|
}
|
|
|
|
export function listDirectSshAliases(configPath = join(homedir(), ".ssh", "config")): string[] {
|
|
if (!existsSync(configPath)) return [];
|
|
const aliases: string[] = [];
|
|
const text = readFileSync(configPath, "utf8");
|
|
for (const line of text.split(/\r?\n/)) {
|
|
const match = /^\s*Host\s+(.+?)\s*$/i.exec(line);
|
|
if (!match) continue;
|
|
for (const alias of match[1].split(/\s+/)) {
|
|
if (!alias || alias.includes("*") || alias.includes("?") || alias.startsWith("!")) continue;
|
|
if (!aliases.includes(alias)) aliases.push(alias);
|
|
}
|
|
}
|
|
return aliases;
|
|
}
|