w: use the new procps_pids library interface
w using the new procps_pids calls from the library. There are some clean-ups of the code within w as well.
This commit is contained in:
parent
eba58ec17a
commit
a02911c1ea
289
w.c
289
w.c
@ -26,13 +26,9 @@
|
|||||||
#include "c.h"
|
#include "c.h"
|
||||||
#include "fileutils.h"
|
#include "fileutils.h"
|
||||||
#include "nls.h"
|
#include "nls.h"
|
||||||
#include "proc/devname.h"
|
#include <proc/sysinfo.h>
|
||||||
#include "proc/escape.h"
|
|
||||||
#include "proc/procps.h"
|
|
||||||
#include "proc/readproc.h"
|
|
||||||
#include "proc/sysinfo.h"
|
|
||||||
#include "proc/version.h"
|
|
||||||
#include <proc/uptime.h>
|
#include <proc/uptime.h>
|
||||||
|
#include <proc/pids.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -59,7 +55,6 @@
|
|||||||
|
|
||||||
static int ignoreuser = 0; /* for '-u' */
|
static int ignoreuser = 0; /* for '-u' */
|
||||||
static int oldstyle = 0; /* for '-o' */
|
static int oldstyle = 0; /* for '-o' */
|
||||||
static proc_t **procs; /* our snapshot of the process table */
|
|
||||||
|
|
||||||
typedef struct utmp utmp_t;
|
typedef struct utmp utmp_t;
|
||||||
|
|
||||||
@ -310,6 +305,27 @@ static void print_logintime(time_t logt, FILE * fout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the Device ID of the given TTY
|
||||||
|
*/
|
||||||
|
static int get_tty_device(const char *restrict const name)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
static char buf[32];
|
||||||
|
char *dev_paths[] = { "/dev/%s", "/dev/tty%s", "/dev/pts/%s", NULL};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (name[0] == '/' && stat(name, &st) == 0)
|
||||||
|
return st.st_rdev;
|
||||||
|
|
||||||
|
for (i=0; dev_paths[i] != NULL; i++) {
|
||||||
|
snprintf(buf, 32, dev_paths[i], name);
|
||||||
|
if (stat(buf, &st) == 0)
|
||||||
|
return st.st_rdev;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function scans the process table accumulating total cpu
|
* This function scans the process table accumulating total cpu
|
||||||
* times for any processes "associated" with this login session.
|
* times for any processes "associated" with this login session.
|
||||||
@ -317,128 +333,162 @@ static void print_logintime(time_t logt, FILE * fout)
|
|||||||
* the user for that login session is doing currently. This the
|
* the user for that login session is doing currently. This the
|
||||||
* essential core of 'w'.
|
* essential core of 'w'.
|
||||||
*/
|
*/
|
||||||
static const proc_t *getproc(const utmp_t * restrict const u,
|
static int find_best_proc(
|
||||||
const char *restrict const tty,
|
const utmp_t * restrict const u,
|
||||||
unsigned long long *restrict const jcpu,
|
const char *restrict const tty,
|
||||||
int *restrict const found_utpid)
|
unsigned long long *restrict const jcpu,
|
||||||
|
unsigned long long *restrict const pcpu,
|
||||||
|
char *cmdline)
|
||||||
{
|
{
|
||||||
int line;
|
#define PIDS_GETINT(e) PROCPS_PIDS_VAL(EU_ ## e, s_int, reap->stacks[i])
|
||||||
proc_t **pptr = procs;
|
#define PIDS_GETULL(e) PROCPS_PIDS_VAL(EU_ ## e, ull_int, reap->stacks[i])
|
||||||
const proc_t *best = NULL;
|
#define PIDS_GETSTR(e) PROCPS_PIDS_VAL(EU_ ## e, str, reap->stacks[i])
|
||||||
const proc_t *secondbest = NULL;
|
unsigned uid = ~0U;
|
||||||
unsigned uid = ~0U;
|
int found_utpid = 0;
|
||||||
|
int i, total_procs, line;
|
||||||
|
unsigned long long best_time = 0;
|
||||||
|
unsigned long long secondbest_time = 0;
|
||||||
|
|
||||||
*found_utpid = 0;
|
struct procps_pidsinfo *info=NULL;
|
||||||
if (!ignoreuser) {
|
struct pids_reap *reap;
|
||||||
char buf[UT_NAMESIZE + 1];
|
enum pids_item items[] = {
|
||||||
/* pointer to static data */
|
PROCPS_PIDS_ID_TGID,
|
||||||
struct passwd *passwd_data;
|
PROCPS_PIDS_TIME_START,
|
||||||
strncpy(buf, u->ut_user, UT_NAMESIZE);
|
PROCPS_PIDS_ID_EUID,
|
||||||
buf[UT_NAMESIZE] = '\0';
|
PROCPS_PIDS_ID_RUID,
|
||||||
passwd_data = getpwnam(buf);
|
PROCPS_PIDS_ID_TPGID,
|
||||||
if (!passwd_data)
|
PROCPS_PIDS_ID_PGRP,
|
||||||
return NULL;
|
PROCPS_PIDS_TTY,
|
||||||
uid = passwd_data->pw_uid;
|
PROCPS_PIDS_TICS_ALL,
|
||||||
/* OK to have passwd_data go out of scope here */
|
PROCPS_PIDS_CMDLINE};
|
||||||
}
|
enum rel_items {
|
||||||
line = tty_to_dev(tty);
|
EU_TGID, EU_START, EU_EUID, EU_RUID, EU_TPGID, EU_PGRP, EU_TTY,
|
||||||
*jcpu = 0;
|
EU_TICS_ALL, EU_CMDLINE};
|
||||||
for (; *pptr; pptr++) {
|
|
||||||
const proc_t *restrict const tmp = *pptr;
|
*jcpu = 0;
|
||||||
if (unlikely(tmp->tgid == u->ut_pid)) {
|
*pcpu = 0;
|
||||||
*found_utpid = 1;
|
if (!ignoreuser) {
|
||||||
best = tmp;
|
char buf[UT_NAMESIZE + 1];
|
||||||
}
|
struct passwd *passwd_data;
|
||||||
if (tmp->tty != line)
|
strncpy(buf, u->ut_user, UT_NAMESIZE);
|
||||||
continue;
|
buf[UT_NAMESIZE] = '\0';
|
||||||
(*jcpu) += tmp->utime + tmp->stime;
|
if ((passwd_data = getpwnam(buf)) == NULL)
|
||||||
secondbest = tmp;
|
return 0;
|
||||||
/* same time-logic here as for "best" below */
|
uid = passwd_data->pw_uid;
|
||||||
if (!(secondbest && tmp->start_time <= secondbest->start_time)) {
|
/* OK to have passwd_data go out of scope here */
|
||||||
secondbest = tmp;
|
}
|
||||||
}
|
|
||||||
if (!ignoreuser && uid != tmp->euid && uid != tmp->ruid)
|
line = get_tty_device(tty);
|
||||||
continue;
|
|
||||||
if (tmp->pgrp != tmp->tpgid)
|
if (procps_pids_new(&info, 9, items) < 0)
|
||||||
continue;
|
xerrx(EXIT_FAILURE,
|
||||||
if (best && tmp->start_time <= best->start_time)
|
_("Unable to create pid info structure"));
|
||||||
continue;
|
if ((reap = procps_pids_reap(info, PROCPS_REAP_TASKS_ONLY)) == NULL)
|
||||||
best = tmp;
|
xerrx(EXIT_FAILURE,
|
||||||
}
|
_("Unable to load process information"));
|
||||||
return best ? best : secondbest;
|
total_procs = reap->counts.total;
|
||||||
|
|
||||||
|
for (i=0; i < total_procs; i++) {
|
||||||
|
/* is this the login process? */
|
||||||
|
if (PIDS_GETINT(TGID) == u->ut_pid) {
|
||||||
|
found_utpid = 1;
|
||||||
|
if (!best_time) {
|
||||||
|
best_time = PIDS_GETULL(START);
|
||||||
|
strncpy(cmdline, PIDS_GETSTR(CMDLINE), MAX_CMD_WIDTH);
|
||||||
|
*pcpu = PIDS_GETULL(TICS_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (PIDS_GETINT(TTY) != line)
|
||||||
|
continue;
|
||||||
|
(*jcpu) += PROCPS_PIDS_VAL(EU_TICS_ALL, ull_int, reap->stacks[i]);
|
||||||
|
if (!(secondbest_time && PIDS_GETULL(START) <= secondbest_time)) {
|
||||||
|
secondbest_time = PIDS_GETULL(START);
|
||||||
|
if (cmdline[0] == '-' && cmdline[1] == '\0') {
|
||||||
|
strncpy(cmdline, PIDS_GETSTR(CMDLINE), MAX_CMD_WIDTH);
|
||||||
|
*pcpu = PIDS_GETULL(TICS_ALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(!ignoreuser && uid != PIDS_GETINT(EUID)
|
||||||
|
&& uid != PIDS_GETINT(RUID))
|
||||||
|
|| (PIDS_GETINT(PGRP) != PIDS_GETINT(TPGID))
|
||||||
|
|| (PIDS_GETULL(START) <= best_time)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
best_time = PIDS_GETULL(START);
|
||||||
|
strncpy(cmdline, PIDS_GETSTR(CMDLINE), MAX_CMD_WIDTH);
|
||||||
|
*pcpu = PIDS_GETULL(TICS_ALL);
|
||||||
|
}
|
||||||
|
procps_pids_unref(&info);
|
||||||
|
return found_utpid;
|
||||||
|
#undef PIDS_GETINT
|
||||||
|
#undef PIDS_GETULL
|
||||||
|
#undef PIDS_GETSTR
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showinfo(utmp_t * u, int formtype, int maxcmd, int from,
|
static void showinfo(
|
||||||
const int userlen, const int fromlen, const int ip_addresses)
|
utmp_t * u, int formtype, int maxcmd, int from,
|
||||||
|
const int userlen, const int fromlen, const int ip_addresses)
|
||||||
{
|
{
|
||||||
unsigned long long jcpu;
|
unsigned long long jcpu, pcpu;
|
||||||
int ut_pid_found;
|
unsigned i;
|
||||||
unsigned i;
|
char uname[UT_NAMESIZE + 1] = "", tty[5 + UT_LINESIZE + 1] = "/dev/";
|
||||||
char uname[UT_NAMESIZE + 1] = "", tty[5 + UT_LINESIZE + 1] = "/dev/";
|
long hertz;
|
||||||
const proc_t *best;
|
char cmdline[MAX_CMD_WIDTH + 1];
|
||||||
long hertz;
|
|
||||||
|
|
||||||
hertz = procps_hertz_get();
|
strcpy(cmdline, "-");
|
||||||
for (i = 0; i < UT_LINESIZE; i++)
|
|
||||||
/* clean up tty if garbled */
|
|
||||||
if (isalnum(u->ut_line[i]) || (u->ut_line[i] == '/'))
|
|
||||||
tty[i + 5] = u->ut_line[i];
|
|
||||||
else
|
|
||||||
tty[i + 5] = '\0';
|
|
||||||
|
|
||||||
best = getproc(u, tty + 5, &jcpu, &ut_pid_found);
|
hertz = procps_hertz_get();
|
||||||
|
for (i = 0; i < UT_LINESIZE; i++)
|
||||||
|
/* clean up tty if garbled */
|
||||||
|
if (isalnum(u->ut_line[i]) || (u->ut_line[i] == '/'))
|
||||||
|
tty[i + 5] = u->ut_line[i];
|
||||||
|
else
|
||||||
|
tty[i + 5] = '\0';
|
||||||
|
|
||||||
/*
|
if (find_best_proc(u, tty + 5, &jcpu, &pcpu, cmdline) == 0)
|
||||||
* just skip if stale utmp entry (i.e. login proc doesn't
|
/*
|
||||||
* exist). If there is a desire a cmdline flag could be
|
* just skip if stale utmp entry (i.e. login proc doesn't
|
||||||
* added to optionally show it with a prefix of (stale)
|
* exist). If there is a desire a cmdline flag could be
|
||||||
* in front of cmd or something like that.
|
* added to optionally show it with a prefix of (stale)
|
||||||
*/
|
* in front of cmd or something like that.
|
||||||
if (!ut_pid_found)
|
*/
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* force NUL term for printf */
|
/* force NUL term for printf */
|
||||||
strncpy(uname, u->ut_user, UT_NAMESIZE);
|
strncpy(uname, u->ut_user, UT_NAMESIZE);
|
||||||
|
|
||||||
if (formtype) {
|
if (formtype) {
|
||||||
printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, u->ut_line);
|
printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, u->ut_line);
|
||||||
if (from)
|
if (from)
|
||||||
print_from(u, ip_addresses, fromlen);
|
print_from(u, ip_addresses, fromlen);
|
||||||
print_logintime(u->ut_time, stdout);
|
print_logintime(u->ut_time, stdout);
|
||||||
if (*u->ut_line == ':')
|
if (*u->ut_line == ':')
|
||||||
/* idle unknown for xdm logins */
|
/* idle unknown for xdm logins */
|
||||||
printf(" ?xdm? ");
|
printf(" ?xdm? ");
|
||||||
else
|
else
|
||||||
print_time_ival7(idletime(tty), 0, stdout);
|
print_time_ival7(idletime(tty), 0, stdout);
|
||||||
print_time_ival7(jcpu / hertz, (jcpu % hertz) * (100. / hertz),
|
print_time_ival7(jcpu / hertz, (jcpu % hertz) * (100. / hertz),
|
||||||
stdout);
|
stdout);
|
||||||
if (best) {
|
if (pcpu > 0)
|
||||||
unsigned long long pcpu = best->utime + best->stime;
|
print_time_ival7(pcpu / hertz,
|
||||||
print_time_ival7(pcpu / hertz,
|
(pcpu % hertz) * (100. / hertz),
|
||||||
(pcpu % hertz) * (100. / hertz),
|
stdout);
|
||||||
stdout);
|
else
|
||||||
} else
|
printf(" ? ");
|
||||||
printf(" ? ");
|
} else {
|
||||||
} else {
|
printf("%-*.*s%-9.8s", userlen + 1, userlen, u->ut_user,
|
||||||
printf("%-*.*s%-9.8s", userlen + 1, userlen, u->ut_user,
|
u->ut_line);
|
||||||
u->ut_line);
|
if (from)
|
||||||
if (from)
|
print_from(u, ip_addresses, fromlen);
|
||||||
print_from(u, ip_addresses, fromlen);
|
if (*u->ut_line == ':')
|
||||||
if (*u->ut_line == ':')
|
/* idle unknown for xdm logins */
|
||||||
/* idle unknown for xdm logins */
|
printf(" ?xdm? ");
|
||||||
printf(" ?xdm? ");
|
else
|
||||||
else
|
print_time_ival7(idletime(tty), 0, stdout);
|
||||||
print_time_ival7(idletime(tty), 0, stdout);
|
}
|
||||||
}
|
printf(" %-*.*s\n", maxcmd, maxcmd, cmdline);
|
||||||
fputs(" ", stdout);
|
|
||||||
if (likely(best)) {
|
|
||||||
char cmdbuf[MAX_CMD_WIDTH];
|
|
||||||
escape_command(cmdbuf, best, sizeof cmdbuf, &maxcmd, ESC_ARGS);
|
|
||||||
fputs(cmdbuf, stdout);
|
|
||||||
} else {
|
|
||||||
printf("-");
|
|
||||||
}
|
|
||||||
fputc('\n', stdout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__ ((__noreturn__))
|
static void __attribute__ ((__noreturn__))
|
||||||
@ -582,7 +632,6 @@ int main(int argc, char **argv)
|
|||||||
if (maxcmd < 3)
|
if (maxcmd < 3)
|
||||||
xwarnx(_("warning: screen width %d suboptimal"), win.ws_col);
|
xwarnx(_("warning: screen width %d suboptimal"), win.ws_col);
|
||||||
|
|
||||||
procs = readproctab(PROC_FILLCOM | PROC_FILLUSR | PROC_FILLSTAT);
|
|
||||||
|
|
||||||
if (header) {
|
if (header) {
|
||||||
/* print uptime and headers */
|
/* print uptime and headers */
|
||||||
|
Loading…
Reference in New Issue
Block a user