mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-06 05:04:17 +01:00
Users: add more detailed information
This commit is contained in:
@@ -12,6 +12,8 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
ffStrbufAppendF(buffer, "%i", *(int*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT)
|
||||
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT64)
|
||||
ffStrbufAppendF(buffer, "%" PRIu64, *(uint64_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
|
||||
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
|
||||
|
||||
@@ -7,6 +7,7 @@ typedef enum FFformatargtype
|
||||
{
|
||||
FF_FORMAT_ARG_TYPE_NULL = 0,
|
||||
FF_FORMAT_ARG_TYPE_UINT,
|
||||
FF_FORMAT_ARG_TYPE_UINT64,
|
||||
FF_FORMAT_ARG_TYPE_UINT16,
|
||||
FF_FORMAT_ARG_TYPE_UINT8,
|
||||
FF_FORMAT_ARG_TYPE_INT,
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffDetectUsers(FFlist* users /* List of FFstrbuf */, FFstrbuf* error);
|
||||
typedef struct FFUserResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf hostname;
|
||||
FFstrbuf clientIp;
|
||||
FFstrbuf tty;
|
||||
uint64_t loginTime; // ms
|
||||
} FFUserResult;
|
||||
|
||||
const char* ffDetectUsers(FFlist* users);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define getutxent getutent
|
||||
#endif
|
||||
|
||||
void ffDetectUsers(FFlist* users, FFstrbuf* error)
|
||||
const char* ffDetectUsers(FFlist* users)
|
||||
{
|
||||
struct utmpx* n = NULL;
|
||||
setutxent();
|
||||
@@ -22,15 +22,25 @@ next:
|
||||
if(n->ut_type != USER_PROCESS)
|
||||
continue;
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, user, *users)
|
||||
FF_LIST_FOR_EACH(FFUserResult, user, *users)
|
||||
{
|
||||
if(ffStrbufEqualS(user, n->ut_user))
|
||||
if(ffStrbufEqualS(&user->name, n->ut_user))
|
||||
goto next;
|
||||
}
|
||||
|
||||
ffStrbufInitS((FFstrbuf*)ffListAdd(users), n->ut_user);
|
||||
FFUserResult* user = (FFUserResult*) ffListAdd(users);
|
||||
ffStrbufInitS(&user->name, n->ut_user);
|
||||
ffStrbufInitS(&user->hostname, n->ut_host);
|
||||
ffStrbufInitS(&user->tty, n->ut_line);
|
||||
#ifdef __linux__
|
||||
if(n->ut_addr_v6[0] || n->ut_addr_v6[1] || n->ut_addr_v6[2] || n->ut_addr_v6[3])
|
||||
ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", n->ut_addr_v6[0], n->ut_addr_v6[1], n->ut_addr_v6[2], n->ut_addr_v6[3]);
|
||||
else
|
||||
#else
|
||||
ffStrbufInit(&user->clientIp);
|
||||
#endif
|
||||
user->loginTime = (uint64_t) n->ut_tv.tv_sec * 1000 + (uint64_t) n->ut_tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
if(users->length == 0)
|
||||
ffStrbufAppendS(error, "Unable to detect users");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -4,17 +4,20 @@
|
||||
#include <windows.h>
|
||||
#include <wtsapi32.h>
|
||||
|
||||
void ffDetectUsers(FFlist* users, FFstrbuf* error)
|
||||
static uint64_t to_ms(uint64_t ret)
|
||||
{
|
||||
ret -= 116444736000000000ull;
|
||||
return ret / 10000ull;
|
||||
}
|
||||
|
||||
const char* ffDetectUsers(FFlist* users)
|
||||
{
|
||||
WTS_SESSION_INFO_1W* sessionInfo;
|
||||
DWORD sessionCount;
|
||||
DWORD level = 1;
|
||||
|
||||
if(!WTSEnumerateSessionsExW(WTS_CURRENT_SERVER_HANDLE, &level, 0, &sessionInfo, &sessionCount))
|
||||
{
|
||||
ffStrbufAppendS(error, "WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE) failed");
|
||||
return;
|
||||
}
|
||||
return "WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE) failed";
|
||||
|
||||
for (DWORD i = 0; i < sessionCount; i++)
|
||||
{
|
||||
@@ -22,14 +25,33 @@ void ffDetectUsers(FFlist* users, FFstrbuf* error)
|
||||
if(session->State != WTSActive)
|
||||
continue;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY domainName = ffStrbufCreateWS(session->pDomainName);
|
||||
FF_STRBUF_AUTO_DESTROY userName = ffStrbufCreateWS(session->pUserName);
|
||||
FFUserResult* user = (FFUserResult*) ffListAdd(users);
|
||||
ffStrbufInitWS(&user->name, session->pUserName);
|
||||
ffStrbufInitWS(&user->hostname, session->pHostName);
|
||||
|
||||
ffStrbufInitF((FFstrbuf*)ffListAdd(users), "%s\\%s", domainName.chars, userName.chars);
|
||||
DWORD bytes = 0;
|
||||
PWTS_CLIENT_ADDRESS address = NULL;
|
||||
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSClientAddress, (LPWSTR *) &address, &bytes))
|
||||
{
|
||||
if (address->AddressFamily == 2 /*AF_INET*/)
|
||||
ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", address->Address[2], address->Address[3], address->Address[4], address->Address[5]);
|
||||
WTSFreeMemory(address);
|
||||
}
|
||||
else
|
||||
ffStrbufInitS(&user->clientIp, "0.0.0.0");
|
||||
|
||||
bytes = 0;
|
||||
PWTSINFOW wtsInfo = NULL;
|
||||
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSSessionInfo, (LPWSTR *) &wtsInfo, &bytes))
|
||||
{
|
||||
user->loginTime = to_ms(*(uint64_t*) &wtsInfo->LogonTime);
|
||||
WTSFreeMemory(wtsInfo);
|
||||
}
|
||||
else
|
||||
user->loginTime = 0;
|
||||
}
|
||||
|
||||
WTSFreeMemoryExW(WTSTypeSessionInfoLevel1, sessionInfo, 1);
|
||||
|
||||
if(users->length == 0)
|
||||
ffStrbufAppendS(error, "Unable to detect users");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -8,4 +8,6 @@ typedef struct FFUsersOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
bool compact;
|
||||
} FFUsersOptions;
|
||||
|
||||
+80
-18
@@ -4,42 +4,90 @@
|
||||
#include "modules/users/users.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define FF_USERS_NUM_FORMAT_ARGS 1
|
||||
|
||||
void ffPrintUsers(FFUsersOptions* options)
|
||||
{
|
||||
FF_LIST_AUTO_DESTROY users = ffListCreate(sizeof(FFstrbuf));
|
||||
FF_LIST_AUTO_DESTROY users = ffListCreate(sizeof(FFUserResult));
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY error = ffStrbufCreate();
|
||||
const char* error = ffDetectUsers(&users);
|
||||
|
||||
ffDetectUsers(&users, &error);
|
||||
|
||||
if(error.length > 0)
|
||||
if(error)
|
||||
{
|
||||
ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "%*s", error.length, error.chars);
|
||||
ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "%s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
|
||||
for(uint32_t i = 0; i < users.length; ++i)
|
||||
if(users.length == 0)
|
||||
{
|
||||
if(i > 0)
|
||||
ffStrbufAppendS(&result, ", ");
|
||||
FFstrbuf* user = (FFstrbuf*)ffListGet(&users, i);
|
||||
ffStrbufAppend(&result, user);
|
||||
ffStrbufDestroy(user);
|
||||
ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "%s", "Unable to detect any users");
|
||||
return;
|
||||
}
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
puts(result.chars);
|
||||
if(options->compact)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
|
||||
for(uint32_t i = 0; i < users.length; ++i)
|
||||
{
|
||||
if(i > 0)
|
||||
ffStrbufAppendS(&result, ", ");
|
||||
FFUserResult* user = (FFUserResult*)ffListGet(&users, i);
|
||||
ffStrbufAppend(&result, &user->name);
|
||||
}
|
||||
ffStrbufPutTo(&result, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t i = 0; i < users.length; ++i)
|
||||
{
|
||||
FFUserResult* user = (FFUserResult*)ffListGet(&users, i);
|
||||
|
||||
ffPrintLogoAndKey(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateCopy(&user->name);
|
||||
if(user->hostname.length)
|
||||
ffStrbufAppendF(&result, "@%s", user->hostname.chars);
|
||||
|
||||
if(user->loginTime)
|
||||
{
|
||||
char buf[64];
|
||||
time_t time = (time_t) (user->loginTime / 1000);
|
||||
strftime(buf, sizeof(buf), "%FT%T%z", localtime(&time));
|
||||
ffStrbufAppendF(&result, " - login time %s", buf);
|
||||
}
|
||||
|
||||
ffStrbufPutTo(&result, stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result},
|
||||
});
|
||||
for(uint32_t i = 0; i < users.length; ++i)
|
||||
{
|
||||
FFUserResult* user = (FFUserResult*)ffListGet(&users, i);
|
||||
|
||||
ffPrintFormat(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &user->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &user->hostname},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &user->tty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &user->clientIp},
|
||||
{FF_FORMAT_ARG_TYPE_UINT64, &user->loginTime},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFUserResult, user, users)
|
||||
{
|
||||
ffStrbufDestroy(&user->clientIp);
|
||||
ffStrbufDestroy(&user->hostname);
|
||||
ffStrbufDestroy(&user->tty);
|
||||
ffStrbufDestroy(&user->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +95,8 @@ void ffInitUsersOptions(FFUsersOptions* options)
|
||||
{
|
||||
ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, NULL);
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
|
||||
options->compact = true;
|
||||
}
|
||||
|
||||
bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const char* value)
|
||||
@@ -56,6 +106,12 @@ bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const
|
||||
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
|
||||
return true;
|
||||
|
||||
if(ffStrEqualsIgnCase(subKey, "compact"))
|
||||
{
|
||||
options->compact = ffOptionParseBoolean(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -77,6 +133,12 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module)
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
continue;
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "compact"))
|
||||
{
|
||||
options->compact = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source);
|
||||
|
||||
static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source)
|
||||
{
|
||||
if (!source) return ffStrbufClear(result);
|
||||
return ffStrbufSetNWS(result, (uint32_t)wcslen(source), source);
|
||||
}
|
||||
|
||||
@@ -17,6 +18,7 @@ void ffStrbufInitNWS(FFstrbuf* result, uint32_t length, const wchar_t* source);
|
||||
|
||||
static inline void ffStrbufInitWS(FFstrbuf* result, const wchar_t* source)
|
||||
{
|
||||
if (!source) return ffStrbufInit(result);
|
||||
return ffStrbufInitNWS(result, (uint32_t)wcslen(source), source);
|
||||
}
|
||||
|
||||
@@ -29,6 +31,7 @@ static inline FFstrbuf ffStrbufCreateNWS(uint32_t length, const wchar_t* source)
|
||||
|
||||
static inline FFstrbuf ffStrbufCreateWS(const wchar_t* source)
|
||||
{
|
||||
if (!source) return ffStrbufCreate();
|
||||
return ffStrbufCreateNWS((uint32_t)wcslen(source), source);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user