top hotplug memory support
Another patch from Jim for top to support hot-pluggable memory. Not fully tested on real hot-pluggable memory because neither of us have it
This commit is contained in:
parent
29b8775c39
commit
a26c3bfa39
@ -13,7 +13,7 @@ global:
|
|||||||
Hertz; smp_num_cpus; have_privs; getbtime;
|
Hertz; smp_num_cpus; have_privs; getbtime;
|
||||||
sprint_uptime; uptime; user_from_uid; print_uptime; loadavg;
|
sprint_uptime; uptime; user_from_uid; print_uptime; loadavg;
|
||||||
pretty_print_signals; print_given_signals; unix_print_signals; signal_name_to_number; signal_number_to_name;
|
pretty_print_signals; print_given_signals; unix_print_signals; signal_name_to_number; signal_number_to_name;
|
||||||
meminfo; vminfo; getstat; getdiskstat; getpartitions_num; getslabinfo; get_pid_digits;
|
cpuinfo; meminfo; vminfo; getstat; getdiskstat; getpartitions_num; getslabinfo; get_pid_digits;
|
||||||
kb_active; kb_inactive; kb_main_buffers; kb_main_cached;
|
kb_active; kb_inactive; kb_main_buffers; kb_main_cached;
|
||||||
kb_main_free; kb_main_total; kb_main_used; kb_swap_free;
|
kb_main_free; kb_main_total; kb_main_used; kb_swap_free;
|
||||||
kb_swap_total; kb_swap_used; kb_main_shared;
|
kb_swap_total; kb_swap_used; kb_main_shared;
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
#include <netinet/in.h> /* htons */
|
#include <netinet/in.h> /* htons */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OOMEM_ENABLE
|
|
||||||
long smp_num_cpus; /* number of CPUs */
|
long smp_num_cpus; /* number of CPUs */
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BAD_OPEN_MESSAGE \
|
#define BAD_OPEN_MESSAGE \
|
||||||
"Error: /proc must be mounted\n" \
|
"Error: /proc must be mounted\n" \
|
||||||
@ -182,11 +180,7 @@ static void old_Hertz_hack(void){
|
|||||||
setlocale(LC_NUMERIC, savelocale);
|
setlocale(LC_NUMERIC, savelocale);
|
||||||
jiffies = user_j + nice_j + sys_j + other_j;
|
jiffies = user_j + nice_j + sys_j + other_j;
|
||||||
seconds = (up_1 + up_2) / 2;
|
seconds = (up_1 + up_2) / 2;
|
||||||
#ifndef OOMEM_ENABLE
|
|
||||||
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
|
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
|
||||||
#else
|
|
||||||
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus() );
|
|
||||||
#endif
|
|
||||||
/* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
|
/* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
|
||||||
switch(h){
|
switch(h){
|
||||||
case 9 ... 11 : Hertz = 10; break; /* S/390 (sometimes) */
|
case 9 ... 11 : Hertz = 10; break; /* S/390 (sometimes) */
|
||||||
@ -252,44 +246,13 @@ static int check_for_privs(void){
|
|||||||
return !!rc;
|
return !!rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OOMEM_ENABLE
|
|
||||||
long smp_num_cpus(void)
|
|
||||||
{
|
|
||||||
static long _smp_num_cpus=-1; /* number of CPUs */
|
|
||||||
|
|
||||||
if (_smp_num_cpus != -1)
|
|
||||||
return(_smp_num_cpus);
|
|
||||||
|
|
||||||
// ought to count CPUs in /proc/stat instead of relying
|
|
||||||
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
|
||||||
//
|
|
||||||
// SourceForge has an old Alpha running Linux 2.2.20 that
|
|
||||||
// appears to have a non-SMP kernel on a 2-way SMP box.
|
|
||||||
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
|
|
||||||
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
|
||||||
|
|
||||||
_smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
|
||||||
if(_smp_num_cpus<1) _smp_num_cpus=1; /* SPARC glibc is buggy */
|
|
||||||
|
|
||||||
return(_smp_num_cpus);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void init_libproc(void) __attribute__((constructor));
|
static void init_libproc(void) __attribute__((constructor));
|
||||||
static void init_libproc(void){
|
static void init_libproc(void){
|
||||||
have_privs = check_for_privs();
|
have_privs = check_for_privs();
|
||||||
init_Linux_version(); /* Must be called before we check code */
|
init_Linux_version(); /* Must be called before we check code */
|
||||||
#ifndef OOMEM_ENABLE
|
|
||||||
// ought to count CPUs in /proc/stat instead of relying
|
cpuinfo();
|
||||||
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
|
||||||
//
|
|
||||||
// SourceForge has an old Alpha running Linux 2.2.20 that
|
|
||||||
// appears to have a non-SMP kernel on a 2-way SMP box.
|
|
||||||
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
|
|
||||||
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
|
||||||
smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
|
||||||
if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
|
|
||||||
#endif
|
|
||||||
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
|
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
|
||||||
Hertz = find_elf_note(AT_CLKTCK);
|
Hertz = find_elf_note(AT_CLKTCK);
|
||||||
if(Hertz!=NOTE_NOT_FOUND) return;
|
if(Hertz!=NOTE_NOT_FOUND) return;
|
||||||
@ -978,3 +941,19 @@ unsigned get_pid_digits(void){
|
|||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void cpuinfo (void) {
|
||||||
|
// ought to count CPUs in /proc/stat instead of relying
|
||||||
|
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
||||||
|
//
|
||||||
|
// SourceForge has an old Alpha running Linux 2.2.20 that
|
||||||
|
// appears to have a non-SMP kernel on a 2-way SMP box.
|
||||||
|
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
|
||||||
|
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
||||||
|
|
||||||
|
smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if (smp_num_cpus<1) /* SPARC glibc is buggy */
|
||||||
|
smp_num_cpus=1;
|
||||||
|
}
|
||||||
|
@ -7,12 +7,8 @@
|
|||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
extern unsigned long long Hertz; /* clock tick frequency */
|
extern unsigned long long Hertz; /* clock tick frequency */
|
||||||
#ifndef OOMEM_ENABLE
|
extern long smp_num_cpus; /* number of CPUs */
|
||||||
extern long smp_num_cpus; /* number of CPUs */
|
extern int have_privs; /* boolean, true if setuid or similar */
|
||||||
#else
|
|
||||||
extern long smp_num_cpus(void); /* number of CPUs */
|
|
||||||
#endif
|
|
||||||
extern int have_privs; /* boolean, true if setuid or similar */
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define JT double
|
#define JT double
|
||||||
@ -136,5 +132,7 @@ extern unsigned int getslabinfo (struct slab_cache**);
|
|||||||
|
|
||||||
extern unsigned get_pid_digits(void) FUNCTION;
|
extern unsigned get_pid_digits(void) FUNCTION;
|
||||||
|
|
||||||
|
extern void cpuinfo (void);
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
#endif /* SYSINFO_H */
|
#endif /* SYSINFO_H */
|
||||||
|
10
top.1
10
top.1
@ -59,9 +59,9 @@
|
|||||||
.ds FM full\-screen mode
|
.ds FM full\-screen mode
|
||||||
.ds KA arrow key
|
.ds KA arrow key
|
||||||
.ds KS scrolling key
|
.ds KS scrolling key
|
||||||
.ds MP \fBphysical\fR memory
|
.ds MP physical memory
|
||||||
.ds MS \fBshared\fR memory
|
.ds MS shared memory
|
||||||
.ds MV \fBvirtual\fR memory
|
.ds MV virtual memory
|
||||||
.ds NT \fBNote\fR:
|
.ds NT \fBNote\fR:
|
||||||
.ds PU CPU
|
.ds PU CPU
|
||||||
.ds Pu cpu
|
.ds Pu cpu
|
||||||
@ -775,9 +775,9 @@ line.
|
|||||||
|
|
||||||
.TP 7
|
.TP 7
|
||||||
\ \ \<\fBEnter\fR> or <\fBSpace\fR> :\fIRefresh-Display \fR
|
\ \ \<\fBEnter\fR> or <\fBSpace\fR> :\fIRefresh-Display \fR
|
||||||
These commands do nothing, they are simply ignored.
|
These commands awaken \*(We and following receipt of any input
|
||||||
However, they will awaken \*(We and following receipt of any input
|
|
||||||
the entire display will be repainted.
|
the entire display will be repainted.
|
||||||
|
They also force an update of any hotplugged \*(Pu or \*(MP changes.
|
||||||
|
|
||||||
Use either of these keys if you have a large delay interval and wish
|
Use either of these keys if you have a large delay interval and wish
|
||||||
to see current status,
|
to see current status,
|
||||||
|
51
top.c
51
top.c
@ -1679,7 +1679,7 @@ static void zap_fieldstab (void) {
|
|||||||
|
|
||||||
Cpu_pmax = 99.0;
|
Cpu_pmax = 99.0;
|
||||||
Fieldstab[P_CPU].fmts = "%#4.1f ";
|
Fieldstab[P_CPU].fmts = "%#4.1f ";
|
||||||
if (Rc.mode_irixps && Cpu_tot > 1 && !Thread_mode) {
|
if (Rc.mode_irixps && Cpu_tot > 1 && !Thread_mode) {
|
||||||
Cpu_pmax = 9999.0;
|
Cpu_pmax = 9999.0;
|
||||||
Fieldstab[P_CPU].fmts = "%4.0f ";
|
Fieldstab[P_CPU].fmts = "%4.0f ";
|
||||||
}
|
}
|
||||||
@ -1696,13 +1696,13 @@ static void zap_fieldstab (void) {
|
|||||||
static CPU_t *cpus_refresh (CPU_t *cpus) {
|
static CPU_t *cpus_refresh (CPU_t *cpus) {
|
||||||
static const char err_read[] = "failed /proc/stat read";
|
static const char err_read[] = "failed /proc/stat read";
|
||||||
static FILE *fp = NULL;
|
static FILE *fp = NULL;
|
||||||
static int smp_sav = -1;
|
static int sav_cpus = -1;
|
||||||
char buf[MEDBUFSIZ]; // enough for /proc/stat CPU line (not the intr line)
|
char buf[MEDBUFSIZ]; // enough for /proc/stat CPU line (not the intr line)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*** hotplug_acclimated ***/
|
/*** hotplug_acclimated ***/
|
||||||
if (smp_sav != SMP_NUM_CPUS) {
|
if (sav_cpus != smp_num_cpus) {
|
||||||
Cpu_tot = smp_sav = SMP_NUM_CPUS;
|
Cpu_tot = sav_cpus = smp_num_cpus;
|
||||||
zap_fieldstab();
|
zap_fieldstab();
|
||||||
calibrate_fields();
|
calibrate_fields();
|
||||||
if (fp) { fclose(fp); fp = NULL; }
|
if (fp) { fclose(fp); fp = NULL; }
|
||||||
@ -2000,11 +2000,38 @@ static proc_t **procs_refresh (proc_t **ppt) {
|
|||||||
#undef PTRsz
|
#undef PTRsz
|
||||||
#undef ENTsz
|
#undef ENTsz
|
||||||
} // end: procs_refresh
|
} // end: procs_refresh
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This serves as our interface to the memory & cpu count (sysinfo)
|
||||||
|
* portion of libproc. In support of those hotpluggable resources,
|
||||||
|
* the sampling frequencies are reduced so as to minimize overhead.
|
||||||
|
* We'll strive to verify the number of cpus every 5 minutes and the
|
||||||
|
* memory availability/usage every 3 seconds. */
|
||||||
|
static void sysinfo_refresh (int forced) {
|
||||||
|
static time_t mem_secs, cpu_secs;
|
||||||
|
time_t cur_secs;
|
||||||
|
|
||||||
|
if (forced)
|
||||||
|
mem_secs = cpu_secs = 0;
|
||||||
|
time(&cur_secs);
|
||||||
|
|
||||||
|
if (3 <= cur_secs - mem_secs) {
|
||||||
|
meminfo();
|
||||||
|
mem_secs = cur_secs;
|
||||||
|
}
|
||||||
|
#ifndef PRETEND4CPUS
|
||||||
|
if (300 <= cur_secs - cpu_secs) {
|
||||||
|
cpuinfo();
|
||||||
|
cpu_secs = cur_secs;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // end: sysinfo_refresh
|
||||||
|
|
||||||
/*###### Startup routines ##############################################*/
|
/*###### Startup routines ##############################################*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No mater what *they* say, we handle the really really BIG and
|
* No matter what *they* say, we handle the really really BIG and
|
||||||
* IMPORTANT stuff upon which all those lessor functions depend! */
|
* IMPORTANT stuff upon which all those lessor functions depend! */
|
||||||
static void before (char *me) {
|
static void before (char *me) {
|
||||||
int i;
|
int i;
|
||||||
@ -2015,10 +2042,9 @@ static void before (char *me) {
|
|||||||
|
|
||||||
// establish cpu particulars -- even bigger!
|
// establish cpu particulars -- even bigger!
|
||||||
#ifdef PRETEND4CPUS
|
#ifdef PRETEND4CPUS
|
||||||
SMP_NUM_CPUS = Cpu_tot = 4;
|
smp_num_cpus = 4;
|
||||||
#else
|
|
||||||
Cpu_tot = SMP_NUM_CPUS;
|
|
||||||
#endif
|
#endif
|
||||||
|
Cpu_tot = smp_num_cpus;
|
||||||
if (linux_version_code > LINUX_VERSION(2, 5, 41))
|
if (linux_version_code > LINUX_VERSION(2, 5, 41))
|
||||||
Cpu_States_fmts = STATES_line2x5;
|
Cpu_States_fmts = STATES_line2x5;
|
||||||
if (linux_version_code >= LINUX_VERSION(2, 6, 0))
|
if (linux_version_code >= LINUX_VERSION(2, 6, 0))
|
||||||
@ -2081,6 +2107,7 @@ static void configs_read (void) {
|
|||||||
fbuf[0] = '\0';
|
fbuf[0] = '\0';
|
||||||
fgets(fbuf, sizeof(fbuf), fp); // sys rc file, line 2
|
fgets(fbuf, sizeof(fbuf), fp); // sys rc file, line 2
|
||||||
sscanf(fbuf, "%f", &Rc.delay_time);
|
sscanf(fbuf, "%f", &Rc.delay_time);
|
||||||
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = fopen(Rc_name, "r");
|
fp = fopen(Rc_name, "r");
|
||||||
@ -3009,7 +3036,8 @@ static void do_key (int ch) {
|
|||||||
help_view();
|
help_view();
|
||||||
break;
|
break;
|
||||||
case kbd_ENTER: // these two will have the effect of waking us
|
case kbd_ENTER: // these two will have the effect of waking us
|
||||||
case kbd_SPACE: // from 'select()' then refreshing the display
|
case kbd_SPACE: // from 'select()', updating hotplugged resources
|
||||||
|
sysinfo_refresh(1); // and then refreshing the display
|
||||||
break;
|
break;
|
||||||
default: // and now, the real work...
|
default: // and now, the real work...
|
||||||
for (i = 0; i < MAXTBL(key_tab); ++i)
|
for (i = 0; i < MAXTBL(key_tab); ++i)
|
||||||
@ -3110,14 +3138,14 @@ static proc_t **summary_show (void) {
|
|||||||
|
|
||||||
// whoa first time, gotta' prime the pump...
|
// whoa first time, gotta' prime the pump...
|
||||||
if (!p_table) {
|
if (!p_table) {
|
||||||
struct timeval tv = { 0, 300000 };
|
|
||||||
p_table = procs_refresh(NULL);
|
p_table = procs_refresh(NULL);
|
||||||
putp(Cap_clr_scr);
|
putp(Cap_clr_scr);
|
||||||
select(0, NULL, NULL, NULL, &tv); // sleep for a bit...
|
usleep(LIB_USLEEP);
|
||||||
} else
|
} else
|
||||||
putp(Batch ? "\n\n" : Cap_home);
|
putp(Batch ? "\n\n" : Cap_home);
|
||||||
|
|
||||||
p_table = procs_refresh(p_table);
|
p_table = procs_refresh(p_table);
|
||||||
|
sysinfo_refresh(0);
|
||||||
|
|
||||||
// Display Uptime and Loadavg
|
// Display Uptime and Loadavg
|
||||||
if (isROOM(View_LOADAV, 1)) {
|
if (isROOM(View_LOADAV, 1)) {
|
||||||
@ -3157,7 +3185,6 @@ static proc_t **summary_show (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display Memory and Swap stats
|
// Display Memory and Swap stats
|
||||||
meminfo();
|
|
||||||
if (isROOM(View_MEMORY, 2)) {
|
if (isROOM(View_MEMORY, 2)) {
|
||||||
#define mkM(x) (unsigned long)(kb_main_ ## x >> shift)
|
#define mkM(x) (unsigned long)(kb_main_ ## x >> shift)
|
||||||
#define mkS(x) (unsigned long)(kb_swap_ ## x >> shift)
|
#define mkS(x) (unsigned long)(kb_swap_ ## x >> shift)
|
||||||
|
17
top.h
17
top.h
@ -62,23 +62,16 @@
|
|||||||
#define STRSORTCMP strcmp
|
#define STRSORTCMP strcmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef OOMEM_ENABLE
|
|
||||||
/* FIXME: perhaps making this a function in the suse version of
|
|
||||||
sysinfo.c was a prelude to hotpluggable updates -- unfortunately,
|
|
||||||
the return value is invariant as currently implemented! */
|
|
||||||
#define SMP_NUM_CPUS smp_num_cpus()
|
|
||||||
#else
|
|
||||||
#define SMP_NUM_CPUS smp_num_cpus
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*###### Some Miscellaneous constants ##################################*/
|
/*###### Some Miscellaneous constants ##################################*/
|
||||||
|
|
||||||
/* The default delay twix updates */
|
/* The default delay twix updates */
|
||||||
#define DEF_DELAY 3.0
|
#define DEF_DELAY 3.0
|
||||||
|
|
||||||
/* Length of time a 'message' is displayed (in microseconds) */
|
/* Length of time a message is displayed and the duration
|
||||||
|
of a 'priming' wait during library startup (in microseconds) */
|
||||||
#define MSG_USLEEP (useconds_t)1250000
|
#define MSG_USLEEP (useconds_t)1250000
|
||||||
|
#define LIB_USLEEP (useconds_t)150000
|
||||||
|
|
||||||
/* Specific process id monitoring support (command line only) */
|
/* Specific process id monitoring support (command line only) */
|
||||||
#define MONPIDMAX 20
|
#define MONPIDMAX 20
|
||||||
@ -592,9 +585,6 @@ typedef struct WIN_t {
|
|||||||
#if defined(ATEOJ_RPTHSH) && defined(OFF_HST_HASH)
|
#if defined(ATEOJ_RPTHSH) && defined(OFF_HST_HASH)
|
||||||
# error 'ATEOJ_RPTHSH' conflicts with 'OFF_HST_HASH'
|
# error 'ATEOJ_RPTHSH' conflicts with 'OFF_HST_HASH'
|
||||||
#endif
|
#endif
|
||||||
#if defined(PRETEND4CPUS) && defined (OOMEM_ENABLE)
|
|
||||||
# error 'PRETEND4CPUS' conflicts with 'OOMEM_ENABLE'
|
|
||||||
#endif
|
|
||||||
#if (LRGBUFSIZ < SCREENMAX)
|
#if (LRGBUFSIZ < SCREENMAX)
|
||||||
# error 'LRGBUFSIZ' must NOT be less than 'SCREENMAX'
|
# error 'LRGBUFSIZ' must NOT be less than 'SCREENMAX'
|
||||||
#endif
|
#endif
|
||||||
@ -655,6 +645,7 @@ typedef struct WIN_t {
|
|||||||
#endif
|
#endif
|
||||||
//atic void prochlp (proc_t *p);
|
//atic void prochlp (proc_t *p);
|
||||||
//atic proc_t **procs_refresh (proc_t **ppt);
|
//atic proc_t **procs_refresh (proc_t **ppt);
|
||||||
|
//atic void sysinfo_refresh (int forced);
|
||||||
/*------ Startup routines ----------------------------------------------*/
|
/*------ Startup routines ----------------------------------------------*/
|
||||||
//atic void before (char *me);
|
//atic void before (char *me);
|
||||||
//atic void configs_read (void);
|
//atic void configs_read (void);
|
||||||
|
69
w.c
69
w.c
@ -29,6 +29,7 @@
|
|||||||
#include <utmp.h>
|
#include <utmp.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
static int ignoreuser = 0; /* for '-u' */
|
static int ignoreuser = 0; /* for '-u' */
|
||||||
static proc_t **procs; /* our snapshot of the process table */
|
static proc_t **procs; /* our snapshot of the process table */
|
||||||
@ -44,6 +45,7 @@ typedef struct utmp utmp_t;
|
|||||||
/* Uh... same thing as UT_NAMESIZE */
|
/* Uh... same thing as UT_NAMESIZE */
|
||||||
#define USERSZ (sizeof u->ut_user)
|
#define USERSZ (sizeof u->ut_user)
|
||||||
|
|
||||||
|
#define MAX_FROM_LEN 16
|
||||||
|
|
||||||
/* This routine is careful since some programs leave utmp strings
|
/* This routine is careful since some programs leave utmp strings
|
||||||
* unprintable. Always outputs at least 16 chars padded with spaces
|
* unprintable. Always outputs at least 16 chars padded with spaces
|
||||||
@ -57,7 +59,7 @@ static void print_host(const char *restrict host, int len) {
|
|||||||
/* for now, we'll just limit it to the 16 that the libc5 version
|
/* for now, we'll just limit it to the 16 that the libc5 version
|
||||||
* of utmp uses.
|
* of utmp uses.
|
||||||
*/
|
*/
|
||||||
if (len > 16) len = 16;
|
if (len > MAX_FROM_LEN) len = MAX_FROM_LEN;
|
||||||
last = host + len;
|
last = host + len;
|
||||||
for ( ; host < last ; host++){
|
for ( ; host < last ; host++){
|
||||||
if (isprint(*host) && *host != ' ') {
|
if (isprint(*host) && *host != ' ') {
|
||||||
@ -67,8 +69,45 @@ static void print_host(const char *restrict host, int len) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// space-fill, and a '-' too if needed to ensure the column exists
|
/* space-fill, and a '-' too if needed to ensure the column exists */
|
||||||
if(width < 16) fputs("- "+width, stdout);
|
if(width < MAX_FROM_LEN) fputs("- "+width, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine prints either the hostname or the IP address of the remote */
|
||||||
|
static void print_from(const utmp_t *restrict const u, int ip_addresses) {
|
||||||
|
char buf[MAX_FROM_LEN + 1];
|
||||||
|
char buf_ipv6[INET6_ADDRSTRLEN];
|
||||||
|
int len;
|
||||||
|
int32_t ut_addr_v6[4]; /* IP address of remote host. */
|
||||||
|
|
||||||
|
if (ip_addresses) { /* -n switch used */
|
||||||
|
memcpy(&ut_addr_v6, &u->ut_addr_v6, sizeof(ut_addr_v6));
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&ut_addr_v6)) {
|
||||||
|
/* map back */
|
||||||
|
ut_addr_v6[0] = ut_addr_v6[3];
|
||||||
|
ut_addr_v6[1] = 0;
|
||||||
|
ut_addr_v6[2] = 0;
|
||||||
|
ut_addr_v6[3] = 0;
|
||||||
|
}
|
||||||
|
if (ut_addr_v6[1] || ut_addr_v6[2] || ut_addr_v6[3]) {
|
||||||
|
/* IPv6 */
|
||||||
|
if (!inet_ntop(AF_INET6, &ut_addr_v6, buf_ipv6, sizeof(buf_ipv6))) {
|
||||||
|
snprintf(buf_ipv6, INET6_ADDRSTRLEN, "?");
|
||||||
|
}
|
||||||
|
strncpy(buf, buf_ipv6, MAX_FROM_LEN);
|
||||||
|
} else {
|
||||||
|
/* IPv4 */
|
||||||
|
if (!inet_ntop(AF_INET, &ut_addr_v6[0], buf, sizeof(buf))) {
|
||||||
|
snprintf(buf, MAX_FROM_LEN, "?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[MAX_FROM_LEN] = 0;
|
||||||
|
for (len = strlen(buf); len < MAX_FROM_LEN; len++) buf[len]=' ';
|
||||||
|
buf[MAX_FROM_LEN] = 0;
|
||||||
|
fputs(buf, stdout);
|
||||||
|
} else {
|
||||||
|
print_host(u->ut_host, sizeof u->ut_host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** compact 7 char format for time intervals (belongs in libproc?) */
|
/***** compact 7 char format for time intervals (belongs in libproc?) */
|
||||||
@ -169,7 +208,7 @@ static const proc_t *getproc(const utmp_t *restrict const u, const char *restric
|
|||||||
|
|
||||||
|
|
||||||
/***** showinfo */
|
/***** showinfo */
|
||||||
static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
|
static void showinfo(utmp_t *u, int formtype, int maxcmd, int from, int ip_addresses) {
|
||||||
unsigned long long jcpu;
|
unsigned long long jcpu;
|
||||||
int ut_pid_found;
|
int ut_pid_found;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -196,7 +235,7 @@ static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
|
|||||||
if (formtype) {
|
if (formtype) {
|
||||||
printf("%-9.8s%-9.8s", uname, u->ut_line);
|
printf("%-9.8s%-9.8s", uname, u->ut_line);
|
||||||
if (from)
|
if (from)
|
||||||
print_host(u->ut_host, sizeof u->ut_host);
|
print_from(u, ip_addresses);
|
||||||
print_logintime(u->ut_time, stdout);
|
print_logintime(u->ut_time, stdout);
|
||||||
if (*u->ut_line == ':') /* idle unknown for xdm logins */
|
if (*u->ut_line == ':') /* idle unknown for xdm logins */
|
||||||
printf(" ?xdm? ");
|
printf(" ?xdm? ");
|
||||||
@ -211,7 +250,7 @@ static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
|
|||||||
} else {
|
} else {
|
||||||
printf("%-9.8s%-9.8s", u->ut_user, u->ut_line);
|
printf("%-9.8s%-9.8s", u->ut_user, u->ut_line);
|
||||||
if (from)
|
if (from)
|
||||||
print_host(u->ut_host, sizeof u->ut_host);
|
print_from(u, ip_addresses);
|
||||||
if (*u->ut_line == ':') /* idle unknown for xdm logins */
|
if (*u->ut_line == ':') /* idle unknown for xdm logins */
|
||||||
printf(" ?xdm? ");
|
printf(" ?xdm? ");
|
||||||
else
|
else
|
||||||
@ -233,14 +272,22 @@ int main(int argc, char **argv) {
|
|||||||
char *user = NULL;
|
char *user = NULL;
|
||||||
utmp_t *u;
|
utmp_t *u;
|
||||||
struct winsize win;
|
struct winsize win;
|
||||||
int header=1, longform=1, from=1, args, maxcmd=80, ch;
|
int args;
|
||||||
|
int maxcmd = 80;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
/* defaults */
|
||||||
|
int header = 1;
|
||||||
|
int longform = 1;
|
||||||
|
int from = 1;
|
||||||
|
int ip_addresses = 0;
|
||||||
|
|
||||||
#ifndef W_SHOWFROM
|
#ifndef W_SHOWFROM
|
||||||
from = 0;
|
from = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
for (args=0; (ch = getopt(argc, argv, "hlusfV")) != EOF; args++)
|
for (args=0; (ch = getopt(argc, argv, "hlusfnV")) != EOF; args++)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'h': header = 0; break;
|
case 'h': header = 0; break;
|
||||||
case 'l': longform = 1; break;
|
case 'l': longform = 1; break;
|
||||||
@ -248,6 +295,7 @@ int main(int argc, char **argv) {
|
|||||||
case 'f': from = !from; break;
|
case 'f': from = !from; break;
|
||||||
case 'V': display_version(); exit(0);
|
case 'V': display_version(); exit(0);
|
||||||
case 'u': ignoreuser = 1; break;
|
case 'u': ignoreuser = 1; break;
|
||||||
|
case 'n': ip_addresses = 1; break;
|
||||||
default:
|
default:
|
||||||
printf("usage: w -hlsufV [user]\n"
|
printf("usage: w -hlsufV [user]\n"
|
||||||
" -h skip header\n"
|
" -h skip header\n"
|
||||||
@ -255,6 +303,7 @@ int main(int argc, char **argv) {
|
|||||||
" -s short listing\n"
|
" -s short listing\n"
|
||||||
" -u ignore uid of processes\n"
|
" -u ignore uid of processes\n"
|
||||||
" -f toggle FROM field (default %s)\n"
|
" -f toggle FROM field (default %s)\n"
|
||||||
|
" -n use IP addresses instead of hostname\n"
|
||||||
" -V display version\n", FROM_STRING);
|
" -V display version\n", FROM_STRING);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -292,14 +341,14 @@ int main(int argc, char **argv) {
|
|||||||
u = getutent();
|
u = getutent();
|
||||||
if (unlikely(!u)) break;
|
if (unlikely(!u)) break;
|
||||||
if (u->ut_type != USER_PROCESS) continue;
|
if (u->ut_type != USER_PROCESS) continue;
|
||||||
if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from);
|
if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from, ip_addresses);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
u = getutent();
|
u = getutent();
|
||||||
if (unlikely(!u)) break;
|
if (unlikely(!u)) break;
|
||||||
if (u->ut_type != USER_PROCESS) continue;
|
if (u->ut_type != USER_PROCESS) continue;
|
||||||
if (*u->ut_user) showinfo(u, longform, maxcmd, from);
|
if (*u->ut_user) showinfo(u, longform, maxcmd, from, ip_addresses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endutent();
|
endutent();
|
||||||
|
Loading…
Reference in New Issue
Block a user