Import NetBSD w(1) and uptime(1)
Change-Id: Id6cc36f4befbce4be3a471ae920d75972a44bef1
This commit is contained in:
parent
61df9b64d1
commit
11eaad3501
13 changed files with 1611 additions and 1 deletions
98
bin/ps/extern.h
Normal file
98
bin/ps/extern.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* $NetBSD: extern.h,v 1.33 2010/05/31 03:18:33 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.3 (Berkeley) 4/2/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* We expect to be included by ps.h, which will already have
|
||||
* defined the types we use.
|
||||
*/
|
||||
|
||||
extern double ccpu;
|
||||
extern int eval, fscale, mempages, nlistread, rawcpu, maxslp, uspace;
|
||||
extern int sumrusage, termwidth, totwidth;
|
||||
extern int needenv, needcomm, commandonly;
|
||||
extern uid_t myuid;
|
||||
extern kvm_t *kd;
|
||||
extern VAR var[];
|
||||
extern VARLIST displaylist;
|
||||
extern VARLIST sortlist;
|
||||
|
||||
void command(void *, VARENT *, int);
|
||||
void cpuid(void *, VARENT *, int);
|
||||
void cputime(void *, VARENT *, int);
|
||||
int donlist(void);
|
||||
int donlist_sysctl(void);
|
||||
void fmt_puts(char *, int *);
|
||||
void fmt_putc(int, int *);
|
||||
void elapsed(void *, VARENT *, int);
|
||||
double getpcpu(const struct kinfo_proc2 *);
|
||||
double getpmem(const struct kinfo_proc2 *);
|
||||
void gname(void *, VARENT *, int);
|
||||
void groups(void *, VARENT *, int);
|
||||
void groupnames(void *, VARENT *, int);
|
||||
void logname(void *, VARENT *, int);
|
||||
void longtname(void *, VARENT *, int);
|
||||
void lname(void *, VARENT *, int);
|
||||
void lstarted(void *, VARENT *, int);
|
||||
void lstate(void *, VARENT *, int);
|
||||
void maxrss(void *, VARENT *, int);
|
||||
void nlisterr(struct nlist *);
|
||||
void p_rssize(void *, VARENT *, int);
|
||||
void pagein(void *, VARENT *, int);
|
||||
void parsefmt(const char *);
|
||||
void parsefmt_insert(const char *, VARENT **);
|
||||
void parsesort(const char *);
|
||||
VARENT * varlist_find(VARLIST *, const char *);
|
||||
void emul(void *, VARENT *, int);
|
||||
void pcpu(void *, VARENT *, int);
|
||||
void pmem(void *, VARENT *, int);
|
||||
void pnice(void *, VARENT *, int);
|
||||
void pri(void *, VARENT *, int);
|
||||
void printheader(void);
|
||||
void putimeval(void *, VARENT *, int);
|
||||
void pvar(void *, VARENT *, int);
|
||||
void rgname(void *, VARENT *, int);
|
||||
void rssize(void *, VARENT *, int);
|
||||
void runame(void *, VARENT *, int);
|
||||
void showkey(void);
|
||||
void started(void *, VARENT *, int);
|
||||
void state(void *, VARENT *, int);
|
||||
void svgname(void *, VARENT *, int);
|
||||
void svuname(void *, VARENT *, int);
|
||||
void tdev(void *, VARENT *, int);
|
||||
void tname(void *, VARENT *, int);
|
||||
void tsize(void *, VARENT *, int);
|
||||
void ucomm(void *, VARENT *, int);
|
||||
void uname(void *, VARENT *, int);
|
||||
void uvar(void *, VARENT *, int);
|
||||
void vsize(void *, VARENT *, int);
|
||||
void wchan(void *, VARENT *, int);
|
60
bin/ps/fmt.c
Normal file
60
bin/ps/fmt.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* $NetBSD: fmt.c,v 1.21 2007/12/12 22:55:43 lukem Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: fmt.c,v 1.21 2007/12/12 22:55:43 lukem Exp $");
|
||||
|
||||
#include <kvm.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <vis.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include "ps.h"
|
||||
|
||||
void
|
||||
fmt_puts(char *s, int *leftp)
|
||||
{
|
||||
static char *v = 0;
|
||||
static int maxlen = 0;
|
||||
char *nv;
|
||||
int len, nlen;
|
||||
|
||||
if (*leftp == 0)
|
||||
return;
|
||||
len = strlen(s) * 4 + 1;
|
||||
if (len > maxlen) {
|
||||
if (maxlen == 0)
|
||||
nlen = getpagesize();
|
||||
else
|
||||
nlen = maxlen;
|
||||
while (len > nlen)
|
||||
nlen *= 2;
|
||||
nv = realloc(v, nlen);
|
||||
if (nv == 0)
|
||||
return;
|
||||
v = nv;
|
||||
maxlen = nlen;
|
||||
}
|
||||
len = strvis(v, s, VIS_TAB | VIS_NL | VIS_CSTYLE);
|
||||
if (*leftp != -1) {
|
||||
if (len > *leftp) {
|
||||
v[*leftp] = '\0';
|
||||
*leftp = 0;
|
||||
} else
|
||||
*leftp -= len;
|
||||
}
|
||||
(void)printf("%s", v);
|
||||
}
|
||||
|
||||
void
|
||||
fmt_putc(int c, int *leftp)
|
||||
{
|
||||
|
||||
if (*leftp == 0)
|
||||
return;
|
||||
if (*leftp != -1)
|
||||
*leftp -= 1;
|
||||
putchar(c);
|
||||
}
|
94
bin/ps/ps.h
Normal file
94
bin/ps/ps.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* $NetBSD: ps.h,v 1.26 2006/10/02 17:54:35 apb Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ps.h 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define UNLIMITED 0 /* unlimited terminal width */
|
||||
|
||||
#define PRINTMODE 0 /* print values */
|
||||
#define WIDTHMODE 1 /* determine width of column */
|
||||
|
||||
enum type {
|
||||
UNSPECIFIED,
|
||||
CHAR, UCHAR, SHORT, USHORT, INT, UINT, LONG, ULONG,
|
||||
KPTR, KPTR24, INT32, UINT32, SIGLIST, INT64, UINT64,
|
||||
TIMEVAL, CPUTIME, PCPU, VSIZE
|
||||
};
|
||||
|
||||
/* Variables. */
|
||||
typedef SIMPLEQ_HEAD(varlist, varent) VARLIST;
|
||||
|
||||
typedef struct varent {
|
||||
SIMPLEQ_ENTRY(varent) next;
|
||||
struct var *var;
|
||||
} VARENT;
|
||||
|
||||
typedef struct var {
|
||||
const char *name; /* name(s) of variable */
|
||||
const char *header; /* header, possibly changed from default */
|
||||
#define COMM 0x01 /* needs exec arguments and environment (XXX) */
|
||||
#define ARGV0 0x02 /* only print argv[0] */
|
||||
#define LJUST 0x04 /* left adjust on output (trailing blanks) */
|
||||
#define INF127 0x08 /* 127 = infinity: if > 127, print 127. */
|
||||
#define LWP 0x10 /* dispatch to kinfo_lwp routine */
|
||||
#define UAREA 0x20 /* need to check p_uvalid */
|
||||
#define ALIAS 0x40 /* entry is alias for 'header' */
|
||||
u_int flag;
|
||||
/* output routine */
|
||||
void (*oproc)(void *, struct varent *, int);
|
||||
/*
|
||||
* The following (optional) elements are hooks for passing information
|
||||
* to the generic output routine: pvar (that which prints simple
|
||||
* elements from struct kinfo_proc2).
|
||||
*/
|
||||
int off; /* offset in structure */
|
||||
enum type type; /* type of element */
|
||||
const char *fmt; /* printf format */
|
||||
|
||||
/* current longest element */
|
||||
int width; /* printing width */
|
||||
int64_t longestp; /* longest positive signed value */
|
||||
int64_t longestn; /* longest negative signed value */
|
||||
u_int64_t longestu; /* longest unsigned value */
|
||||
double longestpd; /* longest positive double */
|
||||
double longestnd; /* longest negative double */
|
||||
} VAR;
|
||||
|
||||
#define OUTPUT(vent, ki, kl, mode) do { \
|
||||
if ((vent)->var->flag & LWP) \
|
||||
((vent)->var->oproc)((void *)(kl), (vent), (mode)); \
|
||||
else \
|
||||
((vent)->var->oproc)((void *)(ki), (vent), (mode)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#include "extern.h"
|
|
@ -538,6 +538,7 @@
|
|||
./usr/bin/unxz minix-sys
|
||||
./usr/bin/unzip minix-sys
|
||||
./usr/bin/update minix-sys
|
||||
./usr/bin/uptime minix-sys
|
||||
./usr/bin/users minix-sys
|
||||
./usr/bin/uud minix-sys
|
||||
./usr/bin/uudecode minix-sys
|
||||
|
@ -549,6 +550,7 @@
|
|||
./usr/bin/view minix-sys
|
||||
./usr/bin/vis minix-sys
|
||||
./usr/bin/vol minix-sys
|
||||
./usr/bin/w minix-sys
|
||||
./usr/bin/wall minix-sys
|
||||
./usr/bin/wc minix-sys
|
||||
./usr/bin/what minix-sys
|
||||
|
@ -2529,6 +2531,7 @@
|
|||
./usr/man/man1/unvis.1 minix-sys
|
||||
./usr/man/man1/unxz.1 minix-sys
|
||||
./usr/man/man1/unzip.1 minix-sys
|
||||
./usr/man/man1/uptime.1 minix-sys
|
||||
./usr/man/man1/users.1 minix-sys
|
||||
./usr/man/man1/uud.1 minix-sys
|
||||
./usr/man/man1/uue.1 minix-sys
|
||||
|
@ -2537,6 +2540,7 @@
|
|||
./usr/man/man1/view.1 minix-sys
|
||||
./usr/man/man1/vis.1 minix-sys
|
||||
./usr/man/man1/vol.1 minix-sys
|
||||
./usr/man/man1/w.1 minix-sys
|
||||
./usr/man/man1/wait.1 minix-sys
|
||||
./usr/man/man1/wall.1 minix-sys
|
||||
./usr/man/man1/wc.1 minix-sys
|
||||
|
|
253
minix/usr.bin/w/minix_proc.c
Normal file
253
minix/usr.bin/w/minix_proc.c
Normal file
|
@ -0,0 +1,253 @@
|
|||
/* MINIX3 implementations of a subset of some BSD-kernel-specific functions. */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/sysctl.h> /* for KERN_PROC_ */
|
||||
|
||||
#include <minix/paths.h>
|
||||
#include <minix/procfs.h>
|
||||
|
||||
#include "minix_proc.h"
|
||||
|
||||
/*
|
||||
* Parse a procfs psinfo file, and fill the given minix_proc structure with the
|
||||
* results. Return 1 on success, or 0 if this process should be skipped.
|
||||
*/
|
||||
static int
|
||||
parse_psinfo(FILE *fp, int op, int __unused arg, pid_t pid,
|
||||
struct minix_proc *p)
|
||||
{
|
||||
char type, state, pstate, name[256];
|
||||
unsigned int uid, pgrp, dev;
|
||||
int version;
|
||||
|
||||
assert(op == KERN_PROC_ALL); /* this is all we support right now */
|
||||
|
||||
if (fscanf(fp, "%d", &version) != 1 || version != PSINFO_VERSION)
|
||||
return 0;
|
||||
|
||||
if (fscanf(fp, " %c %*d %255s %c %*d %*d %*u %*u %*u %*u",
|
||||
&type, name, &state) != 3)
|
||||
return 0;
|
||||
|
||||
if (type != TYPE_USER)
|
||||
return 0; /* user processes only */
|
||||
|
||||
if (fscanf(fp, " %*u %*u %*u %c %*d %u %*u %u %*d %*c %*d %u",
|
||||
&pstate, &uid, &pgrp, &dev) != 4)
|
||||
return 0;
|
||||
|
||||
/* The fields as expected by the main w(1) code. */
|
||||
p->p_pid = pid;
|
||||
p->p__pgid = (pid_t)pgrp;
|
||||
p->p_tpgid = (dev != 0) ? (pid_t)pgrp : 0;
|
||||
p->p_tdev = (dev_t)dev;
|
||||
strlcpy(p->p_comm, name, sizeof(p->p_comm));
|
||||
|
||||
/* Some fields we need for ranking ("sorting") processes later. */
|
||||
p->p_minix_state = state;
|
||||
p->p_minix_pstate = pstate;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The w(1)-specific implementation of kvm_getproc2. Return an array of
|
||||
* process information structures (of type minix_proc), along with the number
|
||||
* of processes in the resulting array. Return NULL on failure, in which case
|
||||
* errno should be set to something meaningful.
|
||||
*/
|
||||
struct minix_proc *
|
||||
minix_getproc(void * __unused dummy, int op, int arg, int elemsize, int *cnt)
|
||||
{
|
||||
struct minix_proc *procs;
|
||||
char path[PATH_MAX];
|
||||
DIR *dp;
|
||||
FILE *fp;
|
||||
struct dirent *de;
|
||||
pid_t pid, *pids;
|
||||
unsigned int i, npids, size;
|
||||
int e;
|
||||
|
||||
assert(elemsize == sizeof(struct minix_proc));
|
||||
|
||||
/*
|
||||
* First see how much memory we will need in order to store the actual
|
||||
* process data. We store the PIDs in a (relatively small) allocated
|
||||
* memory area immediately, so that we don't have to reiterate through
|
||||
* the /proc directory twice.
|
||||
*/
|
||||
if ((dp = opendir(_PATH_PROC)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((pids = malloc(size = sizeof(pid_t) * 64)) == NULL) {
|
||||
e = errno;
|
||||
closedir(dp);
|
||||
errno = e;
|
||||
return NULL;
|
||||
}
|
||||
npids = 0;
|
||||
|
||||
while ((de = readdir(dp)) != NULL) {
|
||||
if ((pid = (pid_t)atoi(de->d_name)) > 0) {
|
||||
if (sizeof(pid_t) * npids == size &&
|
||||
(pids = realloc(pids, size *= 2)) == NULL)
|
||||
break;
|
||||
pids[npids++] = pid;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
|
||||
/* No results, or out of memory? Then bail out. */
|
||||
if (npids == 0 || pids == NULL) {
|
||||
if (pids != NULL) {
|
||||
e = errno;
|
||||
free(pids);
|
||||
errno = e;
|
||||
} else
|
||||
errno = ENOENT; /* no processes found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now obtain actual process data for the PIDs we obtained. */
|
||||
if ((procs = malloc(sizeof(struct minix_proc) * npids)) == NULL) {
|
||||
e = errno;
|
||||
free(pids);
|
||||
errno = e;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*cnt = 0;
|
||||
for (i = 0; i < npids; i++) {
|
||||
pid = pids[i];
|
||||
|
||||
snprintf(path, sizeof(path), _PATH_PROC "/%u/psinfo", pid);
|
||||
|
||||
/* Processes may legitimately disappear between calls. */
|
||||
if ((fp = fopen(path, "r")) == NULL)
|
||||
continue;
|
||||
|
||||
if (parse_psinfo(fp, op, arg, pid, &procs[*cnt]))
|
||||
(*cnt)++;
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
free(pids);
|
||||
|
||||
/* The returned data is not freed, but we are called only once. */
|
||||
return procs;
|
||||
}
|
||||
|
||||
/*
|
||||
* A w(1)-specific MINIX3 implementation of kvm_getargv2. Return an array of
|
||||
* strings representing the command line of the given process, optionally (if
|
||||
* not 0) limited to a number of printable characters if the arguments were
|
||||
* to be printed with a space in between. Return NULL on failure. Since the
|
||||
* caller will not use earlier results after calling this function again, we
|
||||
* can safely return static results.
|
||||
*/
|
||||
char **
|
||||
minix_getargv(void * __unused dummy, const struct minix_proc * p, int nchr)
|
||||
{
|
||||
#define MAX_ARGS 32
|
||||
static char *argv[MAX_ARGS+1], buf[4096];
|
||||
char path[PATH_MAX];
|
||||
ssize_t i, bytes;
|
||||
int fd, argc;
|
||||
|
||||
/* Get the command line of the process from procfs. */
|
||||
snprintf(path, sizeof(path), _PATH_PROC "/%u/cmdline", p->p_pid);
|
||||
|
||||
if ((fd = open(path, O_RDONLY)) < 0)
|
||||
return NULL;
|
||||
|
||||
bytes = read(fd, buf, sizeof(buf));
|
||||
|
||||
close(fd);
|
||||
|
||||
if (bytes <= 0)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Construct an array of arguments. Stop whenever we run out of bytes
|
||||
* or printable characters (simply counting the null characters as
|
||||
* spaces), or whenever we fill up our argument array. Note that this
|
||||
* is security-sensitive code, as it effectively processes (mostly-)
|
||||
* arbitrary input from other users.
|
||||
*/
|
||||
bytes--; /* buffer should/will be null terminated */
|
||||
if (nchr != 0 && bytes > nchr)
|
||||
bytes = nchr;
|
||||
argc = 0;
|
||||
for (i = 0; i < bytes && argc < MAX_ARGS; i++) {
|
||||
if (i == 0 || buf[i-1] == 0)
|
||||
argv[argc++] = &buf[i];
|
||||
}
|
||||
buf[i] = 0;
|
||||
argv[argc] = NULL;
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
/*
|
||||
* A w(1)-specific implementation of proc_compare_wrapper. Return 0 if the
|
||||
* first given process is more worthy of being shown as the representative
|
||||
* process of what a user is doing, or 1 for the second process. Since procfs
|
||||
* currently does not expose enough information to do this well, we use some
|
||||
* very basic heuristics, and leave a proper implementation to future work.
|
||||
*/
|
||||
int
|
||||
minix_proc_compare(const struct minix_proc * p1, const struct minix_proc * p2)
|
||||
{
|
||||
static const int state_prio[] = /* best to worst */
|
||||
{ STATE_RUN, STATE_WAIT, STATE_SLEEP, STATE_STOP, STATE_ZOMBIE };
|
||||
unsigned int i;
|
||||
int sp1 = -1, sp2 = -1;
|
||||
|
||||
if (p1 == NULL) return 1;
|
||||
if (p2 == NULL) return 0;
|
||||
|
||||
/*
|
||||
* Pick any runnable candidate over a waiting candidate, any waiting
|
||||
* candidate over a sleeping candidate, etcetera. The rationale is
|
||||
* roughly as follows: runnable means that something is definitely
|
||||
* happening; waiting means that probably something interesting is
|
||||
* happening, which eliminates e.g. shells; sleeping means that not
|
||||
* much is going on; stopped and zombified means that definitely
|
||||
* nothing is going on.
|
||||
*/
|
||||
for (i = 0; i < sizeof(state_prio) / sizeof(state_prio[0]); i++) {
|
||||
if (p1->p_minix_state == state_prio[i]) sp1 = i;
|
||||
if (p2->p_minix_state == state_prio[i]) sp2 = i;
|
||||
}
|
||||
if (sp1 != sp2)
|
||||
return (sp1 > sp2);
|
||||
|
||||
/*
|
||||
* Pick any non-PM-sleeping process over any PM-sleeping process.
|
||||
* Here the rationale is that PM-sleeping processes are typically
|
||||
* waiting for another process, which means that the other process is
|
||||
* probably more worthy of reporting. Again, the shell is an example
|
||||
* of a process we'd rather not report if there's something else.
|
||||
*/
|
||||
if (sp1 == STATE_SLEEP) {
|
||||
if (p1->p_minix_pstate != PSTATE_NONE) return 1;
|
||||
if (p2->p_minix_pstate != PSTATE_NONE) return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick the candidate with the largest PID. The rationale is that
|
||||
* statistically that will most likely yield the most recently spawned
|
||||
* process, which makes it the most interesting process as well.
|
||||
*/
|
||||
return p1->p_pid < p2->p_pid;
|
||||
}
|
47
minix/usr.bin/w/minix_proc.h
Normal file
47
minix/usr.bin/w/minix_proc.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef _W_MINIX_PROC_H
|
||||
#define _W_MINIX_PROC_H
|
||||
|
||||
/*
|
||||
* This header file is tailored very specifically to the needs of w(1), which
|
||||
* needs process information but uses a BSD infrastructure (namely, the Kernel
|
||||
* Data Access Library or, eh, KVM.. huh?) which we cannot implement in MINIX3
|
||||
* without making a very, very large number of changes all over the place.
|
||||
*
|
||||
* In order to allow w(1) to function on MINIX3, we override some of the KVM
|
||||
* functionality with MINIX3 implementations, by means of #defines. While that
|
||||
* is indeed butt ugly, this approach does have advantages: we are able to
|
||||
* implement the full expected functionality with minimal changes to w(1)
|
||||
* itself, and whenever w(1) uses a KVM function or a process information field
|
||||
* that this header does not supply, w(1) will break during compilation.
|
||||
*/
|
||||
|
||||
struct minix_proc {
|
||||
pid_t p_pid; /* process ID */
|
||||
pid_t p__pgid; /* process group ID */
|
||||
pid_t p_tpgid; /* tty process group ID (= p_pgid or 0) */
|
||||
dev_t p_tdev; /* controlling terminal (= tty rdev or 0) */
|
||||
char p_minix_state; /* minix specific: process kernel state */
|
||||
char p_minix_pstate; /* minix specific: process PM state */
|
||||
char p_comm[256]; /* simple command line (= process name) */
|
||||
};
|
||||
#undef kinfo_proc2
|
||||
#define kinfo_proc2 minix_proc
|
||||
|
||||
struct minix_proc *minix_getproc(void *dummy, int op, int arg, int elemsize,
|
||||
int *cnt);
|
||||
#undef kvm_getproc2
|
||||
#define kvm_getproc2 minix_getproc
|
||||
|
||||
#undef kvm_geterr
|
||||
#define kvm_geterr(dummy) strerror(errno)
|
||||
|
||||
char **minix_getargv(void *dummy, const struct minix_proc *p, int nchr);
|
||||
#undef kvm_getargv2
|
||||
#define kvm_getargv2 minix_getargv
|
||||
|
||||
int minix_proc_compare(const struct minix_proc *p1,
|
||||
const struct minix_proc *p2);
|
||||
#undef proc_compare_wrapper
|
||||
#define proc_compare_wrapper minix_proc_compare
|
||||
|
||||
#endif /* !_W_MINIX_PROC_H */
|
|
@ -29,7 +29,7 @@ SUBDIR= asa \
|
|||
tr true tsort tty ul uname unexpand unifdef \
|
||||
uniq units unvis unzip users \
|
||||
uuidgen vis \
|
||||
\
|
||||
w \
|
||||
wall wc what whereis who whois \
|
||||
write xargs xinstall xstr yes
|
||||
|
||||
|
|
24
usr.bin/w/Makefile
Normal file
24
usr.bin/w/Makefile
Normal file
|
@ -0,0 +1,24 @@
|
|||
# $NetBSD: Makefile,v 1.21 2011/10/21 02:26:09 christos Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= w
|
||||
SRCS= fmt.c pr_time.c w.c
|
||||
MAN= w.1 uptime.1
|
||||
.if defined(__MINIX)
|
||||
.PATH: ${NETBSDSRCDIR}/minix/usr.bin/w
|
||||
SRCS+= minix_proc.c
|
||||
CPPFLAGS+= -I${NETBSDSRCDIR}/minix/usr.bin/w
|
||||
.else
|
||||
DPADD= ${LIBKVM} ${LIBUTIL}
|
||||
LDADD= -lkvm -lutil
|
||||
.endif
|
||||
LINKS= ${BINDIR}/w ${BINDIR}/uptime
|
||||
CPPFLAGS+= -DSUPPORT_UTMP -DSUPPORT_UTMPX
|
||||
|
||||
.PATH: ${NETBSDSRCDIR}/bin/ps
|
||||
|
||||
COPTS.pr_time.c += -Wno-format-y2k
|
||||
|
||||
.include <bsd.prog.mk>
|
38
usr.bin/w/extern.h
Normal file
38
usr.bin/w/extern.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* $NetBSD: extern.h,v 1.7 2011/10/21 02:26:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
struct kinfo_proc2;
|
||||
void fmt_puts(char *, int *);
|
||||
void fmt_putc(int, int *);
|
||||
void pr_attime(time_t *, time_t *);
|
||||
void pr_idle(time_t);
|
116
usr.bin/w/pr_time.c
Normal file
116
usr.bin/w/pr_time.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* $NetBSD: pr_time.c,v 1.18 2011/08/17 13:48:11 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pr_time.c 8.2 (Berkeley) 4/4/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pr_time.c,v 1.18 2011/08/17 13:48:11 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* pr_attime --
|
||||
* Print the time since the user logged in.
|
||||
*
|
||||
* Note: SCCS forces the bizarre string manipulation, things like
|
||||
* %I% get replaced in the source code.
|
||||
*/
|
||||
void
|
||||
pr_attime(time_t *started, time_t *now)
|
||||
{
|
||||
static char buf[256];
|
||||
int tnow_yday;
|
||||
struct tm *tp;
|
||||
time_t diff;
|
||||
|
||||
tnow_yday = localtime(now)->tm_yday;
|
||||
tp = localtime(started);
|
||||
diff = *now - *started;
|
||||
|
||||
if (diff > SECSPERDAY * DAYSPERWEEK) {
|
||||
/* If more than a week, use day-month-year. */
|
||||
(void)strftime(buf, sizeof(buf), "%d%b%y", tp);
|
||||
} else if (tp->tm_yday != tnow_yday) {
|
||||
/* If not today, use day-hour-am/pm. Damn SCCS */
|
||||
(void)strftime(buf, sizeof(buf), "%a%" "I%p", tp);
|
||||
} else {
|
||||
/* Default is hh:mm{am,pm}. Damn SCCS */
|
||||
(void)strftime(buf, sizeof(buf), "%l:%" "M%p", tp);
|
||||
}
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
(void)fputs(buf, stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
* pr_idle --
|
||||
* Display the idle time.
|
||||
*/
|
||||
void
|
||||
pr_idle(time_t idle)
|
||||
{
|
||||
int days;
|
||||
|
||||
if (idle == (time_t)-1) {
|
||||
(void)printf(" ? ");
|
||||
return;
|
||||
}
|
||||
|
||||
days = idle / SECSPERDAY;
|
||||
|
||||
/* If idle more than 36 hours, print as a number of days. */
|
||||
if (idle >= 48 * SECSPERHOUR)
|
||||
printf(" %ddays ", days);
|
||||
else if (idle >= 36 * SECSPERHOUR)
|
||||
printf(" 1day ");
|
||||
|
||||
/* If idle more than an hour, print as HH:MM. */
|
||||
else if (idle >= SECSPERHOUR)
|
||||
(void)printf(" %2d:%02d ",
|
||||
(int)(idle / SECSPERHOUR),
|
||||
(int)((idle % SECSPERHOUR) / SECSPERMIN));
|
||||
|
||||
/* Else print the minutes idle. */
|
||||
else
|
||||
(void)printf(" %2d ", (int)(idle / SECSPERMIN));
|
||||
}
|
58
usr.bin/w/uptime.1
Normal file
58
usr.bin/w/uptime.1
Normal file
|
@ -0,0 +1,58 @@
|
|||
.\" $NetBSD: uptime.1,v 1.10 2003/08/07 11:17:13 agc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)uptime.1 8.2 (Berkeley) 4/18/94
|
||||
.\"
|
||||
.Dd April 18, 1994
|
||||
.Dt UPTIME 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm uptime
|
||||
.Nd show how long system has been running
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility displays the current time,
|
||||
the length of time the system has been up,
|
||||
the number of users, and the load average of the system over the last
|
||||
1, 5, and 15 minutes.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /netbsd
|
||||
.It Pa /netbsd
|
||||
system name list
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr w 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 3.0 .
|
126
usr.bin/w/w.1
Normal file
126
usr.bin/w/w.1
Normal file
|
@ -0,0 +1,126 @@
|
|||
.\" $NetBSD: w.1,v 1.18 2005/01/11 09:39:12 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)w.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd January 11, 2005
|
||||
.Dt W 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm w
|
||||
.Nd who present users are and what they are doing
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl hinw
|
||||
.Op Fl M Ar core
|
||||
.Op Fl N Ar system
|
||||
.Op Ar user
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility prints a summary of the current activity on the system,
|
||||
including what each user is doing.
|
||||
The first line displays the current time of day, how long the system has
|
||||
been running, the number of users logged into the system, and the load
|
||||
averages.
|
||||
The load average numbers give the number of jobs in the run queue averaged
|
||||
over 1, 5, and 15 minutes.
|
||||
.Pp
|
||||
The fields output are the user's login name, the name of the terminal the
|
||||
user is on, the host from which the user is logged in, the time the user
|
||||
logged on, the time since the user last typed anything,
|
||||
and the name and arguments of the current process.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl h
|
||||
Suppress the heading.
|
||||
.It Fl i
|
||||
Output is sorted by idle time.
|
||||
.It Fl M
|
||||
Extract values associated with the name list from the specified
|
||||
core instead of the default
|
||||
.Dq /dev/kmem .
|
||||
.It Fl N
|
||||
Extract the name list from the specified system instead of the
|
||||
default
|
||||
.Dq /netbsd .
|
||||
.It Fl n
|
||||
Show network addresses as numbers (normally
|
||||
.Nm
|
||||
interprets addresses and attempts to display them symbolically).
|
||||
.It Fl w
|
||||
Show wide output without truncating any fields.
|
||||
.El
|
||||
.Pp
|
||||
If a
|
||||
.Ar user
|
||||
name is specified, the output is restricted to that user.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/run/utmp -compact
|
||||
.It Pa /var/run/utmp
|
||||
list of users on the system
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr finger 1 ,
|
||||
.Xr ps 1 ,
|
||||
.Xr uptime 1 ,
|
||||
.Xr who 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 3.0 .
|
||||
.Sh BUGS
|
||||
The notion of the
|
||||
.Dq current process
|
||||
is muddy.
|
||||
The current algorithm is ``the highest numbered process on the terminal
|
||||
that is not ignoring interrupts, or, if there is none, the highest numbered
|
||||
process on the terminal''.
|
||||
This fails, for example, in critical sections of programs like the shell
|
||||
and editor, or when faulty programs running in the background fork and fail
|
||||
to ignore interrupts.
|
||||
(In cases where no process can be found,
|
||||
.Nm
|
||||
prints
|
||||
.Dq \- . )
|
||||
.Pp
|
||||
Background processes are not shown, even though they account for
|
||||
much of the load on the system.
|
||||
.Pp
|
||||
Sometimes processes, typically those in the background, are printed with
|
||||
null or garbaged arguments.
|
||||
In these cases, the name of the command is printed in parentheses.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility does not know about the new conventions for detection of background
|
||||
jobs.
|
||||
It will sometimes find a background job instead of the right one.
|
692
usr.bin/w/w.c
Normal file
692
usr.bin/w/w.c
Normal file
|
@ -0,0 +1,692 @@
|
|||
/* $NetBSD: w.c,v 1.77 2013/09/09 19:20:38 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)w.c 8.6 (Berkeley) 6/30/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: w.c,v 1.77 2013/09/09 19:20:38 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* w - print system status (who and what)
|
||||
*
|
||||
* This program is similar to the systat command on Tenex/Tops 10/20
|
||||
*
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <nlist.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
#ifdef SUPPORT_UTMP
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMPX
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
#include <vis.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#ifdef __minix
|
||||
/* MINIX3 note: please see this header for information about the port. */
|
||||
#include "minix_proc.h"
|
||||
#endif /* __minix */
|
||||
|
||||
struct timeval boottime;
|
||||
struct winsize ws;
|
||||
kvm_t *kd;
|
||||
time_t now; /* the current time of day */
|
||||
int ttywidth; /* width of tty */
|
||||
int argwidth; /* width of tty left to print process args */
|
||||
int header = 1; /* true if -h flag: don't print heading */
|
||||
int nflag; /* true if -n flag: don't convert addrs */
|
||||
int wflag; /* true if -w flag: wide printout */
|
||||
int sortidle; /* sort bu idle time */
|
||||
char *sel_user; /* login of particular user selected */
|
||||
char domain[MAXHOSTNAMELEN + 1];
|
||||
int maxname = 8, maxline = 3, maxhost = 16;
|
||||
|
||||
/*
|
||||
* One of these per active utmp entry.
|
||||
*/
|
||||
struct entry {
|
||||
struct entry *next;
|
||||
char name[UTX_USERSIZE + 1];
|
||||
char line[UTX_LINESIZE + 1];
|
||||
char host[UTX_HOSTSIZE + 1];
|
||||
char type[2];
|
||||
struct timeval tv;
|
||||
dev_t tdev; /* dev_t of terminal */
|
||||
time_t idle; /* idle time of terminal in seconds */
|
||||
struct kinfo_proc2 *tp; /* `most interesting' tty proc */
|
||||
struct kinfo_proc2 *pp; /* pid proc */
|
||||
pid_t pid; /* pid or ~0 if not known */
|
||||
} *ehead = NULL, **nextp = &ehead;
|
||||
|
||||
static void pr_args(struct kinfo_proc2 *);
|
||||
static void pr_header(time_t *, int);
|
||||
#ifndef __minix
|
||||
static int proc_compare_wrapper(const struct kinfo_proc2 *,
|
||||
const struct kinfo_proc2 *);
|
||||
#endif /* !__minix */
|
||||
#if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
|
||||
static int ttystat(const char *, struct stat *);
|
||||
static void process(struct entry *);
|
||||
#endif
|
||||
static void fixhost(struct entry *ep);
|
||||
__dead static void usage(int);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct kinfo_proc2 *kp;
|
||||
struct entry *ep;
|
||||
int ch, i, nentries, nusers, wcmd, curtain, use_sysctl;
|
||||
char *memf, *nlistf, *usrnp;
|
||||
const char *options;
|
||||
time_t then;
|
||||
#ifndef __minix
|
||||
size_t len;
|
||||
#endif /* !__minix */
|
||||
#ifdef SUPPORT_UTMP
|
||||
struct utmp *ut;
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMPX
|
||||
struct utmpx *utx;
|
||||
#endif
|
||||
const char *progname;
|
||||
#ifndef __minix
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
#endif /* !__minix */
|
||||
|
||||
setprogname(argv[0]);
|
||||
|
||||
/* Are we w(1) or uptime(1)? */
|
||||
progname = getprogname();
|
||||
if (*progname == '-')
|
||||
progname++;
|
||||
if (*progname == 'u') {
|
||||
wcmd = 0;
|
||||
options = "";
|
||||
} else {
|
||||
wcmd = 1;
|
||||
options = "hiM:N:nw";
|
||||
}
|
||||
|
||||
memf = nlistf = NULL;
|
||||
while ((ch = getopt(argc, argv, options)) != -1)
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
header = 0;
|
||||
break;
|
||||
case 'i':
|
||||
sortidle = 1;
|
||||
break;
|
||||
case 'M':
|
||||
header = 0;
|
||||
memf = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
nlistf = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'w':
|
||||
wflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(wcmd);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
use_sysctl = (memf == NULL && nlistf == NULL);
|
||||
|
||||
#ifndef __minix
|
||||
if ((kd = kvm_openfiles(nlistf, memf, NULL,
|
||||
memf == NULL ? KVM_NO_FILES : O_RDONLY, errbuf)) == NULL)
|
||||
errx(1, "%s", errbuf);
|
||||
#else
|
||||
if (!use_sysctl)
|
||||
errx(1, "The -M and -N flags are not supported on MINIX3.");
|
||||
kd = NULL;
|
||||
#endif /* __minix */
|
||||
|
||||
(void)time(&now);
|
||||
|
||||
if (use_sysctl) {
|
||||
#ifndef __minix
|
||||
len = sizeof(curtain);
|
||||
if (sysctlbyname("security.curtain", &curtain, &len,
|
||||
NULL, 0) == -1)
|
||||
#endif /* !__minix */
|
||||
curtain = 0;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_UTMPX
|
||||
setutxent();
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMP
|
||||
setutent();
|
||||
#endif
|
||||
|
||||
if (*argv)
|
||||
sel_user = *argv;
|
||||
|
||||
nusers = 0;
|
||||
#ifdef SUPPORT_UTMPX
|
||||
while ((utx = getutxent()) != NULL) {
|
||||
if (utx->ut_type != USER_PROCESS)
|
||||
continue;
|
||||
++nusers;
|
||||
if (sel_user &&
|
||||
strncmp(utx->ut_name, sel_user, sizeof(utx->ut_name)) != 0)
|
||||
continue;
|
||||
if ((ep = calloc(1, sizeof(struct entry))) == NULL)
|
||||
err(1, NULL);
|
||||
(void)memcpy(ep->name, utx->ut_name, sizeof(utx->ut_name));
|
||||
(void)memcpy(ep->line, utx->ut_line, sizeof(utx->ut_line));
|
||||
ep->name[sizeof(utx->ut_name)] = '\0';
|
||||
ep->line[sizeof(utx->ut_line)] = '\0';
|
||||
if (!nflag || getnameinfo((struct sockaddr *)&utx->ut_ss,
|
||||
utx->ut_ss.ss_len, ep->host, sizeof(ep->host), NULL, 0,
|
||||
NI_NUMERICHOST) != 0) {
|
||||
(void)memcpy(ep->host, utx->ut_host,
|
||||
sizeof(utx->ut_host));
|
||||
ep->host[sizeof(utx->ut_host)] = '\0';
|
||||
}
|
||||
fixhost(ep);
|
||||
ep->type[0] = 'x';
|
||||
ep->tv = utx->ut_tv;
|
||||
ep->pid = utx->ut_pid;
|
||||
*nextp = ep;
|
||||
nextp = &(ep->next);
|
||||
if (wcmd != 0)
|
||||
process(ep);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_UTMP
|
||||
while ((ut = getutent()) != NULL) {
|
||||
if (ut->ut_name[0] == '\0')
|
||||
continue;
|
||||
|
||||
if (sel_user &&
|
||||
strncmp(ut->ut_name, sel_user, sizeof(ut->ut_name)) != 0)
|
||||
continue;
|
||||
|
||||
/* Don't process entries that we have utmpx for */
|
||||
for (ep = ehead; ep != NULL; ep = ep->next) {
|
||||
if (strncmp(ep->line, ut->ut_line,
|
||||
sizeof(ut->ut_line)) == 0)
|
||||
break;
|
||||
}
|
||||
if (ep != NULL)
|
||||
continue;
|
||||
|
||||
++nusers;
|
||||
if ((ep = calloc(1, sizeof(struct entry))) == NULL)
|
||||
err(1, NULL);
|
||||
(void)memcpy(ep->name, ut->ut_name, sizeof(ut->ut_name));
|
||||
(void)memcpy(ep->line, ut->ut_line, sizeof(ut->ut_line));
|
||||
(void)memcpy(ep->host, ut->ut_host, sizeof(ut->ut_host));
|
||||
ep->name[sizeof(ut->ut_name)] = '\0';
|
||||
ep->line[sizeof(ut->ut_line)] = '\0';
|
||||
ep->host[sizeof(ut->ut_host)] = '\0';
|
||||
fixhost(ep);
|
||||
ep->tv.tv_sec = ut->ut_time;
|
||||
*nextp = ep;
|
||||
nextp = &(ep->next);
|
||||
if (wcmd != 0)
|
||||
process(ep);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_UTMPX
|
||||
endutxent();
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMP
|
||||
endutent();
|
||||
#endif
|
||||
|
||||
if (header || wcmd == 0) {
|
||||
pr_header(&now, nusers);
|
||||
if (wcmd == 0)
|
||||
exit (0);
|
||||
}
|
||||
|
||||
if ((kp = kvm_getproc2(kd, KERN_PROC_ALL, 0,
|
||||
sizeof(struct kinfo_proc2), &nentries)) == NULL)
|
||||
errx(1, "%s", kvm_geterr(kd));
|
||||
|
||||
/* Include trailing space because TTY header starts one column early. */
|
||||
for (i = 0; i < nentries; i++, kp++) {
|
||||
|
||||
for (ep = ehead; ep != NULL; ep = ep->next) {
|
||||
if (ep->tdev != 0 && ep->tdev == kp->p_tdev &&
|
||||
kp->p__pgid == kp->p_tpgid) {
|
||||
/*
|
||||
* Proc is in foreground of this
|
||||
* terminal
|
||||
*/
|
||||
if (proc_compare_wrapper(ep->tp, kp))
|
||||
ep->tp = kp;
|
||||
break;
|
||||
}
|
||||
if (ep->pid != 0 && ep->pid == kp->p_pid) {
|
||||
ep->pp = kp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
|
||||
ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
|
||||
ttywidth = 79;
|
||||
else
|
||||
ttywidth = ws.ws_col - 1;
|
||||
|
||||
if (!wflag && maxhost > (ttywidth / 3))
|
||||
maxhost = ttywidth / 3;
|
||||
|
||||
argwidth = printf("%-*s TTY %-*s %*s IDLE WHAT\n",
|
||||
maxname, "USER", maxhost, "FROM",
|
||||
7 /* "dddhhXm" */, "LOGIN@");
|
||||
argwidth -= sizeof("WHAT\n") - 1 /* NUL */;
|
||||
argwidth = ttywidth - argwidth;
|
||||
if (argwidth < 4)
|
||||
argwidth = 8;
|
||||
if (wflag)
|
||||
argwidth = -1;
|
||||
|
||||
/* sort by idle time */
|
||||
if (sortidle && ehead != NULL) {
|
||||
struct entry *from = ehead, *save;
|
||||
|
||||
ehead = NULL;
|
||||
while (from != NULL) {
|
||||
for (nextp = &ehead;
|
||||
(*nextp) && from->idle >= (*nextp)->idle;
|
||||
nextp = &(*nextp)->next)
|
||||
continue;
|
||||
save = from;
|
||||
from = from->next;
|
||||
save->next = *nextp;
|
||||
*nextp = save;
|
||||
}
|
||||
}
|
||||
#if defined(SUPPORT_UTMP) && defined(SUPPORT_UTMPX)
|
||||
else if (ehead != NULL) {
|
||||
struct entry *from = ehead, *save;
|
||||
|
||||
ehead = NULL;
|
||||
while (from != NULL) {
|
||||
for (nextp = &ehead;
|
||||
(*nextp) && strcmp(from->line, (*nextp)->line) > 0;
|
||||
nextp = &(*nextp)->next)
|
||||
continue;
|
||||
save = from;
|
||||
from = from->next;
|
||||
save->next = *nextp;
|
||||
*nextp = save;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!nflag) {
|
||||
int rv;
|
||||
char *p;
|
||||
|
||||
rv = gethostname(domain, sizeof(domain));
|
||||
domain[sizeof(domain) - 1] = '\0';
|
||||
if (rv < 0 || (p = strchr(domain, '.')) == 0)
|
||||
domain[0] = '\0';
|
||||
else
|
||||
memmove(domain, p, strlen(p) + 1);
|
||||
}
|
||||
|
||||
for (ep = ehead; ep != NULL; ep = ep->next) {
|
||||
if (ep->tp != NULL)
|
||||
kp = ep->tp;
|
||||
else if (ep->pp != NULL)
|
||||
kp = ep->pp;
|
||||
else if (ep->pid != 0) {
|
||||
if (curtain)
|
||||
kp = NULL;
|
||||
else {
|
||||
warnx("Stale utmp%s entry: %s %s %s",
|
||||
ep->type, ep->name, ep->line, ep->host);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifndef __minix
|
||||
usrnp = (kp == NULL) ? ep->name : kp->p_login;
|
||||
#else
|
||||
usrnp = ep->name; /* TODO: implement getlogin/setlogin */
|
||||
#endif /* __minix */
|
||||
(void)printf("%-*s %-7.7s %-*.*s ",
|
||||
maxname, usrnp, ep->line,
|
||||
maxhost, maxhost, ep->host);
|
||||
then = (time_t)ep->tv.tv_sec;
|
||||
pr_attime(&then, &now);
|
||||
pr_idle(ep->idle);
|
||||
pr_args(kp);
|
||||
(void)printf("\n");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_args(struct kinfo_proc2 *kp)
|
||||
{
|
||||
char **argv;
|
||||
int left;
|
||||
|
||||
if (kp == 0)
|
||||
goto nothing;
|
||||
left = argwidth;
|
||||
argv = kvm_getargv2(kd, kp, (argwidth < 0) ? 0 : argwidth);
|
||||
if (argv == 0) {
|
||||
if (kp->p_comm == 0) {
|
||||
goto nothing;
|
||||
} else {
|
||||
fmt_putc('(', &left);
|
||||
fmt_puts((char *)kp->p_comm, &left);
|
||||
fmt_putc(')', &left);
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (*argv) {
|
||||
fmt_puts(*argv, &left);
|
||||
argv++;
|
||||
fmt_putc(' ', &left);
|
||||
}
|
||||
return;
|
||||
nothing:
|
||||
putchar('-');
|
||||
}
|
||||
|
||||
static void
|
||||
pr_header(time_t *nowp, int nusers)
|
||||
{
|
||||
double avenrun[3];
|
||||
time_t uptime;
|
||||
int days, hrs, mins;
|
||||
int mib[2];
|
||||
size_t size, i;
|
||||
char buf[256];
|
||||
|
||||
/*
|
||||
* Print time of day.
|
||||
*
|
||||
* SCCS forces the string manipulation below, as it replaces
|
||||
* %, M, and % in a character string with the file name.
|
||||
*/
|
||||
(void)strftime(buf, sizeof(buf), "%l:%" "M%p", localtime(nowp));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
(void)printf("%s ", buf);
|
||||
|
||||
/*
|
||||
* Print how long system has been up.
|
||||
* (Found by looking getting "boottime" from the kernel)
|
||||
*/
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_BOOTTIME;
|
||||
size = sizeof(boottime);
|
||||
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
|
||||
boottime.tv_sec != 0) {
|
||||
uptime = now - boottime.tv_sec;
|
||||
uptime += 30;
|
||||
if (uptime > SECSPERMIN) {
|
||||
days = uptime / SECSPERDAY;
|
||||
uptime %= SECSPERDAY;
|
||||
hrs = uptime / SECSPERHOUR;
|
||||
uptime %= SECSPERHOUR;
|
||||
mins = uptime / SECSPERMIN;
|
||||
(void)printf(" up");
|
||||
if (days > 0)
|
||||
(void)printf(" %d day%s,", days,
|
||||
days > 1 ? "s" : "");
|
||||
if (hrs > 0 && mins > 0)
|
||||
(void)printf(" %2d:%02d,", hrs, mins);
|
||||
else {
|
||||
if (hrs > 0)
|
||||
(void)printf(" %d hr%s,",
|
||||
hrs, hrs > 1 ? "s" : "");
|
||||
if (mins > 0)
|
||||
(void)printf(" %d min%s,",
|
||||
mins, mins > 1 ? "s" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print number of users logged in to system */
|
||||
(void)printf(" %d user%s", nusers, nusers != 1 ? "s" : "");
|
||||
|
||||
/*
|
||||
* Print 1, 5, and 15 minute load averages.
|
||||
*/
|
||||
if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) == -1)
|
||||
(void)printf(", no load average information available\n");
|
||||
else {
|
||||
(void)printf(", load averages:");
|
||||
for (i = 0; i < (sizeof(avenrun) / sizeof(avenrun[0])); i++) {
|
||||
if (i > 0)
|
||||
(void)printf(",");
|
||||
(void)printf(" %.2f", avenrun[i]);
|
||||
}
|
||||
(void)printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
|
||||
static int
|
||||
ttystat(const char *line, struct stat *st)
|
||||
{
|
||||
char ttybuf[MAXPATHLEN];
|
||||
|
||||
(void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line);
|
||||
return stat(ttybuf, st);
|
||||
}
|
||||
|
||||
static void
|
||||
process(struct entry *ep)
|
||||
{
|
||||
struct stat st;
|
||||
time_t touched;
|
||||
int max;
|
||||
|
||||
if ((max = strlen(ep->name)) > maxname)
|
||||
maxname = max;
|
||||
if ((max = strlen(ep->line)) > maxline)
|
||||
maxline = max;
|
||||
if ((max = strlen(ep->host)) > maxhost)
|
||||
maxhost = max;
|
||||
|
||||
ep->tdev = 0;
|
||||
ep->idle = (time_t)-1;
|
||||
|
||||
#ifdef SUPPORT_UTMP
|
||||
/*
|
||||
* Hack to recognize and correctly parse
|
||||
* ut entry made by ftpd. The "tty" used
|
||||
* by ftpd is not a real tty, just identifier in
|
||||
* form ftpPID. Pid parsed from the "tty name"
|
||||
* is used later to match corresponding process.
|
||||
* NB: This is only used for utmp entries. For utmpx,
|
||||
* we already have the pid.
|
||||
*/
|
||||
if (ep->pid == 0 && strncmp(ep->line, "ftp", 3) == 0) {
|
||||
ep->pid = strtol(ep->line + 3, NULL, 10);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (ttystat(ep->line, &st) == -1)
|
||||
return;
|
||||
|
||||
ep->tdev = st.st_rdev;
|
||||
/*
|
||||
* If this is the console device, attempt to ascertain
|
||||
* the true console device dev_t.
|
||||
*/
|
||||
if (ep->tdev == 0) {
|
||||
int mib[2];
|
||||
size_t size;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_CONSDEV;
|
||||
size = sizeof(dev_t);
|
||||
(void) sysctl(mib, 2, &ep->tdev, &size, NULL, 0);
|
||||
}
|
||||
|
||||
touched = st.st_atime;
|
||||
if (touched < ep->tv.tv_sec) {
|
||||
/* tty untouched since before login */
|
||||
touched = ep->tv.tv_sec;
|
||||
}
|
||||
if ((ep->idle = now - touched) < 0)
|
||||
ep->idle = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __minix
|
||||
static int
|
||||
proc_compare_wrapper(const struct kinfo_proc2 *p1,
|
||||
const struct kinfo_proc2 *p2)
|
||||
{
|
||||
struct kinfo_lwp *l1, *l2;
|
||||
int cnt;
|
||||
|
||||
if (p1 == NULL)
|
||||
return 1;
|
||||
|
||||
l1 = kvm_getlwps(kd, p1->p_pid, 0, sizeof(*l1), &cnt);
|
||||
if (l1 == NULL || cnt == 0)
|
||||
return 1;
|
||||
|
||||
l2 = kvm_getlwps(kd, p2->p_pid, 0, sizeof(*l1), &cnt);
|
||||
if (l2 == NULL || cnt == 0)
|
||||
return 0;
|
||||
|
||||
return proc_compare(p1, l1, p2, l2);
|
||||
}
|
||||
#endif /* !__minix */
|
||||
|
||||
static void
|
||||
fixhost(struct entry *ep)
|
||||
{
|
||||
char host_buf[sizeof(ep->host)];
|
||||
char *p, *x;
|
||||
struct hostent *hp;
|
||||
struct in_addr l;
|
||||
|
||||
strlcpy(host_buf, *ep->host ? ep->host : "-", sizeof(host_buf));
|
||||
p = host_buf;
|
||||
|
||||
/*
|
||||
* XXX: Historical behavior, ':' in hostname means X display number,
|
||||
* IPv6 not handled.
|
||||
*/
|
||||
for (x = p; x < &host_buf[sizeof(host_buf)]; x++)
|
||||
if (*x == '\0' || *x == ':')
|
||||
break;
|
||||
if (x == p + sizeof(host_buf) || *x != ':')
|
||||
x = NULL;
|
||||
else
|
||||
*x++ = '\0';
|
||||
|
||||
if (!nflag && inet_aton(p, &l) &&
|
||||
(hp = gethostbyaddr((char *)&l, sizeof(l), AF_INET))) {
|
||||
if (domain[0] != '\0') {
|
||||
p = hp->h_name;
|
||||
p += strlen(hp->h_name);
|
||||
p -= strlen(domain);
|
||||
if (p > hp->h_name &&
|
||||
strcasecmp(p, domain) == 0)
|
||||
*p = '\0';
|
||||
}
|
||||
p = hp->h_name;
|
||||
}
|
||||
|
||||
if (x)
|
||||
(void)snprintf(ep->host, sizeof(ep->host), "%s:%s", p, x);
|
||||
else
|
||||
|
||||
strlcpy(ep->host, p, sizeof(ep->host));
|
||||
}
|
||||
|
||||
static void
|
||||
usage(int wcmd)
|
||||
{
|
||||
|
||||
if (wcmd)
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [-hinw] [-M core] [-N system] [user]\n",
|
||||
getprogname());
|
||||
else
|
||||
(void)fprintf(stderr, "Usage: %s\n", getprogname());
|
||||
exit(1);
|
||||
}
|
Loading…
Reference in a new issue