* Copyright (c) 1980, 1991 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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
"@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)w.c 5.29 (Berkeley) 4/23/91";
* w - print system status (who and what)
* This program is similar to the systat command on Tenex/Tops 10/20
int ttywidth
; /* width of tty */
int argwidth
; /* width of tty */
int header
= 1; /* true if -h flag: don't print heading */
int wcmd
= 1; /* true if this is w(1), and not uptime(1) */
int nusers
; /* number of users logged in now */
char * sel_user
; /* login of particular user selected */
time_t now
; /* the current time of day */
time_t uptime
; /* time of last reboot & elapsed time since */
int sortidle
; /* sort bu idle time */
* One of these per active utmp entry.
dev_t tdev
; /* dev_t of terminal */
int idle
; /* idle time of terminal in minutes */
struct proc
*proc
; /* list of procs in foreground */
char *args
; /* arg list of interesting process */
} *ep
, *ehead
= NULL
, **nextp
= &ehead
;
#if defined(hp300) || defined(i386)
#define USAGE "[ -hi ] [ user ]"
#define usage() fprintf(stderr, "usage: %s: %s\n", program, USAGE)
struct stat
*stp
, *ttystat();
* are we w(1) or uptime(1)
if ((cp
= rindex(program
, '/')) || *(cp
= program
) == '-')
while ((ch
= getopt(argc
, argv
, "hiflsuw")) != EOF
)
case 'f': case 'l': case 's': case 'u': case 'w':
error("[-flsuw] no longer supported");
if (header
&& kvm_nlist(nl
) != 0) {
error("can't get namelist");
ut
= fopen(_PATH_UTMP
, "r");
while (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
= (struct entry
*)
calloc(1, sizeof (struct entry
))) == NULL
) {
bcopy(&utmp
, &(ep
->utmp
), sizeof (struct utmp
));
stp
= ttystat(ep
->utmp
.ut_line
);
#if defined(hp300) || defined(i386)
* XXX 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((void *)nl
[X_CNTTY
].n_value
,
&cn_ttyp
, sizeof(cn_ttyp
)) > 0) {
(void)kvm_read(cn_ttyp
, &cn_tty
,
ep
->idle
= ((now
- stp
->st_atime
) + 30) / 60; /* secs->mins */
if (header
|| wcmd
== 0) {
fputs(attime(&now
), stdout
);
* Print how long system has been up.
* (Found by looking for "boottime" in kernel)
(void)kvm_read((void *)nl
[X_BOOTTIME
].n_value
, &boottime
,
uptime
= now
- boottime
.tv_sec
;
days
= uptime
/ (60*60*24);
printf(" %d day%s,", days
, days
>1?"s":"");
if (hrs
> 0 && mins
> 0) {
printf(" %2d:%02d,", hrs
, mins
);
printf(" %d hr%s,", hrs
, hrs
>1?"s":"");
printf(" %d min%s,", mins
, mins
>1?"s":"");
/* Print number of users logged in to system */
printf(" %d user%s", nusers
, nusers
>1?"s":"");
* Print 1, 5, and 15 minute load averages.
printf(", load average:");
(void)getloadavg(avenrun
, sizeof(avenrun
) / sizeof(avenrun
[0]));
for (i
= 0; i
< (sizeof(avenrun
)/sizeof(avenrun
[0])); i
++) {
printf(" %.2f", avenrun
[i
]);
if (wcmd
== 0) /* if uptime(1) then done */
#define HEADER "USER TTY FROM LOGIN@ IDLE WHAT\n"
#define WUSED (sizeof (HEADER) - sizeof ("WHAT\n"))
while ((p
= kvm_nextproc()) != NULL
) {
if (p
->p_stat
== SZOMB
|| (p
->p_flag
& SCTTY
) == 0)
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
->proc
, p
))
if ((ioctl(1, TIOCGWINSZ
, &ws
) == -1 &&
ioctl(2, TIOCGWINSZ
, &ws
) == -1 &&
ioctl(0, 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
= strdup(kvm_getargs(ep
->proc
, kvm_getu(ep
->proc
)));
if (sortidle
&& ehead
!= NULL
) {
struct entry
*from
= ehead
, *save
;
(*nextp
) && from
->idle
>= (*nextp
)->idle
;
for (ep
= ehead
; ep
!= NULL
; ep
= ep
->next
) {
printf("%-*.*s %-2.2s %-*.*s %s",
UT_NAMESIZE
, UT_NAMESIZE
, ep
->utmp
.ut_name
,
strncmp(ep
->utmp
.ut_line
, "tty", 3) == 0 ?
ep
->utmp
.ut_line
+3 : ep
->utmp
.ut_line
,
UT_HOSTSIZE
, UT_HOSTSIZE
, *ep
->utmp
.ut_host
?
attime(&ep
->utmp
.ut_time
));
printf(" %ddays ", (ep
->idle
+ 12 * 60) / (24 * 60));
printf("%.*s\n", argwidth
, ep
->args
);
static struct stat statbuf
;
char ttybuf
[sizeof (_PATH_DEV
) + UT_LINESIZE
+ 1];
sprintf(ttybuf
, "%s/%.*s", _PATH_DEV
, UT_LINESIZE
, line
);
(void) stat(ttybuf
, &statbuf
);
* prttime prints a time in hours and minutes or minutes and seconds.
* The character string tail is printed at the end, obvious
* strings to pass are "", " ", or "am".
fprintf(stderr
, "%s: ", program
);
fmt
= va_arg(ap
, char *);
(void) vfprintf(stderr
, fmt
, ap
);