mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-29 19:20:43 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 06957877a8 | |||
| 2f68ce7f74 | |||
| 408646df1c | |||
| ad62e3d1f5 |
@@ -2,6 +2,7 @@
|
||||
|
||||
Bugfixes:
|
||||
* Improved uptime detection on SunOS via kstat. (#2674, Uptime, SunOS)
|
||||
* Fixed substring formatting returning the remaining string when a negative end index is before the start of the string. (General)
|
||||
|
||||
# 2.70.0
|
||||
|
||||
|
||||
@@ -552,7 +552,7 @@ static bool parseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint3
|
||||
if (end < 0) {
|
||||
end = (int32_t) tempString.length + end;
|
||||
}
|
||||
if ((uint32_t) end > tempString.length) {
|
||||
if (end >= 0 && (uint32_t) end > tempString.length) {
|
||||
end = (int32_t) tempString.length;
|
||||
}
|
||||
if (end > start) {
|
||||
|
||||
+36
-21
@@ -149,6 +149,32 @@ void restoreTerm(void) {
|
||||
tcsetattr(ftty, TCSAFLUSH, &oldTerm);
|
||||
}
|
||||
|
||||
static const char* waitForTerminalResponse(void) {
|
||||
#ifndef __APPLE__
|
||||
const int pollResult = poll(&(struct pollfd) { .fd = ftty, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS);
|
||||
if (pollResult <= 0) {
|
||||
FF_DEBUG("poll(/dev/tty) returned %d after %d ms: %s",
|
||||
pollResult, FF_IO_TERM_RESP_WAIT_MS, pollResult == 0 ? "timed out" : strerror(errno));
|
||||
return "poll(/dev/tty) timeout or failed";
|
||||
}
|
||||
#else
|
||||
{
|
||||
// On macOS, poll(/dev/tty) always returns immediately
|
||||
// See also https://nathancraddock.com/blog/macos-dev-tty-polling/
|
||||
fd_set rd;
|
||||
FD_ZERO(&rd);
|
||||
FD_SET(ftty, &rd);
|
||||
const int selectResult = select(ftty + 1, &rd, nullptr, nullptr, &(struct timeval) { .tv_sec = FF_IO_TERM_RESP_WAIT_MS / 1000, .tv_usec = (FF_IO_TERM_RESP_WAIT_MS % 1000) * 1000 });
|
||||
if (selectResult <= 0) {
|
||||
FF_DEBUG("select(/dev/tty) returned %d after %d ms: %s",
|
||||
selectResult, FF_IO_TERM_RESP_WAIT_MS, selectResult == 0 ? "timed out" : strerror(errno));
|
||||
return "select(/dev/tty) timeout or failed";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...) {
|
||||
if (ftty < 0) {
|
||||
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
@@ -174,28 +200,10 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
|
||||
ffWriteFDData(ftty, strlen(request), request);
|
||||
|
||||
// Give the terminal some time to respond
|
||||
#ifndef __APPLE__
|
||||
const int pollResult = poll(&(struct pollfd) { .fd = ftty, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS);
|
||||
if (pollResult <= 0) {
|
||||
FF_DEBUG("poll(/dev/tty) returned %d after %d ms: %s",
|
||||
pollResult, FF_IO_TERM_RESP_WAIT_MS, pollResult == 0 ? "timed out" : strerror(errno));
|
||||
return "poll(/dev/tty) timeout or failed";
|
||||
const char* error = waitForTerminalResponse();
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
#else
|
||||
{
|
||||
// On macOS, poll(/dev/tty) always returns immediately
|
||||
// See also https://nathancraddock.com/blog/macos-dev-tty-polling/
|
||||
fd_set rd;
|
||||
FD_ZERO(&rd);
|
||||
FD_SET(ftty, &rd);
|
||||
const int selectResult = select(ftty + 1, &rd, nullptr, nullptr, &(struct timeval) { .tv_sec = FF_IO_TERM_RESP_WAIT_MS / 1000, .tv_usec = (FF_IO_TERM_RESP_WAIT_MS % 1000) * 1000 });
|
||||
if (selectResult <= 0) {
|
||||
FF_DEBUG("select(/dev/tty) returned %d after %d ms: %s",
|
||||
selectResult, FF_IO_TERM_RESP_WAIT_MS, selectResult == 0 ? "timed out" : strerror(errno));
|
||||
return "select(/dev/tty) timeout or failed";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
char buffer[1024];
|
||||
size_t bytesRead = 0;
|
||||
@@ -204,6 +212,13 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
|
||||
va_start(args, format);
|
||||
|
||||
while (true) {
|
||||
// The response may arrive in several chunks; a terminal that sends an incomplete
|
||||
// response would otherwise block `read` forever
|
||||
if (bytesRead > 0 && (error = waitForTerminalResponse())) {
|
||||
va_end(args);
|
||||
return error;
|
||||
}
|
||||
|
||||
ssize_t nRead = read(ftty, buffer + bytesRead, sizeof(buffer) - bytesRead - 1);
|
||||
|
||||
if (nRead <= 0) {
|
||||
|
||||
@@ -414,6 +414,35 @@ void ffListFilesRecursively(const char* path, bool pretty) {
|
||||
listFilesRecursively(folder.length, &folder, 0, nullptr, pretty);
|
||||
}
|
||||
|
||||
static const char* waitForTerminalResponse(HANDLE hInput) {
|
||||
while (true) {
|
||||
NTSTATUS status = NtWaitForSingleObject(hInput, FALSE, &(LARGE_INTEGER) { .QuadPart = (int64_t) FF_IO_TERM_RESP_WAIT_MS * -10000 });
|
||||
if (status != STATUS_WAIT_0) {
|
||||
FF_DEBUG("NtWaitForSingleObject() failed or timeout: %s", ffDebugNtStatus(status));
|
||||
return "NtWaitForSingleObject() failed or timeout";
|
||||
}
|
||||
|
||||
// Ignore all unexpected input events
|
||||
INPUT_RECORD record;
|
||||
DWORD len = 0;
|
||||
if (!PeekConsoleInputW(hInput, &record, 1, &len)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Key-up events carry no input for `ReadFile`; leaving one in the buffer would make the
|
||||
// wait return while the next `ReadFile` still blocks
|
||||
if (
|
||||
record.EventType == KEY_EVENT &&
|
||||
record.Event.KeyEvent.bKeyDown &&
|
||||
record.Event.KeyEvent.uChar.UnicodeChar != L'\r' &&
|
||||
record.Event.KeyEvent.uChar.UnicodeChar != L'\n') {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReadConsoleInputW(hInput, &record, 1, &len);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...) {
|
||||
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
FF_AUTO_CLOSE_FD HANDLE hConin = INVALID_HANDLE_VALUE;
|
||||
@@ -440,29 +469,10 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
|
||||
WriteFile(hOutput, request, (DWORD) strlen(request), &bytes, nullptr);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
NTSTATUS status = NtWaitForSingleObject(hInput, FALSE, &(LARGE_INTEGER) { .QuadPart = (int64_t) FF_IO_TERM_RESP_WAIT_MS * -10000 });
|
||||
if (status != STATUS_WAIT_0) {
|
||||
FF_DEBUG("NtWaitForSingleObject() failed or timeout: %s", ffDebugNtStatus(status));
|
||||
SetConsoleMode(hInput, inputMode);
|
||||
return "NtWaitForSingleObject() failed or timeout";
|
||||
}
|
||||
|
||||
// Ignore all unexpected input events
|
||||
INPUT_RECORD record;
|
||||
DWORD len = 0;
|
||||
if (!PeekConsoleInputW(hInput, &record, 1, &len)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
record.EventType == KEY_EVENT &&
|
||||
record.Event.KeyEvent.uChar.UnicodeChar != L'\r' &&
|
||||
record.Event.KeyEvent.uChar.UnicodeChar != L'\n') {
|
||||
break;
|
||||
} else {
|
||||
ReadConsoleInputW(hInput, &record, 1, &len);
|
||||
}
|
||||
const char* error = waitForTerminalResponse(hInput);
|
||||
if (error) {
|
||||
SetConsoleMode(hInput, inputMode);
|
||||
return error;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
@@ -472,6 +482,16 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
|
||||
uint32_t bytesRead = 0;
|
||||
|
||||
while (true) {
|
||||
// The response may arrive in several chunks; a terminal that sends an incomplete
|
||||
// response would otherwise block `ReadFile` forever
|
||||
if (bytesRead > 0 && (error = waitForTerminalResponse(hInput))) {
|
||||
va_end(args);
|
||||
if (hasInputMode) {
|
||||
SetConsoleMode(hInput, inputMode);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
DWORD bytes = 0;
|
||||
BOOL readOk = ReadFile(hInput, buffer + bytesRead, (DWORD) (sizeof(buffer) - 1 - bytesRead), &bytes, nullptr);
|
||||
if (!readOk || bytes == 0) {
|
||||
|
||||
@@ -52,15 +52,15 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
|
||||
if (inf.ssid) { // https://developer.apple.com/forums/thread/732431
|
||||
ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String);
|
||||
} else if (networkProfile.ssid) {
|
||||
ffStrbufSetStatic(&item->conn.ssid, inf.configuration.networkProfiles.firstObject.ssid.UTF8String);
|
||||
} else if (networkProfile.ssid) { // Dead in macOS 27.2
|
||||
ffStrbufSetStatic(&item->conn.ssid, networkProfile.ssid.UTF8String);
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.ssid, "<redacted>"); // https://developer.apple.com/forums/thread/732431
|
||||
ffStrbufSetStatic(&item->conn.ssid, "<redacted>");
|
||||
}
|
||||
|
||||
if (inf.bssid) {
|
||||
ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String);
|
||||
} else if (networkProfile.bssidList) {
|
||||
} else if (networkProfile.bssidList) { // Dead in macOS 27.2
|
||||
ffStrbufSetStatic(&item->conn.bssid, [networkProfile.bssidList.firstObject[@"BSSID"] UTF8String]);
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.bssid, "<redacted>");
|
||||
|
||||
@@ -96,6 +96,7 @@ int main(void) {
|
||||
VERIFY("output({1~10,10})", "12345 67890", "output()");
|
||||
VERIFY("output({1~10,5})", "12345 67890", "output()");
|
||||
VERIFY("output({1~3,-3})", "12345 67890", "output(45 67)");
|
||||
VERIFY("output({1~0,-12})", "12345 67890", "output()");
|
||||
VERIFY("output({1~-5,-3})", "12345 67890", "output(67)");
|
||||
VERIFY("output({1~-0,10})", "12345 67890", "output(12345 6789)");
|
||||
VERIFY("output({1~-3,-5})", "12345 67890", "output()");
|
||||
|
||||
Reference in New Issue
Block a user