diff --git a/doc/json_schema.json b/doc/json_schema.json index 3533c651f..fcfd1eeeb 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -903,10 +903,6 @@ "const": "uptime", "description": "Print how long system has been running" }, - { - "const": "users", - "description": "Print users currently logged in" - }, { "const": "version", "description": "Print Fastfetch version" @@ -1999,6 +1995,42 @@ } } }, + { + "title": "Users", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "const": "users", + "description": "Print users currently logged in" + }, + "compact": { + "type": "boolean", + "description": "Show all active users in one line", + "default": false + }, + "myselfOnly": { + "type": "boolean", + "description": "Show only the current user", + "default": false + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + } + }, { "title": "Weather", "type": "object", diff --git a/src/data/help.json b/src/data/help.json index cbecc9032..8fe01ff0f 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1450,6 +1450,24 @@ "default": false } }, + { + "long": "users-compact", + "desc": "Show all active users in one line", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, + { + "long": "users-myself-only", + "desc": "Show only current user", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "player-name", "desc": "The name of the player to use for module Media and Player", diff --git a/src/detection/users/users.h b/src/detection/users/users.h index 67be7f1fd..e29a1858d 100644 --- a/src/detection/users/users.h +++ b/src/detection/users/users.h @@ -11,4 +11,4 @@ typedef struct FFUserResult uint64_t loginTime; // ms } FFUserResult; -const char* ffDetectUsers(FFlist* users); +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users); diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index 695a6a724..86e69dbe4 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -15,15 +15,18 @@ #include #endif -const char* ffDetectUsers(FFlist* users) +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users) { struct utmpx* n = NULL; setutxent(); next: - while((n = getutxent())) + while ((n = getutxent())) { - if(n->ut_type != USER_PROCESS) + if (n->ut_type != USER_PROCESS) + continue; + + if (options->myselfOnly && !ffStrbufEqualS(&instance.state.platform.userName, n->ut_user)) continue; FF_LIST_FOR_EACH(FFUserResult, user, *users) diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index 115f7935d..b7bdf2721 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -10,23 +10,28 @@ static inline uint64_t to_ms(uint64_t ret) return ret / 10000ull; } -const char* ffDetectUsers(FFlist* users) +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users) { WTS_SESSION_INFO_1W* sessionInfo; DWORD sessionCount; DWORD level = 1; - if(!WTSEnumerateSessionsExW(WTS_CURRENT_SERVER_HANDLE, &level, 0, &sessionInfo, &sessionCount)) + if (!WTSEnumerateSessionsExW(WTS_CURRENT_SERVER_HANDLE, &level, 0, &sessionInfo, &sessionCount)) return "WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE) failed"; for (DWORD i = 0; i < sessionCount; i++) { WTS_SESSION_INFO_1W* session = &sessionInfo[i]; - if(session->State != WTSActive) + if (session->State != WTSActive) + continue; + + FF_STRBUF_AUTO_DESTROY userName = ffStrbufCreateWS(session->pUserName); + + if (options->myselfOnly && !ffStrbufEqual(&instance.state.platform.userName, &userName)) continue; FFUserResult* user = (FFUserResult*) ffListAdd(users); - ffStrbufInitWS(&user->name, session->pUserName); + ffStrbufInitMove(&user->name, &userName); ffStrbufInitWS(&user->hostName, session->pHostName); ffStrbufInitWS(&user->sessionName, session->pSessionName); ffStrbufInit(&user->clientIp); diff --git a/src/modules/users/option.h b/src/modules/users/option.h index 6883e8dd0..af194fea2 100644 --- a/src/modules/users/option.h +++ b/src/modules/users/option.h @@ -10,4 +10,5 @@ typedef struct FFUsersOptions FFModuleArgs moduleArgs; bool compact; + bool myselfOnly; } FFUsersOptions; diff --git a/src/modules/users/users.c b/src/modules/users/users.c index 3e81d7a24..57349db0c 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -13,7 +13,7 @@ void ffPrintUsers(FFUsersOptions* options) { FF_LIST_AUTO_DESTROY users = ffListCreate(sizeof(FFUserResult)); - const char* error = ffDetectUsers(&users); + const char* error = ffDetectUsers(options, &users); if(error) { @@ -94,12 +94,18 @@ bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; - if(ffStrEqualsIgnCase(subKey, "compact")) + if (ffStrEqualsIgnCase(subKey, "compact")) { options->compact = ffOptionParseBoolean(value); return true; } + if (ffStrEqualsIgnCase(subKey, "myself-only")) + { + options->myselfOnly = ffOptionParseBoolean(value); + return true; + } + return false; } @@ -110,7 +116,7 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) yyjson_obj_foreach(module, idx, max, key_, val) { const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type")) + if (ffStrEqualsIgnCase(key, "type")) continue; if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) @@ -122,6 +128,12 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "myselfOnly")) + { + options->myselfOnly = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); } } @@ -137,11 +149,11 @@ void ffGenerateUsersJsonConfig(FFUsersOptions* options, yyjson_mut_doc* doc, yyj yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); } -void ffGenerateUsersJsonResult(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateUsersJsonResult(FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFUserResult)); - const char* error = ffDetectUsers(&results); + const char* error = ffDetectUsers(options, &results); if(error) { @@ -200,6 +212,7 @@ void ffInitUsersOptions(FFUsersOptions* options) ffOptionInitModuleArg(&options->moduleArgs); options->compact = false; + options->myselfOnly = false; } void ffDestroyUsersOptions(FFUsersOptions* options)