w: new usage & fix coding style
Coding style fixed and more readable help output. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
parent
922d218e1e
commit
7af14af685
650
w.c
650
w.c
@ -1,20 +1,30 @@
|
|||||||
/* w - show what logged in users are doing. Almost entirely rewritten from
|
/*
|
||||||
* scratch by Charles Blake circa June 1996. Some vestigal traces of the
|
* w - show what logged in users are doing.
|
||||||
* original may exist. That was done in 1993 by Larry Greenfield with some
|
*
|
||||||
* fixes by Michael K. Johnson.
|
* Almost entirely rewritten from scratch by Charles Blake circa
|
||||||
|
* June 1996. Some vestigal traces of the original may exist.
|
||||||
|
* That was done in 1993 by Larry Greenfield with some fixes by
|
||||||
|
* Michael K. Johnson.
|
||||||
*
|
*
|
||||||
* Changes by Albert Cahalan, 2002.
|
* Changes by Albert Cahalan, 2002.
|
||||||
*/
|
*/
|
||||||
|
#include "proc/devname.h"
|
||||||
|
#include "proc/escape.h"
|
||||||
|
#include "proc/procps.h"
|
||||||
|
#include "proc/readproc.h"
|
||||||
|
#include "proc/sysinfo.h"
|
||||||
#include "proc/version.h"
|
#include "proc/version.h"
|
||||||
#include "proc/whattime.h"
|
#include "proc/whattime.h"
|
||||||
#include "proc/readproc.h"
|
|
||||||
#include "proc/devname.h"
|
|
||||||
#include "proc/procps.h"
|
|
||||||
#include "proc/sysinfo.h"
|
|
||||||
#include "proc/escape.h"
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -23,12 +33,10 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <pwd.h>
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utmp.h>
|
#include <utmp.h>
|
||||||
#include <locale.h>
|
|
||||||
#include <termios.h>
|
|
||||||
|
|
||||||
static int ignoreuser = 0; /* for '-u' */
|
static int ignoreuser = 0; /* for '-u' */
|
||||||
static int oldstyle = 0; /* for '-o' */
|
static int oldstyle = 0; /* for '-o' */
|
||||||
@ -37,9 +45,9 @@ static proc_t **procs; /* our snapshot of the process table */
|
|||||||
typedef struct utmp utmp_t;
|
typedef struct utmp utmp_t;
|
||||||
|
|
||||||
#ifdef W_SHOWFROM
|
#ifdef W_SHOWFROM
|
||||||
# define FROM_STRING "on"
|
# define FROM_STRING "on"
|
||||||
#else
|
#else
|
||||||
# define FROM_STRING "off"
|
# define FROM_STRING "off"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Uh... same thing as UT_NAMESIZE */
|
/* Uh... same thing as UT_NAMESIZE */
|
||||||
@ -49,297 +57,397 @@ typedef struct utmp utmp_t;
|
|||||||
#define HOSTSZ 40
|
#define HOSTSZ 40
|
||||||
|
|
||||||
|
|
||||||
/* This routine is careful since some programs leave utmp strings
|
/*
|
||||||
* unprintable. Always outputs at least fromlen chars padded with spaces
|
* This routine is careful since some programs leave utmp strings
|
||||||
* on the right if necessary.
|
* unprintable. Always outputs at least 16 chars padded with
|
||||||
|
* spaces on the right if necessary.
|
||||||
*/
|
*/
|
||||||
static void print_host(const char *restrict host, int len, const int fromlen) {
|
static void print_host(const char *restrict host, int len, const int fromlen)
|
||||||
const char *last;
|
{
|
||||||
int width = 0;
|
const char *last;
|
||||||
|
int width = 0;
|
||||||
|
|
||||||
if (len > fromlen) len = fromlen;
|
if (len > fromlen)
|
||||||
last = host + len;
|
len = fromlen;
|
||||||
for ( ; host < last ; host++){
|
last = host + len;
|
||||||
if (isprint(*host) && *host != ' ') {
|
for (; host < last; host++) {
|
||||||
fputc(*host, stdout);
|
if (isprint(*host) && *host != ' ') {
|
||||||
++width;
|
fputc(*host, stdout);
|
||||||
|
++width;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* space-fill, and a '-' too if needed to ensure the
|
||||||
|
* column exists
|
||||||
|
*/
|
||||||
|
while (width++ < fromlen)
|
||||||
|
fputc(' ', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compact 7 char format for time intervals (belongs in libproc?) */
|
||||||
|
static void print_time_ival7(time_t t, int centi_sec, FILE * fout)
|
||||||
|
{
|
||||||
|
if ((long)t < (long)0) {
|
||||||
|
/* system clock changed? */
|
||||||
|
printf(" ? ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (oldstyle) {
|
||||||
|
if (t >= 48 * 60 * 60)
|
||||||
|
/* > 2 days */
|
||||||
|
fprintf(fout, " %2ludays", t / (24 * 60 * 60));
|
||||||
|
else if (t >= 60 * 60)
|
||||||
|
/* > 1 hour */
|
||||||
|
fprintf(fout, " %2lu:%02u ", t / (60 * 60),
|
||||||
|
(unsigned)((t / 60) % 60));
|
||||||
|
else if (t > 60)
|
||||||
|
/* > 1 minute */
|
||||||
|
fprintf(fout, " %2lu:%02um", t / 60, (unsigned)t % 60);
|
||||||
|
else
|
||||||
|
fprintf(fout, " ");
|
||||||
} else {
|
} else {
|
||||||
break;
|
if (t >= 48 * 60 * 60)
|
||||||
|
/* 2 days or more */
|
||||||
|
fprintf(fout, " %2ludays", t / (24 * 60 * 60));
|
||||||
|
else if (t >= 60 * 60)
|
||||||
|
/* 1 hour or more */
|
||||||
|
fprintf(fout, " %2lu:%02um", t / (60 * 60),
|
||||||
|
(unsigned)((t / 60) % 60));
|
||||||
|
else if (t > 60)
|
||||||
|
/* 1 minute or more */
|
||||||
|
fprintf(fout, " %2lu:%02u ", t / 60, (unsigned)t % 60);
|
||||||
|
else
|
||||||
|
fprintf(fout, " %2lu.%02us", t, centi_sec);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// space-fill, and a '-' too if needed to ensure the column exists
|
|
||||||
while(width++ < fromlen)
|
|
||||||
fputc(' ',stdout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** compact 7 char format for time intervals (belongs in libproc?) */
|
/* stat the device file to get an idle time */
|
||||||
static void print_time_ival7(time_t t, int centi_sec, FILE* fout) {
|
static time_t idletime(const char *restrict const tty)
|
||||||
if((long)t < (long)0){ /* system clock changed? */
|
{
|
||||||
printf(" ? ");
|
struct stat sbuf;
|
||||||
return;
|
if (stat(tty, &sbuf) != 0)
|
||||||
}
|
return 0;
|
||||||
if (oldstyle) {
|
return time(NULL) - sbuf.st_atime;
|
||||||
if (t >= 48*60*60) /* > 2 days */
|
|
||||||
fprintf(fout, " %2ludays", t/(24*60*60));
|
|
||||||
else if (t >= 60*60) /* > 1 hour */
|
|
||||||
fprintf(fout, " %2lu:%02u ", t/(60*60), (unsigned) ((t/60)%60));
|
|
||||||
else if (t > 60) /* > 1 minute */
|
|
||||||
fprintf(fout, " %2lu:%02um", t/60, (unsigned) t%60);
|
|
||||||
else
|
|
||||||
fprintf(fout, " ");
|
|
||||||
} else {
|
|
||||||
if (t >= 48*60*60) /* > 2 days */
|
|
||||||
fprintf(fout, " %2ludays", t/(24*60*60));
|
|
||||||
else if (t >= 60*60) /* > 1 hour */
|
|
||||||
fprintf(fout, " %2lu:%02um", t/(60*60), (unsigned) ((t/60)%60));
|
|
||||||
else if (t > 60) /* > 1 minute */
|
|
||||||
fprintf(fout, " %2lu:%02u ", t/60, (unsigned) t%60);
|
|
||||||
else
|
|
||||||
fprintf(fout, " %2lu.%02us", t, centi_sec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**** stat the device file to get an idle time */
|
/* 7 character formatted login time */
|
||||||
static time_t idletime(const char *restrict const tty) {
|
|
||||||
struct stat sbuf;
|
static void print_logintime(time_t logt, FILE * fout)
|
||||||
if (stat(tty, &sbuf) != 0)
|
{
|
||||||
return 0;
|
char weekday[][4] = {
|
||||||
return time(NULL) - sbuf.st_atime;
|
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||||
|
};
|
||||||
|
char month[][4] = {
|
||||||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
|
||||||
|
"Sep", "Oct", "Nov", "Dec"
|
||||||
|
};
|
||||||
|
time_t curt;
|
||||||
|
struct tm *logtm, *curtm;
|
||||||
|
int today;
|
||||||
|
|
||||||
|
curt = time(NULL);
|
||||||
|
curtm = localtime(&curt);
|
||||||
|
/* localtime returns a pointer to static memory */
|
||||||
|
today = curtm->tm_yday;
|
||||||
|
logtm = localtime(&logt);
|
||||||
|
if (curt - logt > 12 * 60 * 60 && logtm->tm_yday != today) {
|
||||||
|
if (curt - logt > 6 * 24 * 60 * 60)
|
||||||
|
fprintf(fout, " %02d%3s%02d", logtm->tm_mday,
|
||||||
|
month[logtm->tm_mon], logtm->tm_year % 100);
|
||||||
|
else
|
||||||
|
fprintf(fout, " %3s%02d ", weekday[logtm->tm_wday],
|
||||||
|
logtm->tm_hour);
|
||||||
|
} else {
|
||||||
|
fprintf(fout, " %02d:%02d ", logtm->tm_hour, logtm->tm_min);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** 7 character formatted login time */
|
/*
|
||||||
static void print_logintime(time_t logt, FILE* fout) {
|
* This function scans the process table accumulating total cpu
|
||||||
char weekday[][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
|
* times for any processes "associated" with this login session.
|
||||||
month [][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
|
* It also searches for the "best" process to report as "(w)hat"
|
||||||
"Aug", "Sep", "Oct", "Nov", "Dec" };
|
* the user for that login session is doing currently. This the
|
||||||
time_t curt;
|
* essential core of 'w'.
|
||||||
struct tm *logtm, *curtm;
|
|
||||||
int today;
|
|
||||||
|
|
||||||
curt = time(NULL);
|
|
||||||
curtm = localtime(&curt);
|
|
||||||
/* localtime returns a pointer to static memory */
|
|
||||||
today = curtm->tm_yday;
|
|
||||||
logtm = localtime(&logt);
|
|
||||||
if (curt - logt > 12*60*60 && logtm->tm_yday != today) {
|
|
||||||
if (curt - logt > 6*24*60*60)
|
|
||||||
fprintf(fout, " %02d%3s%02d", logtm->tm_mday, month[logtm->tm_mon],
|
|
||||||
logtm->tm_year % 100);
|
|
||||||
else
|
|
||||||
fprintf(fout, " %3s%02d ", weekday[logtm->tm_wday], logtm->tm_hour);
|
|
||||||
} else {
|
|
||||||
fprintf(fout, " %02d:%02d ", logtm->tm_hour, logtm->tm_min);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This function scans the process table accumulating total cpu times for
|
|
||||||
* any processes "associated" with this login session. It also searches
|
|
||||||
* for the "best" process to report as "(w)hat" the user for that login
|
|
||||||
* session is doing currently. This the essential core of 'w'.
|
|
||||||
*/
|
*/
|
||||||
static const proc_t *getproc(const utmp_t *restrict const u, const char *restrict const tty, unsigned long long *restrict const jcpu, int *restrict const found_utpid) {
|
static const proc_t *getproc(const utmp_t * restrict const u,
|
||||||
int line;
|
const char *restrict const tty,
|
||||||
proc_t **pptr = procs;
|
unsigned long long *restrict const jcpu,
|
||||||
const proc_t *best = NULL;
|
int *restrict const found_utpid)
|
||||||
const proc_t *secondbest = NULL;
|
{
|
||||||
unsigned uid = ~0U;
|
int line;
|
||||||
|
proc_t **pptr = procs;
|
||||||
|
const proc_t *best = NULL;
|
||||||
|
const proc_t *secondbest = NULL;
|
||||||
|
unsigned uid = ~0U;
|
||||||
|
|
||||||
*found_utpid = 0;
|
*found_utpid = 0;
|
||||||
if(!ignoreuser){
|
if (!ignoreuser) {
|
||||||
char buf[UT_NAMESIZE+1];
|
char buf[UT_NAMESIZE + 1];
|
||||||
struct passwd *passwd_data; /* pointer to static data */
|
/* pointer to static data */
|
||||||
strncpy(buf,u->ut_user,UT_NAMESIZE);
|
struct passwd *passwd_data;
|
||||||
buf[UT_NAMESIZE] = '\0';
|
strncpy(buf, u->ut_user, UT_NAMESIZE);
|
||||||
passwd_data = getpwnam(buf);
|
buf[UT_NAMESIZE] = '\0';
|
||||||
if(!passwd_data) return NULL;
|
passwd_data = getpwnam(buf);
|
||||||
uid = passwd_data->pw_uid;
|
if (!passwd_data)
|
||||||
/* OK to have passwd_data go out of scope here */
|
return NULL;
|
||||||
}
|
uid = passwd_data->pw_uid;
|
||||||
line = tty_to_dev(tty);
|
/* OK to have passwd_data go out of scope here */
|
||||||
*jcpu = 0;
|
|
||||||
for(; *pptr; pptr++) {
|
|
||||||
const proc_t *restrict const tmp = *pptr;
|
|
||||||
if(unlikely(tmp->tgid == u->ut_pid)) {
|
|
||||||
*found_utpid = 1;
|
|
||||||
best = tmp;
|
|
||||||
}
|
}
|
||||||
if(tmp->tty != line) continue;
|
line = tty_to_dev(tty);
|
||||||
(*jcpu) += tmp->utime + tmp->stime;
|
*jcpu = 0;
|
||||||
secondbest = tmp;
|
for (; *pptr; pptr++) {
|
||||||
/* same time-logic here as for "best" below */
|
const proc_t *restrict const tmp = *pptr;
|
||||||
if(! (secondbest && tmp->start_time <= secondbest->start_time) ){
|
if (unlikely(tmp->tgid == u->ut_pid)) {
|
||||||
secondbest = tmp;
|
*found_utpid = 1;
|
||||||
|
best = tmp;
|
||||||
|
}
|
||||||
|
if (tmp->tty != line)
|
||||||
|
continue;
|
||||||
|
(*jcpu) += tmp->utime + tmp->stime;
|
||||||
|
secondbest = tmp;
|
||||||
|
/* same time-logic here as for "best" below */
|
||||||
|
if (!(secondbest && tmp->start_time <= secondbest->start_time)) {
|
||||||
|
secondbest = tmp;
|
||||||
|
}
|
||||||
|
if (!ignoreuser && uid != tmp->euid && uid != tmp->ruid)
|
||||||
|
continue;
|
||||||
|
if (tmp->pgrp != tmp->tpgid)
|
||||||
|
continue;
|
||||||
|
if (best && tmp->start_time <= best->start_time)
|
||||||
|
continue;
|
||||||
|
best = tmp;
|
||||||
}
|
}
|
||||||
if(!ignoreuser && uid != tmp->euid && uid != tmp->ruid) continue;
|
return best ? best : secondbest;
|
||||||
if(tmp->pgrp != tmp->tpgid) continue;
|
|
||||||
if(best && tmp->start_time <= best->start_time) continue;
|
|
||||||
best = tmp;
|
|
||||||
}
|
|
||||||
return best ? best : secondbest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void showinfo(utmp_t * u, int formtype, int maxcmd, int from,
|
||||||
|
const int userlen, const int fromlen)
|
||||||
|
{
|
||||||
|
unsigned long long jcpu;
|
||||||
|
int ut_pid_found;
|
||||||
|
unsigned i;
|
||||||
|
char uname[USERSZ + 1] = "", tty[5 + sizeof u->ut_line + 1] = "/dev/";
|
||||||
|
const proc_t *best;
|
||||||
|
|
||||||
/***** showinfo */
|
for (i = 0; i < sizeof(u->ut_line); i++)
|
||||||
static void showinfo(utmp_t *u, int formtype, int maxcmd, int from, const int userlen, const int fromlen) {
|
/* clean up tty if garbled */
|
||||||
unsigned long long jcpu;
|
if (isalnum(u->ut_line[i]) || (u->ut_line[i] == '/'))
|
||||||
int ut_pid_found;
|
tty[i + 5] = u->ut_line[i];
|
||||||
unsigned i;
|
else
|
||||||
char uname[USERSZ + 1] = "",
|
tty[i + 5] = '\0';
|
||||||
tty[5 + sizeof u->ut_line + 1] = "/dev/";
|
|
||||||
const proc_t *best;
|
|
||||||
|
|
||||||
for (i=0; i < sizeof(u->ut_line); i++) /* clean up tty if garbled */
|
best = getproc(u, tty + 5, &jcpu, &ut_pid_found);
|
||||||
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);
|
/*
|
||||||
|
* just skip if stale utmp entry (i.e. login proc doesn't
|
||||||
|
* exist). If there is a desire a cmdline flag could be
|
||||||
|
* added to optionally show it with a prefix of (stale)
|
||||||
|
* in front of cmd or something like that.
|
||||||
|
*/
|
||||||
|
if (!ut_pid_found)
|
||||||
|
return;
|
||||||
|
|
||||||
/* just skip if stale utmp entry (i.e. login proc doesn't exist). If there
|
/* force NUL term for printf */
|
||||||
* is a desire a cmdline flag could be added to optionally show it with a
|
strncpy(uname, u->ut_user, USERSZ);
|
||||||
* prefix of (stale) in front of cmd or something like that.
|
|
||||||
*/
|
|
||||||
if (!ut_pid_found)
|
|
||||||
return;
|
|
||||||
|
|
||||||
strncpy(uname, u->ut_user, USERSZ); /* force NUL term for printf */
|
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_host(u->ut_host, sizeof u->ut_host, fromlen);
|
||||||
print_host(u->ut_host, sizeof u->ut_host, 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), stdout);
|
print_time_ival7(jcpu / Hertz, (jcpu % Hertz) * (100. / Hertz),
|
||||||
if (best) {
|
stdout);
|
||||||
unsigned long long pcpu = best->utime + best->stime;
|
if (best) {
|
||||||
print_time_ival7(pcpu/Hertz, (pcpu%Hertz)*(100./Hertz), stdout);
|
unsigned long long pcpu = best->utime + best->stime;
|
||||||
} else
|
print_time_ival7(pcpu / Hertz,
|
||||||
printf(" ? ");
|
(pcpu % Hertz) * (100. / Hertz),
|
||||||
} else {
|
stdout);
|
||||||
printf("%-*.*s%-9.8s", userlen+1, userlen, u->ut_user, u->ut_line);
|
} else
|
||||||
if (from)
|
printf(" ? ");
|
||||||
print_host(u->ut_host, sizeof u->ut_host, fromlen);
|
} else {
|
||||||
if (*u->ut_line == ':') /* idle unknown for xdm logins */
|
printf("%-*.*s%-9.8s", userlen + 1, userlen, u->ut_user,
|
||||||
printf(" ?xdm? ");
|
u->ut_line);
|
||||||
else
|
if (from)
|
||||||
print_time_ival7(idletime(tty), 0, stdout);
|
print_host(u->ut_host, sizeof u->ut_host, fromlen);
|
||||||
}
|
if (*u->ut_line == ':')
|
||||||
fputs(" ", stdout);
|
/* idle unknown for xdm logins */
|
||||||
if (likely(best)) {
|
printf(" ?xdm? ");
|
||||||
char cmdbuf[512];
|
else
|
||||||
escape_command(cmdbuf, best, sizeof cmdbuf, &maxcmd, ESC_ARGS);
|
print_time_ival7(idletime(tty), 0, stdout);
|
||||||
fputs(cmdbuf,stdout);
|
}
|
||||||
} else {
|
fputs(" ", stdout);
|
||||||
printf("-");
|
if (likely(best)) {
|
||||||
}
|
char cmdbuf[512];
|
||||||
fputc('\n', stdout);
|
escape_command(cmdbuf, best, sizeof cmdbuf, &maxcmd, ESC_ARGS);
|
||||||
|
fputs(cmdbuf, stdout);
|
||||||
|
} else {
|
||||||
|
printf("-");
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** main */
|
static void __attribute__ ((__noreturn__))
|
||||||
int main(int argc, char **argv) {
|
usage(FILE * out)
|
||||||
char *user = NULL, *p;
|
{
|
||||||
utmp_t *u;
|
fprintf(out,
|
||||||
struct winsize win;
|
"\nUsage: %s [options]\n"
|
||||||
int header=1, longform=1, from=1, args, maxcmd=80, ch;
|
"\nOptions:\n", program_invocation_short_name);
|
||||||
int userlen = 8;
|
fprintf(out,
|
||||||
int fromlen = 16;
|
" -h, --no-header do not print header\n"
|
||||||
char *env_var;
|
" -u, --no-current ignore current process username\n"
|
||||||
|
" -s, --short short format\n"
|
||||||
|
" -f, --from show remote hostname field\n"
|
||||||
|
" -o, --old-style old style output\n"
|
||||||
|
" --help display this help text\n"
|
||||||
|
" -V, --version display version information and exit\n");
|
||||||
|
fprintf(out, "\nFor more information see w(1).\n");
|
||||||
|
|
||||||
|
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *user = NULL, *p;
|
||||||
|
utmp_t *u;
|
||||||
|
struct winsize win;
|
||||||
|
int header = 1, longform = 1, from = 1, args, maxcmd = 80, ch;
|
||||||
|
int userlen = 8;
|
||||||
|
int fromlen = 16;
|
||||||
|
char *env_var;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HELP_OPTION = CHAR_MAX + 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct option longopts[] = {
|
||||||
|
{"no-header", no_argument, NULL, 'h'},
|
||||||
|
{"no-current", no_argument, NULL, 'u'},
|
||||||
|
{"sort", no_argument, NULL, 's'},
|
||||||
|
{"from", no_argument, NULL, 'f'},
|
||||||
|
{"old-style", no_argument, NULL, 'o'},
|
||||||
|
{"help", no_argument, NULL, HELP_OPTION},
|
||||||
|
{"version", no_argument, NULL, 'V'},
|
||||||
|
{NULL, 0, NULL, 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, "hlusfVo")) != EOF; args++)
|
while ((ch = getopt_long(argc, argv, "hlusfVo", longopts, NULL)) != -1)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'h': header = 0; break;
|
case 'h':
|
||||||
case 'l': longform = 1; break;
|
header = 0;
|
||||||
case 's': longform = 0; break;
|
break;
|
||||||
case 'f': from = !from; break;
|
case 'l':
|
||||||
case 'V': display_version(); exit(0);
|
longform = 1;
|
||||||
case 'u': ignoreuser = 1; break;
|
break;
|
||||||
case 'o': oldstyle = 1; break;
|
case 's':
|
||||||
default:
|
longform = 0;
|
||||||
printf("usage: w -hlsufV [user]\n"
|
break;
|
||||||
" -h skip header\n"
|
case 'f':
|
||||||
" -l long listing (default)\n"
|
from = !from;
|
||||||
" -s short listing\n"
|
break;
|
||||||
" -u ignore uid of processes\n"
|
case 'V':
|
||||||
" -f toggle FROM field (default %s)\n"
|
display_version();
|
||||||
" -o old-style output\n"
|
exit(0);
|
||||||
" -V display version\n", FROM_STRING);
|
case 'u':
|
||||||
exit(1);
|
ignoreuser = 1;
|
||||||
}
|
break;
|
||||||
|
case 'o':
|
||||||
|
oldstyle = 1;
|
||||||
|
break;
|
||||||
|
case HELP_OPTION:
|
||||||
|
usage(stdout);
|
||||||
|
default:
|
||||||
|
usage(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
if ((argv[optind]))
|
if ((argv[optind]))
|
||||||
user = (argv[optind]);
|
user = (argv[optind]);
|
||||||
|
|
||||||
/* Get user field length from environment */
|
/* Get user field length from environment */
|
||||||
if ( (env_var = getenv("PROCPS_USERLEN")) != NULL) {
|
if ((env_var = getenv("PROCPS_USERLEN")) != NULL) {
|
||||||
userlen = atoi(env_var);
|
userlen = atoi(env_var);
|
||||||
if (userlen < 8 || userlen > USERSZ) {
|
if (userlen < 8 || userlen > USERSZ) {
|
||||||
fprintf(stderr, "User length environment PROCPS_USERLEN must be between 8 and %d, ignoring.\n", USERSZ);
|
warnx
|
||||||
userlen=8;
|
("User length environment PROCPS_USERLEN must be between 8 and %d, ignoring.\n",
|
||||||
}
|
USERSZ);
|
||||||
|
userlen = 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Get from field length from environment */
|
/* Get from field length from environment */
|
||||||
if ( (env_var = getenv("PROCPS_FROMLEN")) != NULL) {
|
if ((env_var = getenv("PROCPS_FROMLEN")) != NULL) {
|
||||||
fromlen = atoi(env_var);
|
fromlen = atoi(env_var);
|
||||||
if (fromlen < 8 || fromlen > HOSTSZ) {
|
if (fromlen < 8 || fromlen > HOSTSZ) {
|
||||||
fprintf(stderr, "From length environment PROCPS_FROMLEN must be between 8 and %d, ignoring.\n", HOSTSZ);
|
warnx
|
||||||
fromlen=16;
|
("From length environment PROCPS_FROMLEN must be between 8 and %d, ignoring.\n",
|
||||||
}
|
HOSTSZ);
|
||||||
|
fromlen = 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 0)
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1 && win.ws_col > 0)
|
||||||
maxcmd = win.ws_col;
|
maxcmd = win.ws_col;
|
||||||
else if (p = getenv("COLUMNS"))
|
else if (p = getenv("COLUMNS"))
|
||||||
maxcmd = atoi(p);
|
maxcmd = atoi(p);
|
||||||
else
|
|
||||||
maxcmd = 80;
|
|
||||||
if (maxcmd < 71) {
|
|
||||||
fprintf(stderr, "%d column window is too narrow\n", maxcmd);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
maxcmd -= 21 + userlen + (from ? fromlen : 0) + (longform ? 20 : 0);
|
|
||||||
if (maxcmd < 3)
|
|
||||||
fprintf(stderr, "warning: screen width %d suboptimal.\n", win.ws_col);
|
|
||||||
|
|
||||||
procs = readproctab(PROC_FILLCOM | PROC_FILLUSR | PROC_FILLSTAT);
|
|
||||||
|
|
||||||
if (header) { /* print uptime and headers */
|
|
||||||
print_uptime();
|
|
||||||
printf("%-*s TTY ",userlen,"USER");
|
|
||||||
if (from)
|
|
||||||
printf("FROM ");
|
|
||||||
if (longform)
|
|
||||||
printf(" LOGIN@ IDLE JCPU PCPU WHAT\n");
|
|
||||||
else
|
else
|
||||||
printf(" IDLE WHAT\n");
|
maxcmd = 80;
|
||||||
}
|
if (maxcmd < 71)
|
||||||
|
errx(EXIT_FAILURE, "%d column window is too narrow", maxcmd);
|
||||||
|
|
||||||
utmpname(UTMP_FILE);
|
maxcmd -= 21 + userlen + (from ? fromlen : 0) + (longform ? 20 : 0);
|
||||||
setutent();
|
if (maxcmd < 3)
|
||||||
if (user) {
|
warnx("warning: screen width %d suboptimal", win.ws_col);
|
||||||
for (;;) {
|
|
||||||
u = getutent();
|
|
||||||
if (unlikely(!u)) break;
|
|
||||||
if (u->ut_type != USER_PROCESS) continue;
|
|
||||||
if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from, userlen, fromlen);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (;;) {
|
|
||||||
u = getutent();
|
|
||||||
if (unlikely(!u)) break;
|
|
||||||
if (u->ut_type != USER_PROCESS) continue;
|
|
||||||
if (*u->ut_user) showinfo(u, longform, maxcmd, from, userlen, fromlen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endutent();
|
|
||||||
|
|
||||||
return 0;
|
procs = readproctab(PROC_FILLCOM | PROC_FILLUSR | PROC_FILLSTAT);
|
||||||
|
|
||||||
|
if (header) {
|
||||||
|
/* print uptime and headers */
|
||||||
|
print_uptime();
|
||||||
|
printf("%-*s TTY ", userlen, "USER");
|
||||||
|
if (from)
|
||||||
|
printf("FROM ");
|
||||||
|
if (longform)
|
||||||
|
printf(" LOGIN@ IDLE JCPU PCPU WHAT\n");
|
||||||
|
else
|
||||||
|
printf(" IDLE WHAT\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
utmpname(UTMP_FILE);
|
||||||
|
setutent();
|
||||||
|
if (user) {
|
||||||
|
for (;;) {
|
||||||
|
u = getutent();
|
||||||
|
if (unlikely(!u))
|
||||||
|
break;
|
||||||
|
if (u->ut_type != USER_PROCESS)
|
||||||
|
continue;
|
||||||
|
if (!strncmp(u->ut_user, user, USERSZ))
|
||||||
|
showinfo(u, longform, maxcmd, from, userlen,
|
||||||
|
fromlen);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (;;) {
|
||||||
|
u = getutent();
|
||||||
|
if (unlikely(!u))
|
||||||
|
break;
|
||||||
|
if (u->ut_type != USER_PROCESS)
|
||||||
|
continue;
|
||||||
|
if (*u->ut_user)
|
||||||
|
showinfo(u, longform, maxcmd, from, userlen,
|
||||||
|
fromlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endutent();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user