blob: 186a043136cea0da6ad70692e8f6f25374ec4192 [file] [log] [blame] [raw]
/*
htop - UsersMeter.c
(C) 2004-2011 Hisham H. Muhammad
Copyright 2015-2023 Rivoreo
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
/*{
#include "Meter.h"
}*/
#include "config.h"
#ifdef HAVE_UTMPX
#include "UsersMeter.h"
#include "CRT.h"
#include "XAlloc.h"
#include "StringUtils.h"
#include <utmpx.h>
#include <string.h>
int UsersMeter_attributes[] = {
HTOP_SESSIONS_COLOR, HTOP_USERS_COLOR
};
static void UsersMeter_updateValues(Meter *this, char *buffer, int len) {
int session_count = 0;
int user_count = 0;
struct {
char *name;
size_t len;
} *user_names = NULL;
const struct utmpx *utx;
setutxent();
while ((utx = getutxent())) {
if(utx->ut_type != USER_PROCESS) continue;
session_count++;
size_t len = strnlen(utx->ut_user, sizeof utx->ut_user);
int i = user_count;
do {
if(--i < 0) {
user_names = xRealloc(user_names, (user_count + 1) * sizeof *user_names);
user_names[user_count].len = len;
user_names[user_count].name = xMalloc(len);
memcpy(user_names[user_count].name, utx->ut_user, len);
user_count++;
break;
}
} while(len != user_names[i].len || memcmp(utx->ut_user, user_names[i].name, len));
}
endutxent();
for(int i = 0; i < user_count; i++) free(user_names[i].name);
free(user_names);
xSnprintf(buffer, len, "%d/%d", session_count, user_count);
this->values[0] = session_count;
this->values[1] = user_count;
}
static void UsersMeter_display(Object *super, RichString *out) {
Meter *this = (Meter *)super;
char buffer[20];
int session_count = this->values[0];
int user_count = this->values[1];
RichString_write(out, CRT_colors[HTOP_METER_TEXT_COLOR], ": ");
xSnprintf(buffer, sizeof buffer, "%d", session_count);
RichString_append(out, CRT_colors[HTOP_SESSIONS_COLOR], buffer);
RichString_append(out, CRT_colors[HTOP_METER_TEXT_COLOR], session_count == 1 ? " session, " : " sessions, ");
xSnprintf(buffer, sizeof buffer, "%d", user_count);
RichString_append(out, CRT_colors[HTOP_USERS_COLOR], buffer);
RichString_append(out, CRT_colors[HTOP_METER_TEXT_COLOR], user_count == 1 ? " user" : " users");
}
static double UsersMeter_getMaximum(Meter *this) {
double v = this->values[0];
double r = 64;
while(v > 64) {
v /= 2;
r *= 2;
}
return r;
}
MeterClass UsersMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = UsersMeter_display,
},
.updateValues = UsersMeter_updateValues,
.getMaximum = UsersMeter_getMaximum,
.defaultMode = TEXT_METERMODE,
.maxItems = 2,
.total = 64,
.attributes = UsersMeter_attributes,
.values_are_overlapped = true,
.name = "Users",
.uiName = "User session counter",
.caption = "Usr"
};
#endif