mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-28 07:44:06 +01:00
Shell (Linux): supports more ksh variants
This commit is contained in:
@@ -118,22 +118,162 @@ static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version) {
|
static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version) {
|
||||||
if (ffProcessAppendStdErr(version, (char* const[]) { exe->chars, "--version", nullptr }) == nullptr && ffStrbufSubstrAfterFirstS(version, " (AT&T Research) ")) {
|
ffStrbufClear(version);
|
||||||
// version sh (AT&T Research) 93u+ 2012-08-01
|
|
||||||
ffStrbufSubstrBeforeFirstC(version, ' ');
|
// ksh93 has used both stderr and stdout for --version, and the exit
|
||||||
|
// status is not consistent across releases. Parse any captured output
|
||||||
|
// before trying the next probe.
|
||||||
|
for (int attempt = 0; attempt < 4; ++attempt) {
|
||||||
|
ffStrbufClear(version);
|
||||||
|
if (attempt < 2 && (ffStrbufEndsWithS(exe, "mksh") || ffStrbufEndsWithS(exe, "pdksh") || ffStrbufEndsWithS(exe, "oksh")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (attempt == 0) {
|
||||||
|
ffProcessAppendStdErr(version, (char* const[]) { exe->chars, "--version", nullptr });
|
||||||
|
} else if (attempt == 1) {
|
||||||
|
ffProcessAppendStdOut(version, (char* const[]) { exe->chars, "--version", nullptr });
|
||||||
|
} else if (attempt == 2) {
|
||||||
|
ffProcessAppendStdOut(version, (char* const[]) {
|
||||||
|
exe->chars,
|
||||||
|
"-c",
|
||||||
|
"printf '%s\\n' \"${KSH_VERSION:-${SH_VERSION:-}}\"",
|
||||||
|
nullptr
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ffProcessAppendStdOut(version, (char* const[]) {
|
||||||
|
exe->chars,
|
||||||
|
"-c",
|
||||||
|
"printf '%s\\n' \"${.sh.version}\"",
|
||||||
|
nullptr
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* p = version->chars;
|
||||||
|
while (*p && isspace((unsigned char) *p))
|
||||||
|
++p;
|
||||||
|
if (!*p)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// @(#)PD KSH v5.2.14, @(#)MIRBSD KSH R59, @(#)LEGACY KSH R59
|
||||||
|
if (ffStrStartsWith(p, "@(#)")) {
|
||||||
|
const char* marker = strstr(p, " KSH ");
|
||||||
|
if (!marker)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char* start = marker + strlen(" KSH ");
|
||||||
|
while (*start && isspace((unsigned char) *start))
|
||||||
|
++start;
|
||||||
|
const char* end = start;
|
||||||
|
while (*end && !isspace((unsigned char) *end))
|
||||||
|
++end;
|
||||||
|
|
||||||
|
uint32_t length = (uint32_t) (end - start);
|
||||||
|
if (length > 1 && start[0] == 'v' && ffCharIsDigit(start[1])) {
|
||||||
|
++start;
|
||||||
|
--length;
|
||||||
|
}
|
||||||
|
if (length == 0 || (!ffCharIsDigit(start[0]) && !(start[0] == 'R' && length > 1 && ffCharIsDigit(start[1]))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ffStrbufSetNS(version, length, start);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* core = nullptr;
|
||||||
|
if (ffStrStartsWith(p, "version")) {
|
||||||
|
// ksh93 self-doc: version sh (AT&T [Labs] Research) ...
|
||||||
|
const char* selfDoc = strstr(p, " sh (");
|
||||||
|
const char* end = selfDoc ? strchr(selfDoc, ')') : nullptr;
|
||||||
|
if (!end)
|
||||||
|
continue;
|
||||||
|
core = end + 1;
|
||||||
|
} else if (ffStrStartsWith(p, "Version ")) {
|
||||||
|
// $KSH_VERSION / ${.sh.version}: Version <features> <version> <date>
|
||||||
|
core = p + strlen("Version ");
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*core && isspace((unsigned char) *core))
|
||||||
|
++core;
|
||||||
|
|
||||||
|
const char* token = core;
|
||||||
|
while (*token) {
|
||||||
|
while (*token && isspace((unsigned char) *token))
|
||||||
|
++token;
|
||||||
|
if (!*token)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const char* end = token;
|
||||||
|
while (*end && !isspace((unsigned char) *end))
|
||||||
|
++end;
|
||||||
|
uint32_t length = (uint32_t) (end - token);
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
if (length >= 2 && token[0] == '9' && token[1] == '3') {
|
||||||
|
valid = true;
|
||||||
|
for (uint32_t i = 2; i < length; ++i) {
|
||||||
|
char c = token[i];
|
||||||
|
if (!(ffCharIsDigit(c) || ffCharIsEnglishAlphabet(c) || c == '+' || c == '.' || c == '_' || c == '/' || c == '-')) {
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (length >= 5 && token[0] == 'M' && token[1] == '-') {
|
||||||
|
for (uint32_t i = 2; i + 2 < length; ++i) {
|
||||||
|
if (token[i] == '/' && token[i + 1] == '9' && token[i + 2] == '3') {
|
||||||
|
valid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (length > 0 && ffCharIsDigit(token[0]) && (memchr(token, '.', length) || memchr(token, '-', length))) {
|
||||||
|
valid = true;
|
||||||
|
} else if (length > 1 && token[0] == 'v' && ffCharIsDigit(token[1])) {
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
uint32_t resultLength = length;
|
||||||
|
bool date = length >= 10 &&
|
||||||
|
ffCharIsDigit(token[0]) && ffCharIsDigit(token[1]) &&
|
||||||
|
ffCharIsDigit(token[2]) && ffCharIsDigit(token[3]) && token[4] == '-' &&
|
||||||
|
ffCharIsDigit(token[5]) && ffCharIsDigit(token[6]) && token[7] == '-' &&
|
||||||
|
ffCharIsDigit(token[8]) && ffCharIsDigit(token[9]);
|
||||||
|
if (date) {
|
||||||
|
const char* next = end;
|
||||||
|
while (*next && isspace((unsigned char) *next))
|
||||||
|
++next;
|
||||||
|
const char* nextEnd = next;
|
||||||
|
while (*nextEnd && !isspace((unsigned char) *nextEnd))
|
||||||
|
++nextEnd;
|
||||||
|
uint32_t nextLength = (uint32_t) (nextEnd - next);
|
||||||
|
if (nextLength > 0 && nextLength <= 2) {
|
||||||
|
bool suffix = true;
|
||||||
|
for (uint32_t i = 0; i < nextLength; ++i) {
|
||||||
|
if (!ffCharIsEnglishAlphabet(next[i]) && next[i] != '+') {
|
||||||
|
suffix = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (suffix)
|
||||||
|
resultLength = (uint32_t) (nextEnd - token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* start = token;
|
||||||
|
if (resultLength > 1 && start[0] == 'v' && ffCharIsDigit(start[1])) {
|
||||||
|
++start;
|
||||||
|
--resultLength;
|
||||||
|
}
|
||||||
|
ffStrbufSetNS(version, resultLength, start);
|
||||||
|
return version->length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ffStrbufClear(version);
|
ffStrbufClear(version);
|
||||||
if (ffProcessAppendStdOut(version, (char* const[]) { exe->chars, "-c", "echo $KSH_VERSION", nullptr }) == nullptr && ffStrbufSubstrAfterFirstS(version, " KSH ")) {
|
|
||||||
// OKSH: @(#)PD KSH v5.2.14 99/07/13.2
|
|
||||||
// MKSH: @(#)MIRBSD KSH R59 2025/04/26 +Debian
|
|
||||||
// $OKSH_VERSION doesn't exist on OpenBSD
|
|
||||||
ffStrbufSubstrBeforeFirstC(version, ' ');
|
|
||||||
ffStrbufTrimLeft(version, 'v');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +423,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
|
|||||||
if (ffStrEqualsIgnCase(exeName, "nu")) {
|
if (ffStrEqualsIgnCase(exeName, "nu")) {
|
||||||
return getShellVersionNushell(exe, version);
|
return getShellVersionNushell(exe, version);
|
||||||
}
|
}
|
||||||
if (ffStrEqualsIgnCase(exeName, "ksh") || ffStrEqualsIgnCase(exeName, "mksh")) {
|
if (ffStrEqualsIgnCase(exeName, "ksh") || ffStrEqualsIgnCase(exeName, "ksh93") || ffStrEqualsIgnCase(exeName, "mksh") || ffStrEqualsIgnCase(exeName, "pdksh")) {
|
||||||
return getShellVersionKsh(exe, version);
|
return getShellVersionKsh(exe, version);
|
||||||
}
|
}
|
||||||
if (ffStrEqualsIgnCase(exeName, "oksh")) {
|
if (ffStrEqualsIgnCase(exeName, "oksh")) {
|
||||||
|
|||||||
@@ -91,7 +91,9 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) {
|
|||||||
ffStrbufEqualS(&result->processName, "bash") ||
|
ffStrbufEqualS(&result->processName, "bash") ||
|
||||||
ffStrbufEqualS(&result->processName, "zsh") ||
|
ffStrbufEqualS(&result->processName, "zsh") ||
|
||||||
ffStrbufEqualS(&result->processName, "ksh") ||
|
ffStrbufEqualS(&result->processName, "ksh") ||
|
||||||
|
ffStrbufEqualS(&result->processName, "ksh93") ||
|
||||||
ffStrbufEqualS(&result->processName, "mksh") ||
|
ffStrbufEqualS(&result->processName, "mksh") ||
|
||||||
|
ffStrbufEqualS(&result->processName, "pdksh") ||
|
||||||
ffStrbufEqualS(&result->processName, "oksh") ||
|
ffStrbufEqualS(&result->processName, "oksh") ||
|
||||||
ffStrbufEqualS(&result->processName, "csh") ||
|
ffStrbufEqualS(&result->processName, "csh") ||
|
||||||
ffStrbufEqualS(&result->processName, "tcsh") ||
|
ffStrbufEqualS(&result->processName, "tcsh") ||
|
||||||
|
|||||||
Reference in New Issue
Block a user