/*
* top - a top users display for Unix
*
* SYNOPSIS: Linux 1.2.x, 1.3.x, 2.x, using the /proc filesystem
*
* DESCRIPTION:
* This is the machine-dependent module for Linux 1.2.x, 1.3.x or 2.x.
*
* LIBS:
*
* CFLAGS: -DHAVE_GETOPT -DHAVE_STRERROR -DORDER
*
* TERMCAP: -lcurses
*
* AUTHOR: Richard Henderson <rth@tamu.edu>
* Order support added by Alexey Klimkin <kad@klon.tme.mcst.ru>
* Ported to 2.4 by William LeFebvre
*/
#include "config.h"
#include <sys/types.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/param.h> /* for HZ */
#if 0
#include <linux/proc_fs.h> /* for PROC_SUPER_MAGIC */
#else
#define PROC_SUPER_MAGIC 0x9fa0
#endif
#include "top.h"
#include "machine.h"
#include "utils.h"
#define PROCFS "/proc"
extern char *myname;
/*=PROCESS INFORMATION==================================================*/
struct top_proc
{
pid_t pid;
uid_t uid;
char *name;
int pri, nice;
unsigned long size, rss; /* in k */
int state;
unsigned long time;
unsigned long start_time;
double pcpu, wcpu;
struct top_proc *next;
};
/*=STATE IDENT STRINGS==================================================*/
#define NPROCSTATES 7
static char *state_abbrev[NPROCSTATES+1] =
{
"", "run", "sleep", "disk", "zomb", "stop", "swap",
NULL
};
static char *procstatenames[NPROCSTATES+1] =
{
"", " running, ", " sleeping, ", " uninterruptable, ",
" zombie, ", " stopped, ", " swapping, ",
NULL
};
#define NCPUSTATES 5
static char *cpustatenames[NCPUSTATES+1] =
{
"user", "nice", "system", "idle", "iowait",
NULL
};
static int show_iowait = 0;
#define MEMUSED 0
#define MEMFREE 1
#define MEMSHARED 2
#define MEMBUFFERS 3
#define MEMCACHED 4
#define NMEMSTATS 5
static char *memorynames[NMEMSTATS+1] =
{
"K used, ", "K free, ", "K shared, ", "K buffers, ", "K cached",
NULL
};
#define SWAPUSED 0
#define SWAPFREE 1
#define SWAPCACHED 2
#define NSWAPSTATS 3
static char *swapnames[NSWAPSTATS+1] =
{
"K used, ", "K free, ", "K cached",
NULL
};
static char fmt_header[] =
" PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
/* these are names given to allowed sorting orders -- first is default */
char *ordernames[] =
{"cpu", "size", "res", "time", "command", NULL};
/* forward definitions for comparison functions */
int compare_cpu();
int compare_size();
int compare_res();
int compare_time();
int compare_cmd();
int (*proc_compares[])() = {
compare_cpu,
compare_size,
compare_res,
compare_time,
compare_cmd,
NULL };
/*=SYSTEM STATE INFO====================================================*/
/* these are for calculating cpu state percentages */
static long cp_time[NCPUSTATES];
static long cp_old[NCPUSTATES];
static long cp_diff[NCPUSTATES];
/* for calculating the exponential average */
static struct timeval lasttime;
/* these are for keeping track of processes */
#define HASH_SIZE (1003)
#define INITIAL_ACTIVE_SIZE (256)
#define PROCBLOCK_SIZE (32)
static struct top_proc *ptable[HASH_SIZE];
static struct top_proc **pactive;
static struct top_proc **nextactive;
static unsigned int activesize = 0;
static time_t boottime = -1;
/* these are for passing data back to the machine independant portion */
static int cpu_states[NCPUSTATES];
static int process_states[NPROCSTATES];
static long memory_stats[NMEMSTATS];
static long swap_stats[NSWAPSTATS];
/* usefull macros */
#define bytetok(x) (((x) + 512) >> 10)
#define pagetok(x) ((x) << (getpagesize() - 10))
#define HASH(x) (((x) * 1686629713U) % HASH_SIZE)
/*======================================================================*/
static inline char *
skip_ws(const char *p)
{
while (isspace(*p)) p++;
return (char *)p;
}
static inline char *
skip_token(const char *p)
{
while (isspace(*p)) p++;
while (*p &&