* Copyright (c) 1980, 1991 The Regents of the University of California.
* %sccs.include.redist.c%
"@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)w.c 5.37 (Berkeley) %G%";
* w - print system status (who and what)
* This program is similar to the systat command on Tenex/Tops 10/20
time_t now
; /* the current time of day */
time_t uptime
; /* time of last reboot & elapsed time since */
int ttywidth
; /* width of tty */
int argwidth
; /* width of tty */
int header
= 1; /* true if -h flag: don't print heading */
int nflag
; /* true if -n flag: don't convert addrs */
int sortidle
; /* sort bu idle time */
char *sel_user
; /* login of particular user selected */
char domain
[MAXHOSTNAMELEN
];
* One of these per active utmp entry.
dev_t tdev
; /* dev_t of terminal */
time_t idle
; /* idle time of terminal in seconds */
struct kinfo_proc
*kp
; /* `most interesting' proc */
char *args
; /* arg list of interesting process */
} *ep
, *ehead
= NULL
, **nextp
= &ehead
;
#if defined(hp300) || defined(i386)
static void pr_header
__P((kvm_t
*, time_t *, int));
static void usage
__P((int));
char *fmt_argv
__P((char **, char *, int));
int ch
, i
, nentries
, nusers
, wcmd
;
char *memf
, *nlistf
, *p
, *x
;
char buf
[MAXHOSTNAMELEN
], errbuf
[256];
/* Are we w(1) or uptime(1)? */
if ((p
= rindex(program
, '/')) || *(p
= program
) == '-')
while ((ch
= getopt(argc
, argv
, p
)) != EOF
)
case 'f': case 'l': case 's': case 'u': case 'w':
warnx("[-flsuw] no longer supported");
if ((kd
= kvm_openfiles(nlistf
, memf
, NULL
, O_RDONLY
, errbuf
)) == NULL
)
if (header
&& kvm_nlist(kd
, nl
) != 0)
err(1, "can't read namelist");
if ((ut
= fopen(_PATH_UTMP
, "r")) == NULL
)
err(1, "%s", _PATH_UTMP
);
for (nusers
= 0; fread(&utmp
, sizeof(utmp
), 1, ut
);) {
if (utmp
.ut_name
[0] == '\0')
if (wcmd
== 0 || (sel_user
&&
strncmp(utmp
.ut_name
, sel_user
, UT_NAMESIZE
) != 0))
if ((ep
= calloc(1, sizeof(struct entry
))) == NULL
)
bcopy(&utmp
, &(ep
->utmp
), sizeof (struct utmp
));
stp
= ttystat(ep
->utmp
.ut_line
);
#if defined(hp300) || defined(i386)
* If this is the console device, attempt to ascertain
* the true console device dev_t.
if (nl
[X_CNTTY
].n_value
) {
struct tty cn_tty
, *cn_ttyp
;
if (kvm_read(kd
, (u_long
)nl
[X_CNTTY
].n_value
,
(char *)&cn_ttyp
, sizeof(cn_ttyp
)) > 0) {
(void)kvm_read(kd
, (u_long
)cn_ttyp
,
(char *)&cn_tty
, sizeof (cn_tty
));
if ((ep
->idle
= now
- stp
->st_atime
) < 0)
if (header
|| wcmd
== 0) {
pr_header(kd
, &now
, nusers
);
#define HEADER "USER TTY FROM LOGIN@ IDLE WHAT\n"
#define WUSED (sizeof (HEADER) - sizeof ("WHAT\n"))
if ((kp
= kvm_getprocs(kd
, KERN_PROC_ALL
, 0, &nentries
)) == NULL
)
err(1, "%s", kvm_geterr(kd
));
for (i
= 0; i
< nentries
; i
++, kp
++) {
register struct proc
*p
= &kp
->kp_proc
;
register struct eproc
*e
;
if (p
->p_stat
== SIDL
|| p
->p_stat
== SZOMB
)
for (ep
= ehead
; ep
!= NULL
; ep
= ep
->next
) {
if (ep
->tdev
== e
->e_tdev
&& e
->e_pgid
== e
->e_tpgid
) {
* Proc is in foreground of this terminal
if (proc_compare(&ep
->kp
->kp_proc
, p
))
if ((ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &ws
) == -1 &&
ioctl(STDERR_FILENO
, TIOCGWINSZ
, &ws
) == -1 &&
ioctl(STDIN_FILENO
, TIOCGWINSZ
, &ws
) == -1) || ws
.ws_col
== 0)
ttywidth
= ws
.ws_col
- 1;
argwidth
= ttywidth
- WUSED
;
for (ep
= ehead
; ep
!= NULL
; ep
= ep
->next
) {
ep
->args
= fmt_argv(kvm_getargv(kd
, ep
->kp
, argwidth
),
ep
->kp
->kp_proc
.p_comm
, MAXCOMLEN
);
if (sortidle
&& ehead
!= NULL
) {
struct entry
*from
= ehead
, *save
;
(*nextp
) && from
->idle
>= (*nextp
)->idle
;
if (gethostname(domain
, sizeof(domain
) - 1) < 0 ||
(p
= index(domain
, '.')) == 0)
domain
[sizeof(domain
) - 1] = '\0';
bcopy(p
, domain
, strlen(p
) + 1);
for (ep
= ehead
; ep
!= NULL
; ep
= ep
->next
) {
p
= *ep
->utmp
.ut_host
? ep
->utmp
.ut_host
: "-";
if (!nflag
&& isdigit(*p
) &&
(long)(l
= inet_addr(p
)) != -1 &&
(hp
= gethostbyaddr((char *)&l
, sizeof(l
), AF_INET
))) {
if (p
> hp
->h_name
&& !strcmp(p
, domain
))
(void)snprintf(buf
, sizeof(buf
), "%s:%s", p
, x
);
(void)printf("%-*.*s %-2.2s %-*.*s ",
UT_NAMESIZE
, UT_NAMESIZE
, ep
->utmp
.ut_name
,
strncmp(ep
->utmp
.ut_line
, "tty", 3) ?
ep
->utmp
.ut_line
: ep
->utmp
.ut_line
+ 3,
UT_HOSTSIZE
, UT_HOSTSIZE
, *p
? p
: "-");
pr_attime(&ep
->utmp
.ut_time
, &now
);
(void)printf("%.*s\n", argwidth
, ep
->args
);
pr_header(kd
, nowp
, nusers
)
* Note, SCCS forces the string manipulation below, as it
* replaces w.c with file information.
(void)strcpy(fmt
, "%l:%%%p");
(void)strftime(buf
, sizeof(buf
), fmt
, localtime(nowp
));
(void)printf("%s ", buf
);
* Print how long system has been up.
* (Found by looking for "boottime" in kernel)
if ((kvm_read(kd
, (u_long
)nl
[X_BOOTTIME
].n_value
,
&boottime
, sizeof(boottime
))) != sizeof(boottime
))
err(1, "can't read kernel bootime variable");
uptime
= now
- boottime
.tv_sec
;
days
= uptime
/ SECSPERDAY
;
hrs
= uptime
/ SECSPERHOUR
;
mins
= uptime
/ SECSPERMIN
;
(void)printf(" %d day%s,", days
, days
> 1 ? "s" : "");
(void)printf(" %2d:%02d,", hrs
, mins
);
(void)printf(" %d hr%s,",
hrs
, hrs
> 1 ? "s" : "");
(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.
avenrun
, sizeof(avenrun
) / sizeof(avenrun
[0])) == -1)
(void)printf(", no load average information available\n");
(void)printf(", load averages:");
for (i
= 0; i
< (sizeof(avenrun
) / sizeof(avenrun
[0])); i
++) {
(void)printf(" %.2f", avenrun
[i
]);
(void)snprintf(ttybuf
, sizeof(ttybuf
), "%s/%s", _PATH_DEV
, line
);
"usage: w: [-hin] [-M core] [-N system] [user]\n");
(void)fprintf(stderr
, "uptime\n");