xref: /minix3/usr.bin/w/w.c (revision 1f761e1bea5f6d0bb41b751341467673c16776f3)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: w.c,v 1.82 2014/12/22 15:24:14 dennis Exp $	*/
211eaad35SDavid van Moolenbroek 
311eaad35SDavid van Moolenbroek /*-
411eaad35SDavid van Moolenbroek  * Copyright (c) 1980, 1991, 1993, 1994
511eaad35SDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
611eaad35SDavid van Moolenbroek  *
711eaad35SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
811eaad35SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
911eaad35SDavid van Moolenbroek  * are met:
1011eaad35SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
1111eaad35SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
1211eaad35SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
1311eaad35SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
1411eaad35SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
1511eaad35SDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
1611eaad35SDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
1711eaad35SDavid van Moolenbroek  *    without specific prior written permission.
1811eaad35SDavid van Moolenbroek  *
1911eaad35SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2011eaad35SDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2111eaad35SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2211eaad35SDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2311eaad35SDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2411eaad35SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2511eaad35SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2611eaad35SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2711eaad35SDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2811eaad35SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2911eaad35SDavid van Moolenbroek  * SUCH DAMAGE.
3011eaad35SDavid van Moolenbroek  */
3111eaad35SDavid van Moolenbroek 
3211eaad35SDavid van Moolenbroek #include <sys/cdefs.h>
3311eaad35SDavid van Moolenbroek #ifndef lint
3411eaad35SDavid van Moolenbroek __COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\
3511eaad35SDavid van Moolenbroek  The Regents of the University of California.  All rights reserved.");
3611eaad35SDavid van Moolenbroek #endif /* not lint */
3711eaad35SDavid van Moolenbroek 
3811eaad35SDavid van Moolenbroek #ifndef lint
3911eaad35SDavid van Moolenbroek #if 0
4011eaad35SDavid van Moolenbroek static char sccsid[] = "@(#)w.c	8.6 (Berkeley) 6/30/94";
4111eaad35SDavid van Moolenbroek #else
42*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: w.c,v 1.82 2014/12/22 15:24:14 dennis Exp $");
4311eaad35SDavid van Moolenbroek #endif
4411eaad35SDavid van Moolenbroek #endif /* not lint */
4511eaad35SDavid van Moolenbroek 
4611eaad35SDavid van Moolenbroek /*
4711eaad35SDavid van Moolenbroek  * w - print system status (who and what)
4811eaad35SDavid van Moolenbroek  *
4911eaad35SDavid van Moolenbroek  * This program is similar to the systat command on Tenex/Tops 10/20
5011eaad35SDavid van Moolenbroek  *
5111eaad35SDavid van Moolenbroek  */
5211eaad35SDavid van Moolenbroek #include <sys/param.h>
5311eaad35SDavid van Moolenbroek #include <sys/types.h>
5411eaad35SDavid van Moolenbroek #include <sys/time.h>
5511eaad35SDavid van Moolenbroek #include <sys/stat.h>
5611eaad35SDavid van Moolenbroek #include <sys/sysctl.h>
5711eaad35SDavid van Moolenbroek #include <sys/proc.h>
5811eaad35SDavid van Moolenbroek #include <sys/ioctl.h>
5911eaad35SDavid van Moolenbroek #include <sys/socket.h>
6011eaad35SDavid van Moolenbroek 
6111eaad35SDavid van Moolenbroek #include <netinet/in.h>
6211eaad35SDavid van Moolenbroek #include <arpa/inet.h>
6311eaad35SDavid van Moolenbroek 
6411eaad35SDavid van Moolenbroek #include <ctype.h>
6511eaad35SDavid van Moolenbroek #include <err.h>
6611eaad35SDavid van Moolenbroek #include <errno.h>
6711eaad35SDavid van Moolenbroek #include <fcntl.h>
6811eaad35SDavid van Moolenbroek #include <kvm.h>
6911eaad35SDavid van Moolenbroek #include <limits.h>
7011eaad35SDavid van Moolenbroek #include <netdb.h>
7111eaad35SDavid van Moolenbroek #include <nlist.h>
7211eaad35SDavid van Moolenbroek #include <paths.h>
7311eaad35SDavid van Moolenbroek #include <stdio.h>
7411eaad35SDavid van Moolenbroek #include <stdlib.h>
7511eaad35SDavid van Moolenbroek #include <string.h>
7611eaad35SDavid van Moolenbroek #include <time.h>
7711eaad35SDavid van Moolenbroek #include <tzfile.h>
7811eaad35SDavid van Moolenbroek #include <unistd.h>
7911eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
8011eaad35SDavid van Moolenbroek #include <utmp.h>
8111eaad35SDavid van Moolenbroek #endif
8211eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
8311eaad35SDavid van Moolenbroek #include <utmpx.h>
8411eaad35SDavid van Moolenbroek #endif
8511eaad35SDavid van Moolenbroek #include <vis.h>
8611eaad35SDavid van Moolenbroek 
8711eaad35SDavid van Moolenbroek #include "extern.h"
8811eaad35SDavid van Moolenbroek 
8911eaad35SDavid van Moolenbroek struct timeval	boottime;
9011eaad35SDavid van Moolenbroek struct winsize	ws;
9111eaad35SDavid van Moolenbroek kvm_t	       *kd;
9211eaad35SDavid van Moolenbroek time_t		now;		/* the current time of day */
9311eaad35SDavid van Moolenbroek int		ttywidth;	/* width of tty */
9411eaad35SDavid van Moolenbroek int		argwidth;	/* width of tty left to print process args */
9511eaad35SDavid van Moolenbroek int		header = 1;	/* true if -h flag: don't print heading */
9611eaad35SDavid van Moolenbroek int		nflag;		/* true if -n flag: don't convert addrs */
9711eaad35SDavid van Moolenbroek int		wflag;		/* true if -w flag: wide printout */
9811eaad35SDavid van Moolenbroek int		sortidle;	/* sort bu idle time */
9911eaad35SDavid van Moolenbroek char	       *sel_user;	/* login of particular user selected */
10011eaad35SDavid van Moolenbroek char		domain[MAXHOSTNAMELEN + 1];
10111eaad35SDavid van Moolenbroek int maxname = 8, maxline = 3, maxhost = 16;
10211eaad35SDavid van Moolenbroek 
10311eaad35SDavid van Moolenbroek /*
10411eaad35SDavid van Moolenbroek  * One of these per active utmp entry.
10511eaad35SDavid van Moolenbroek  */
10611eaad35SDavid van Moolenbroek struct	entry {
10711eaad35SDavid van Moolenbroek 	struct	entry *next;
10811eaad35SDavid van Moolenbroek 	char name[UTX_USERSIZE + 1];
10911eaad35SDavid van Moolenbroek 	char line[UTX_LINESIZE + 1];
11011eaad35SDavid van Moolenbroek 	char host[UTX_HOSTSIZE + 1];
11111eaad35SDavid van Moolenbroek 	char type[2];
11211eaad35SDavid van Moolenbroek 	struct timeval tv;
11311eaad35SDavid van Moolenbroek 	dev_t	tdev;			/* dev_t of terminal */
11411eaad35SDavid van Moolenbroek 	time_t	idle;			/* idle time of terminal in seconds */
11511eaad35SDavid van Moolenbroek 	struct	kinfo_proc2 *tp;	/* `most interesting' tty proc */
11611eaad35SDavid van Moolenbroek 	struct	kinfo_proc2 *pp;	/* pid proc */
11711eaad35SDavid van Moolenbroek 	pid_t	pid;			/* pid or ~0 if not known */
11811eaad35SDavid van Moolenbroek } *ehead = NULL, **nextp = &ehead;
11911eaad35SDavid van Moolenbroek 
12011eaad35SDavid van Moolenbroek static void	pr_args(struct kinfo_proc2 *);
12111eaad35SDavid van Moolenbroek static void	pr_header(time_t *, int);
12211eaad35SDavid van Moolenbroek static int	proc_compare_wrapper(const struct kinfo_proc2 *,
12311eaad35SDavid van Moolenbroek     const struct kinfo_proc2 *);
12411eaad35SDavid van Moolenbroek #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
12511eaad35SDavid van Moolenbroek static int	ttystat(const char *, struct stat *);
12611eaad35SDavid van Moolenbroek static void	process(struct entry *);
12711eaad35SDavid van Moolenbroek #endif
12811eaad35SDavid van Moolenbroek static void	fixhost(struct entry *ep);
12911eaad35SDavid van Moolenbroek __dead static void	usage(int);
13011eaad35SDavid van Moolenbroek 
13111eaad35SDavid van Moolenbroek int
main(int argc,char ** argv)13211eaad35SDavid van Moolenbroek main(int argc, char **argv)
13311eaad35SDavid van Moolenbroek {
13411eaad35SDavid van Moolenbroek 	struct kinfo_proc2 *kp;
13511eaad35SDavid van Moolenbroek 	struct entry *ep;
13611eaad35SDavid van Moolenbroek 	int ch, i, nentries, nusers, wcmd, curtain, use_sysctl;
13711eaad35SDavid van Moolenbroek 	char *memf, *nlistf, *usrnp;
13811eaad35SDavid van Moolenbroek 	const char *options;
13911eaad35SDavid van Moolenbroek 	time_t then;
14011eaad35SDavid van Moolenbroek 	size_t len;
14111eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
14211eaad35SDavid van Moolenbroek 	struct utmp *ut;
14311eaad35SDavid van Moolenbroek #endif
14411eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
14511eaad35SDavid van Moolenbroek 	struct utmpx *utx;
14611eaad35SDavid van Moolenbroek #endif
14711eaad35SDavid van Moolenbroek 	const char *progname;
14811eaad35SDavid van Moolenbroek 	char errbuf[_POSIX2_LINE_MAX];
14911eaad35SDavid van Moolenbroek 
15011eaad35SDavid van Moolenbroek 	setprogname(argv[0]);
15111eaad35SDavid van Moolenbroek 
15211eaad35SDavid van Moolenbroek 	/* Are we w(1) or uptime(1)? */
15311eaad35SDavid van Moolenbroek 	progname = getprogname();
15411eaad35SDavid van Moolenbroek 	if (*progname == '-')
15511eaad35SDavid van Moolenbroek 		progname++;
15611eaad35SDavid van Moolenbroek 	if (*progname == 'u') {
15711eaad35SDavid van Moolenbroek 		wcmd = 0;
15811eaad35SDavid van Moolenbroek 		options = "";
15911eaad35SDavid van Moolenbroek 	} else {
16011eaad35SDavid van Moolenbroek 		wcmd = 1;
16111eaad35SDavid van Moolenbroek 		options = "hiM:N:nw";
16211eaad35SDavid van Moolenbroek 	}
16311eaad35SDavid van Moolenbroek 
16411eaad35SDavid van Moolenbroek 	memf = nlistf = NULL;
16511eaad35SDavid van Moolenbroek 	while ((ch = getopt(argc, argv, options)) != -1)
16611eaad35SDavid van Moolenbroek 		switch (ch) {
16711eaad35SDavid van Moolenbroek 		case 'h':
16811eaad35SDavid van Moolenbroek 			header = 0;
16911eaad35SDavid van Moolenbroek 			break;
17011eaad35SDavid van Moolenbroek 		case 'i':
17111eaad35SDavid van Moolenbroek 			sortidle = 1;
17211eaad35SDavid van Moolenbroek 			break;
17311eaad35SDavid van Moolenbroek 		case 'M':
17411eaad35SDavid van Moolenbroek 			header = 0;
17511eaad35SDavid van Moolenbroek 			memf = optarg;
17611eaad35SDavid van Moolenbroek 			break;
17711eaad35SDavid van Moolenbroek 		case 'N':
17811eaad35SDavid van Moolenbroek 			nlistf = optarg;
17911eaad35SDavid van Moolenbroek 			break;
18011eaad35SDavid van Moolenbroek 		case 'n':
18111eaad35SDavid van Moolenbroek 			nflag = 1;
18211eaad35SDavid van Moolenbroek 			break;
18311eaad35SDavid van Moolenbroek 		case 'w':
18411eaad35SDavid van Moolenbroek 			wflag = 1;
18511eaad35SDavid van Moolenbroek 			break;
18611eaad35SDavid van Moolenbroek 		case '?':
18711eaad35SDavid van Moolenbroek 		default:
18811eaad35SDavid van Moolenbroek 			usage(wcmd);
18911eaad35SDavid van Moolenbroek 		}
19011eaad35SDavid van Moolenbroek 	argc -= optind;
19111eaad35SDavid van Moolenbroek 	argv += optind;
19211eaad35SDavid van Moolenbroek 
19311eaad35SDavid van Moolenbroek 	use_sysctl = (memf == NULL && nlistf == NULL);
19411eaad35SDavid van Moolenbroek 
19511eaad35SDavid van Moolenbroek 	if ((kd = kvm_openfiles(nlistf, memf, NULL,
19611eaad35SDavid van Moolenbroek 	    memf == NULL ? KVM_NO_FILES : O_RDONLY, errbuf)) == NULL)
19711eaad35SDavid van Moolenbroek 		errx(1, "%s", errbuf);
19811eaad35SDavid van Moolenbroek 
19911eaad35SDavid van Moolenbroek 	(void)time(&now);
20011eaad35SDavid van Moolenbroek 
20111eaad35SDavid van Moolenbroek 	if (use_sysctl) {
20211eaad35SDavid van Moolenbroek 		len = sizeof(curtain);
20311eaad35SDavid van Moolenbroek 		if (sysctlbyname("security.curtain", &curtain, &len,
20411eaad35SDavid van Moolenbroek 		    NULL, 0) == -1)
20511eaad35SDavid van Moolenbroek 			curtain = 0;
20611eaad35SDavid van Moolenbroek 	}
20711eaad35SDavid van Moolenbroek 
20811eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
20911eaad35SDavid van Moolenbroek 	setutxent();
21011eaad35SDavid van Moolenbroek #endif
21111eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
21211eaad35SDavid van Moolenbroek 	setutent();
21311eaad35SDavid van Moolenbroek #endif
21411eaad35SDavid van Moolenbroek 
21511eaad35SDavid van Moolenbroek 	if (*argv)
21611eaad35SDavid van Moolenbroek 		sel_user = *argv;
21711eaad35SDavid van Moolenbroek 
21811eaad35SDavid van Moolenbroek 	nusers = 0;
21911eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
22011eaad35SDavid van Moolenbroek 	while ((utx = getutxent()) != NULL) {
22111eaad35SDavid van Moolenbroek 		if (utx->ut_type != USER_PROCESS)
22211eaad35SDavid van Moolenbroek 			continue;
22311eaad35SDavid van Moolenbroek 		++nusers;
224*0a6a1f1dSLionel Sambuc 
225*0a6a1f1dSLionel Sambuc #ifndef SUPPORT_UTMP
226*0a6a1f1dSLionel Sambuc 		if (wcmd == 0)
227*0a6a1f1dSLionel Sambuc 			continue;
228*0a6a1f1dSLionel Sambuc #endif	/* !SUPPORT_UTMP */
229*0a6a1f1dSLionel Sambuc 
23011eaad35SDavid van Moolenbroek 		if (sel_user &&
23111eaad35SDavid van Moolenbroek 		    strncmp(utx->ut_name, sel_user, sizeof(utx->ut_name)) != 0)
23211eaad35SDavid van Moolenbroek 			continue;
23311eaad35SDavid van Moolenbroek 		if ((ep = calloc(1, sizeof(struct entry))) == NULL)
23411eaad35SDavid van Moolenbroek 			err(1, NULL);
23511eaad35SDavid van Moolenbroek 		(void)memcpy(ep->line, utx->ut_line, sizeof(utx->ut_line));
23611eaad35SDavid van Moolenbroek 		ep->line[sizeof(utx->ut_line)] = '\0';
237*0a6a1f1dSLionel Sambuc 		*nextp = ep;
238*0a6a1f1dSLionel Sambuc 		nextp = &(ep->next);
239*0a6a1f1dSLionel Sambuc 
240*0a6a1f1dSLionel Sambuc 		if (wcmd == 0)
241*0a6a1f1dSLionel Sambuc 			continue;
242*0a6a1f1dSLionel Sambuc 
243*0a6a1f1dSLionel Sambuc 		(void)memcpy(ep->name, utx->ut_name, sizeof(utx->ut_name));
244*0a6a1f1dSLionel Sambuc 		ep->name[sizeof(utx->ut_name)] = '\0';
24511eaad35SDavid van Moolenbroek 		if (!nflag || getnameinfo((struct sockaddr *)&utx->ut_ss,
24611eaad35SDavid van Moolenbroek 		    utx->ut_ss.ss_len, ep->host, sizeof(ep->host), NULL, 0,
24711eaad35SDavid van Moolenbroek 		    NI_NUMERICHOST) != 0) {
24811eaad35SDavid van Moolenbroek 			(void)memcpy(ep->host, utx->ut_host,
24911eaad35SDavid van Moolenbroek 			    sizeof(utx->ut_host));
25011eaad35SDavid van Moolenbroek 			ep->host[sizeof(utx->ut_host)] = '\0';
25111eaad35SDavid van Moolenbroek 		}
25211eaad35SDavid van Moolenbroek 		fixhost(ep);
25311eaad35SDavid van Moolenbroek 		ep->type[0] = 'x';
25411eaad35SDavid van Moolenbroek 		ep->tv = utx->ut_tv;
25511eaad35SDavid van Moolenbroek 		ep->pid = utx->ut_pid;
25611eaad35SDavid van Moolenbroek 		process(ep);
25711eaad35SDavid van Moolenbroek 	}
25811eaad35SDavid van Moolenbroek #endif
25911eaad35SDavid van Moolenbroek 
26011eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
26111eaad35SDavid van Moolenbroek 	while ((ut = getutent()) != NULL) {
26211eaad35SDavid van Moolenbroek 		if (ut->ut_name[0] == '\0')
26311eaad35SDavid van Moolenbroek 			continue;
26411eaad35SDavid van Moolenbroek 
26511eaad35SDavid van Moolenbroek 		if (sel_user &&
26611eaad35SDavid van Moolenbroek 		    strncmp(ut->ut_name, sel_user, sizeof(ut->ut_name)) != 0)
26711eaad35SDavid van Moolenbroek 			continue;
26811eaad35SDavid van Moolenbroek 
26911eaad35SDavid van Moolenbroek 		/* Don't process entries that we have utmpx for */
27011eaad35SDavid van Moolenbroek 		for (ep = ehead; ep != NULL; ep = ep->next) {
27111eaad35SDavid van Moolenbroek 			if (strncmp(ep->line, ut->ut_line,
27211eaad35SDavid van Moolenbroek 			    sizeof(ut->ut_line)) == 0)
27311eaad35SDavid van Moolenbroek 				break;
27411eaad35SDavid van Moolenbroek 		}
27511eaad35SDavid van Moolenbroek 		if (ep != NULL)
27611eaad35SDavid van Moolenbroek 			continue;
27711eaad35SDavid van Moolenbroek 
27811eaad35SDavid van Moolenbroek 		++nusers;
279*0a6a1f1dSLionel Sambuc 
280*0a6a1f1dSLionel Sambuc 		if (wcmd == 0)
281*0a6a1f1dSLionel Sambuc 			continue;
282*0a6a1f1dSLionel Sambuc 
28311eaad35SDavid van Moolenbroek 		if ((ep = calloc(1, sizeof(struct entry))) == NULL)
28411eaad35SDavid van Moolenbroek 			err(1, NULL);
28511eaad35SDavid van Moolenbroek 		(void)memcpy(ep->name, ut->ut_name, sizeof(ut->ut_name));
28611eaad35SDavid van Moolenbroek 		(void)memcpy(ep->line, ut->ut_line, sizeof(ut->ut_line));
28711eaad35SDavid van Moolenbroek 		(void)memcpy(ep->host, ut->ut_host, sizeof(ut->ut_host));
28811eaad35SDavid van Moolenbroek 		ep->name[sizeof(ut->ut_name)] = '\0';
28911eaad35SDavid van Moolenbroek 		ep->line[sizeof(ut->ut_line)] = '\0';
29011eaad35SDavid van Moolenbroek 		ep->host[sizeof(ut->ut_host)] = '\0';
29111eaad35SDavid van Moolenbroek 		fixhost(ep);
29211eaad35SDavid van Moolenbroek 		ep->tv.tv_sec = ut->ut_time;
29311eaad35SDavid van Moolenbroek 		*nextp = ep;
29411eaad35SDavid van Moolenbroek 		nextp = &(ep->next);
29511eaad35SDavid van Moolenbroek 		process(ep);
29611eaad35SDavid van Moolenbroek 	}
29711eaad35SDavid van Moolenbroek #endif
29811eaad35SDavid van Moolenbroek 
29911eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
30011eaad35SDavid van Moolenbroek 	endutxent();
30111eaad35SDavid van Moolenbroek #endif
30211eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
30311eaad35SDavid van Moolenbroek 	endutent();
30411eaad35SDavid van Moolenbroek #endif
30511eaad35SDavid van Moolenbroek 
30611eaad35SDavid van Moolenbroek 	if (header || wcmd == 0) {
30711eaad35SDavid van Moolenbroek 		pr_header(&now, nusers);
30811eaad35SDavid van Moolenbroek 		if (wcmd == 0)
30911eaad35SDavid van Moolenbroek 			exit (0);
31011eaad35SDavid van Moolenbroek 	}
31111eaad35SDavid van Moolenbroek 
31211eaad35SDavid van Moolenbroek 	if ((kp = kvm_getproc2(kd, KERN_PROC_ALL, 0,
31311eaad35SDavid van Moolenbroek 	    sizeof(struct kinfo_proc2), &nentries)) == NULL)
31411eaad35SDavid van Moolenbroek 		errx(1, "%s", kvm_geterr(kd));
31511eaad35SDavid van Moolenbroek 
31611eaad35SDavid van Moolenbroek 	/* Include trailing space because TTY header starts one column early. */
31711eaad35SDavid van Moolenbroek 	for (i = 0; i < nentries; i++, kp++) {
31811eaad35SDavid van Moolenbroek 
31911eaad35SDavid van Moolenbroek 		for (ep = ehead; ep != NULL; ep = ep->next) {
32011eaad35SDavid van Moolenbroek 			if (ep->tdev != 0 && ep->tdev == kp->p_tdev &&
32111eaad35SDavid van Moolenbroek 			    kp->p__pgid == kp->p_tpgid) {
32211eaad35SDavid van Moolenbroek 				/*
32311eaad35SDavid van Moolenbroek 				 * Proc is in foreground of this
32411eaad35SDavid van Moolenbroek 				 * terminal
32511eaad35SDavid van Moolenbroek 				 */
32611eaad35SDavid van Moolenbroek 				if (proc_compare_wrapper(ep->tp, kp))
32711eaad35SDavid van Moolenbroek 					ep->tp = kp;
32811eaad35SDavid van Moolenbroek 				break;
32911eaad35SDavid van Moolenbroek 			}
33011eaad35SDavid van Moolenbroek 			if (ep->pid != 0 && ep->pid == kp->p_pid) {
33111eaad35SDavid van Moolenbroek 				ep->pp = kp;
33211eaad35SDavid van Moolenbroek 				break;
33311eaad35SDavid van Moolenbroek 			}
33411eaad35SDavid van Moolenbroek 		}
33511eaad35SDavid van Moolenbroek 	}
33611eaad35SDavid van Moolenbroek 
33711eaad35SDavid van Moolenbroek 	if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
33811eaad35SDavid van Moolenbroek 	    ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
33911eaad35SDavid van Moolenbroek 	    ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
34011eaad35SDavid van Moolenbroek 		ttywidth = 79;
34111eaad35SDavid van Moolenbroek 	else
34211eaad35SDavid van Moolenbroek 		ttywidth = ws.ws_col - 1;
34311eaad35SDavid van Moolenbroek 
34411eaad35SDavid van Moolenbroek 	if (!wflag && maxhost > (ttywidth / 3))
34511eaad35SDavid van Moolenbroek 		maxhost = ttywidth / 3;
34611eaad35SDavid van Moolenbroek 
34711eaad35SDavid van Moolenbroek 	argwidth = printf("%-*s TTY     %-*s %*s  IDLE WHAT\n",
34811eaad35SDavid van Moolenbroek 	    maxname, "USER", maxhost, "FROM",
34911eaad35SDavid van Moolenbroek 	    7 /* "dddhhXm" */, "LOGIN@");
35011eaad35SDavid van Moolenbroek 	argwidth -= sizeof("WHAT\n") - 1 /* NUL */;
35111eaad35SDavid van Moolenbroek 	argwidth = ttywidth - argwidth;
35211eaad35SDavid van Moolenbroek 	if (argwidth < 4)
35311eaad35SDavid van Moolenbroek 		argwidth = 8;
35411eaad35SDavid van Moolenbroek 	if (wflag)
35511eaad35SDavid van Moolenbroek 		argwidth = -1;
35611eaad35SDavid van Moolenbroek 
35711eaad35SDavid van Moolenbroek 	/* sort by idle time */
35811eaad35SDavid van Moolenbroek 	if (sortidle && ehead != NULL) {
35911eaad35SDavid van Moolenbroek 		struct entry *from = ehead, *save;
36011eaad35SDavid van Moolenbroek 
36111eaad35SDavid van Moolenbroek 		ehead = NULL;
36211eaad35SDavid van Moolenbroek 		while (from != NULL) {
36311eaad35SDavid van Moolenbroek 			for (nextp = &ehead;
36411eaad35SDavid van Moolenbroek 			    (*nextp) && from->idle >= (*nextp)->idle;
36511eaad35SDavid van Moolenbroek 			    nextp = &(*nextp)->next)
36611eaad35SDavid van Moolenbroek 				continue;
36711eaad35SDavid van Moolenbroek 			save = from;
36811eaad35SDavid van Moolenbroek 			from = from->next;
36911eaad35SDavid van Moolenbroek 			save->next = *nextp;
37011eaad35SDavid van Moolenbroek 			*nextp = save;
37111eaad35SDavid van Moolenbroek 		}
37211eaad35SDavid van Moolenbroek 	}
37311eaad35SDavid van Moolenbroek #if defined(SUPPORT_UTMP) && defined(SUPPORT_UTMPX)
37411eaad35SDavid van Moolenbroek 	else if (ehead != NULL) {
37511eaad35SDavid van Moolenbroek 		struct entry *from = ehead, *save;
37611eaad35SDavid van Moolenbroek 
37711eaad35SDavid van Moolenbroek 		ehead = NULL;
37811eaad35SDavid van Moolenbroek 		while (from != NULL) {
37911eaad35SDavid van Moolenbroek 			for (nextp = &ehead;
38011eaad35SDavid van Moolenbroek 			    (*nextp) && strcmp(from->line, (*nextp)->line) > 0;
38111eaad35SDavid van Moolenbroek 			    nextp = &(*nextp)->next)
38211eaad35SDavid van Moolenbroek 				continue;
38311eaad35SDavid van Moolenbroek 			save = from;
38411eaad35SDavid van Moolenbroek 			from = from->next;
38511eaad35SDavid van Moolenbroek 			save->next = *nextp;
38611eaad35SDavid van Moolenbroek 			*nextp = save;
38711eaad35SDavid van Moolenbroek 		}
38811eaad35SDavid van Moolenbroek 	}
38911eaad35SDavid van Moolenbroek #endif
39011eaad35SDavid van Moolenbroek 
39111eaad35SDavid van Moolenbroek 	if (!nflag) {
39211eaad35SDavid van Moolenbroek 		int	rv;
39311eaad35SDavid van Moolenbroek 		char	*p;
39411eaad35SDavid van Moolenbroek 
39511eaad35SDavid van Moolenbroek 		rv = gethostname(domain, sizeof(domain));
39611eaad35SDavid van Moolenbroek 		domain[sizeof(domain) - 1] = '\0';
39711eaad35SDavid van Moolenbroek 		if (rv < 0 || (p = strchr(domain, '.')) == 0)
39811eaad35SDavid van Moolenbroek 			domain[0] = '\0';
39911eaad35SDavid van Moolenbroek 		else
40011eaad35SDavid van Moolenbroek 			memmove(domain, p, strlen(p) + 1);
40111eaad35SDavid van Moolenbroek 	}
40211eaad35SDavid van Moolenbroek 
40311eaad35SDavid van Moolenbroek 	for (ep = ehead; ep != NULL; ep = ep->next) {
40411eaad35SDavid van Moolenbroek 		if (ep->tp != NULL)
40511eaad35SDavid van Moolenbroek 			kp = ep->tp;
40611eaad35SDavid van Moolenbroek 		else if (ep->pp != NULL)
40711eaad35SDavid van Moolenbroek 			kp = ep->pp;
40811eaad35SDavid van Moolenbroek 		else if (ep->pid != 0) {
40911eaad35SDavid van Moolenbroek 			if (curtain)
41011eaad35SDavid van Moolenbroek 				kp = NULL;
41111eaad35SDavid van Moolenbroek 			else {
41211eaad35SDavid van Moolenbroek 				warnx("Stale utmp%s entry: %s %s %s",
41311eaad35SDavid van Moolenbroek 				    ep->type, ep->name, ep->line, ep->host);
41411eaad35SDavid van Moolenbroek 				continue;
41511eaad35SDavid van Moolenbroek 			}
41611eaad35SDavid van Moolenbroek 		}
417*0a6a1f1dSLionel Sambuc #if !defined(__minix)
41811eaad35SDavid van Moolenbroek 		usrnp = (kp == NULL) ? ep->name : kp->p_login;
41911eaad35SDavid van Moolenbroek #else
42011eaad35SDavid van Moolenbroek 		usrnp = ep->name; /* TODO: implement getlogin/setlogin */
421*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
42211eaad35SDavid van Moolenbroek 		(void)printf("%-*s %-7.7s %-*.*s ",
42311eaad35SDavid van Moolenbroek 		    maxname, usrnp, ep->line,
42411eaad35SDavid van Moolenbroek 		    maxhost, maxhost, ep->host);
42511eaad35SDavid van Moolenbroek 		then = (time_t)ep->tv.tv_sec;
42611eaad35SDavid van Moolenbroek 		pr_attime(&then, &now);
42711eaad35SDavid van Moolenbroek 		pr_idle(ep->idle);
42811eaad35SDavid van Moolenbroek 		pr_args(kp);
42911eaad35SDavid van Moolenbroek 		(void)printf("\n");
43011eaad35SDavid van Moolenbroek 	}
43111eaad35SDavid van Moolenbroek 	exit(0);
43211eaad35SDavid van Moolenbroek }
43311eaad35SDavid van Moolenbroek 
43411eaad35SDavid van Moolenbroek static void
pr_args(struct kinfo_proc2 * kp)43511eaad35SDavid van Moolenbroek pr_args(struct kinfo_proc2 *kp)
43611eaad35SDavid van Moolenbroek {
43711eaad35SDavid van Moolenbroek 	char **argv;
43811eaad35SDavid van Moolenbroek 	int left;
43911eaad35SDavid van Moolenbroek 
44011eaad35SDavid van Moolenbroek 	if (kp == 0)
44111eaad35SDavid van Moolenbroek 		goto nothing;
44211eaad35SDavid van Moolenbroek 	left = argwidth;
44311eaad35SDavid van Moolenbroek 	argv = kvm_getargv2(kd, kp, (argwidth < 0) ? 0 : argwidth);
44411eaad35SDavid van Moolenbroek 	if (argv == 0) {
44511eaad35SDavid van Moolenbroek 		fmt_putc('(', &left);
44611eaad35SDavid van Moolenbroek 		fmt_puts((char *)kp->p_comm, &left);
44711eaad35SDavid van Moolenbroek 		fmt_putc(')', &left);
44811eaad35SDavid van Moolenbroek 		return;
44911eaad35SDavid van Moolenbroek 	}
45011eaad35SDavid van Moolenbroek 	while (*argv) {
45111eaad35SDavid van Moolenbroek 		fmt_puts(*argv, &left);
45211eaad35SDavid van Moolenbroek 		argv++;
45311eaad35SDavid van Moolenbroek 		fmt_putc(' ', &left);
45411eaad35SDavid van Moolenbroek 	}
45511eaad35SDavid van Moolenbroek 	return;
45611eaad35SDavid van Moolenbroek nothing:
45711eaad35SDavid van Moolenbroek 	putchar('-');
45811eaad35SDavid van Moolenbroek }
45911eaad35SDavid van Moolenbroek 
46011eaad35SDavid van Moolenbroek static void
pr_header(time_t * nowp,int nusers)46111eaad35SDavid van Moolenbroek pr_header(time_t *nowp, int nusers)
46211eaad35SDavid van Moolenbroek {
46311eaad35SDavid van Moolenbroek 	double avenrun[3];
46411eaad35SDavid van Moolenbroek 	time_t uptime;
46511eaad35SDavid van Moolenbroek 	int days, hrs, mins;
46611eaad35SDavid van Moolenbroek 	int mib[2];
46711eaad35SDavid van Moolenbroek 	size_t size, i;
46811eaad35SDavid van Moolenbroek 	char buf[256];
46911eaad35SDavid van Moolenbroek 
47011eaad35SDavid van Moolenbroek 	/*
47111eaad35SDavid van Moolenbroek 	 * Print time of day.
47211eaad35SDavid van Moolenbroek 	 *
47311eaad35SDavid van Moolenbroek 	 * SCCS forces the string manipulation below, as it replaces
47411eaad35SDavid van Moolenbroek 	 * %, M, and % in a character string with the file name.
47511eaad35SDavid van Moolenbroek 	 */
47611eaad35SDavid van Moolenbroek 	(void)strftime(buf, sizeof(buf), "%l:%" "M%p", localtime(nowp));
47711eaad35SDavid van Moolenbroek 	buf[sizeof(buf) - 1] = '\0';
47811eaad35SDavid van Moolenbroek 	(void)printf("%s ", buf);
47911eaad35SDavid van Moolenbroek 
48011eaad35SDavid van Moolenbroek 	/*
48111eaad35SDavid van Moolenbroek 	 * Print how long system has been up.
48211eaad35SDavid van Moolenbroek 	 * (Found by looking getting "boottime" from the kernel)
48311eaad35SDavid van Moolenbroek 	 */
48411eaad35SDavid van Moolenbroek 	mib[0] = CTL_KERN;
48511eaad35SDavid van Moolenbroek 	mib[1] = KERN_BOOTTIME;
48611eaad35SDavid van Moolenbroek 	size = sizeof(boottime);
48711eaad35SDavid van Moolenbroek 	if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
48811eaad35SDavid van Moolenbroek 	    boottime.tv_sec != 0) {
48911eaad35SDavid van Moolenbroek 		uptime = now - boottime.tv_sec;
49011eaad35SDavid van Moolenbroek 		uptime += 30;
49111eaad35SDavid van Moolenbroek 		if (uptime > SECSPERMIN) {
49211eaad35SDavid van Moolenbroek 			days = uptime / SECSPERDAY;
49311eaad35SDavid van Moolenbroek 			uptime %= SECSPERDAY;
49411eaad35SDavid van Moolenbroek 			hrs = uptime / SECSPERHOUR;
49511eaad35SDavid van Moolenbroek 			uptime %= SECSPERHOUR;
49611eaad35SDavid van Moolenbroek 			mins = uptime / SECSPERMIN;
49711eaad35SDavid van Moolenbroek 			(void)printf(" up");
49811eaad35SDavid van Moolenbroek 			if (days > 0)
49911eaad35SDavid van Moolenbroek 				(void)printf(" %d day%s,", days,
50011eaad35SDavid van Moolenbroek 				    days > 1 ? "s" : "");
50111eaad35SDavid van Moolenbroek 			if (hrs > 0 && mins > 0)
50211eaad35SDavid van Moolenbroek 				(void)printf(" %2d:%02d,", hrs, mins);
50311eaad35SDavid van Moolenbroek 			else {
50411eaad35SDavid van Moolenbroek 				if (hrs > 0)
50511eaad35SDavid van Moolenbroek 					(void)printf(" %d hr%s,",
50611eaad35SDavid van Moolenbroek 					    hrs, hrs > 1 ? "s" : "");
50711eaad35SDavid van Moolenbroek 				if (mins > 0)
50811eaad35SDavid van Moolenbroek 					(void)printf(" %d min%s,",
50911eaad35SDavid van Moolenbroek 					    mins, mins > 1 ? "s" : "");
51011eaad35SDavid van Moolenbroek 			}
51111eaad35SDavid van Moolenbroek 		}
51211eaad35SDavid van Moolenbroek 	}
51311eaad35SDavid van Moolenbroek 
51411eaad35SDavid van Moolenbroek 	/* Print number of users logged in to system */
51511eaad35SDavid van Moolenbroek 	(void)printf(" %d user%s", nusers, nusers != 1 ? "s" : "");
51611eaad35SDavid van Moolenbroek 
51711eaad35SDavid van Moolenbroek 	/*
51811eaad35SDavid van Moolenbroek 	 * Print 1, 5, and 15 minute load averages.
51911eaad35SDavid van Moolenbroek 	 */
52011eaad35SDavid van Moolenbroek 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) == -1)
52111eaad35SDavid van Moolenbroek 		(void)printf(", no load average information available\n");
52211eaad35SDavid van Moolenbroek 	else {
52311eaad35SDavid van Moolenbroek 		(void)printf(", load averages:");
52411eaad35SDavid van Moolenbroek 		for (i = 0; i < (sizeof(avenrun) / sizeof(avenrun[0])); i++) {
52511eaad35SDavid van Moolenbroek 			if (i > 0)
52611eaad35SDavid van Moolenbroek 				(void)printf(",");
52711eaad35SDavid van Moolenbroek 			(void)printf(" %.2f", avenrun[i]);
52811eaad35SDavid van Moolenbroek 		}
52911eaad35SDavid van Moolenbroek 		(void)printf("\n");
53011eaad35SDavid van Moolenbroek 	}
53111eaad35SDavid van Moolenbroek }
53211eaad35SDavid van Moolenbroek 
53311eaad35SDavid van Moolenbroek #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
53411eaad35SDavid van Moolenbroek static int
ttystat(const char * line,struct stat * st)53511eaad35SDavid van Moolenbroek ttystat(const char *line, struct stat *st)
53611eaad35SDavid van Moolenbroek {
53711eaad35SDavid van Moolenbroek 	char ttybuf[MAXPATHLEN];
53811eaad35SDavid van Moolenbroek 
53911eaad35SDavid van Moolenbroek 	(void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line);
54011eaad35SDavid van Moolenbroek 	return stat(ttybuf, st);
54111eaad35SDavid van Moolenbroek }
54211eaad35SDavid van Moolenbroek 
54311eaad35SDavid van Moolenbroek static void
process(struct entry * ep)54411eaad35SDavid van Moolenbroek process(struct entry *ep)
54511eaad35SDavid van Moolenbroek {
54611eaad35SDavid van Moolenbroek 	struct stat st;
54711eaad35SDavid van Moolenbroek 	time_t touched;
54811eaad35SDavid van Moolenbroek 	int max;
54911eaad35SDavid van Moolenbroek 
55011eaad35SDavid van Moolenbroek 	if ((max = strlen(ep->name)) > maxname)
55111eaad35SDavid van Moolenbroek 		maxname = max;
55211eaad35SDavid van Moolenbroek 	if ((max = strlen(ep->line)) > maxline)
55311eaad35SDavid van Moolenbroek 		maxline = max;
55411eaad35SDavid van Moolenbroek 	if ((max = strlen(ep->host)) > maxhost)
55511eaad35SDavid van Moolenbroek 		maxhost = max;
55611eaad35SDavid van Moolenbroek 
55711eaad35SDavid van Moolenbroek 	ep->tdev = 0;
55811eaad35SDavid van Moolenbroek 	ep->idle = (time_t)-1;
55911eaad35SDavid van Moolenbroek 
56011eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
56111eaad35SDavid van Moolenbroek 	/*
56211eaad35SDavid van Moolenbroek 	 * Hack to recognize and correctly parse
56311eaad35SDavid van Moolenbroek 	 * ut entry made by ftpd. The "tty" used
56411eaad35SDavid van Moolenbroek 	 * by ftpd is not a real tty, just identifier in
56511eaad35SDavid van Moolenbroek 	 * form ftpPID. Pid parsed from the "tty name"
56611eaad35SDavid van Moolenbroek 	 * is used later to match corresponding process.
56711eaad35SDavid van Moolenbroek 	 * NB: This is only used for utmp entries. For utmpx,
56811eaad35SDavid van Moolenbroek 	 * we already have the pid.
56911eaad35SDavid van Moolenbroek 	 */
57011eaad35SDavid van Moolenbroek 	if (ep->pid == 0 && strncmp(ep->line, "ftp", 3) == 0) {
57111eaad35SDavid van Moolenbroek 		ep->pid = strtol(ep->line + 3, NULL, 10);
57211eaad35SDavid van Moolenbroek 		return;
57311eaad35SDavid van Moolenbroek 	}
57411eaad35SDavid van Moolenbroek #endif
57511eaad35SDavid van Moolenbroek 	if (ttystat(ep->line, &st) == -1)
57611eaad35SDavid van Moolenbroek 		return;
57711eaad35SDavid van Moolenbroek 
57811eaad35SDavid van Moolenbroek 	ep->tdev = st.st_rdev;
57911eaad35SDavid van Moolenbroek 	/*
58011eaad35SDavid van Moolenbroek 	 * If this is the console device, attempt to ascertain
58111eaad35SDavid van Moolenbroek 	 * the true console device dev_t.
58211eaad35SDavid van Moolenbroek 	 */
58311eaad35SDavid van Moolenbroek 	if (ep->tdev == 0) {
58411eaad35SDavid van Moolenbroek 		int mib[2];
58511eaad35SDavid van Moolenbroek 		size_t size;
58611eaad35SDavid van Moolenbroek 
58711eaad35SDavid van Moolenbroek 		mib[0] = CTL_KERN;
58811eaad35SDavid van Moolenbroek 		mib[1] = KERN_CONSDEV;
58911eaad35SDavid van Moolenbroek 		size = sizeof(dev_t);
59011eaad35SDavid van Moolenbroek 		(void) sysctl(mib, 2, &ep->tdev, &size, NULL, 0);
59111eaad35SDavid van Moolenbroek 	}
59211eaad35SDavid van Moolenbroek 
59311eaad35SDavid van Moolenbroek 	touched = st.st_atime;
59411eaad35SDavid van Moolenbroek 	if (touched < ep->tv.tv_sec) {
59511eaad35SDavid van Moolenbroek 		/* tty untouched since before login */
59611eaad35SDavid van Moolenbroek 		touched = ep->tv.tv_sec;
59711eaad35SDavid van Moolenbroek 	}
59811eaad35SDavid van Moolenbroek 	if ((ep->idle = now - touched) < 0)
59911eaad35SDavid van Moolenbroek 		ep->idle = 0;
60011eaad35SDavid van Moolenbroek }
60111eaad35SDavid van Moolenbroek #endif
60211eaad35SDavid van Moolenbroek 
60311eaad35SDavid van Moolenbroek static int
proc_compare_wrapper(const struct kinfo_proc2 * p1,const struct kinfo_proc2 * p2)60411eaad35SDavid van Moolenbroek proc_compare_wrapper(const struct kinfo_proc2 *p1,
60511eaad35SDavid van Moolenbroek     const struct kinfo_proc2 *p2)
60611eaad35SDavid van Moolenbroek {
60711eaad35SDavid van Moolenbroek 	struct kinfo_lwp *l1, *l2;
60811eaad35SDavid van Moolenbroek 	int cnt;
60911eaad35SDavid van Moolenbroek 
61011eaad35SDavid van Moolenbroek 	if (p1 == NULL)
61111eaad35SDavid van Moolenbroek 		return 1;
61211eaad35SDavid van Moolenbroek 
61311eaad35SDavid van Moolenbroek 	l1 = kvm_getlwps(kd, p1->p_pid, 0, sizeof(*l1), &cnt);
61411eaad35SDavid van Moolenbroek 	if (l1 == NULL || cnt == 0)
61511eaad35SDavid van Moolenbroek 		return 1;
61611eaad35SDavid van Moolenbroek 
61711eaad35SDavid van Moolenbroek 	l2 = kvm_getlwps(kd, p2->p_pid, 0, sizeof(*l1), &cnt);
61811eaad35SDavid van Moolenbroek 	if (l2 == NULL || cnt == 0)
61911eaad35SDavid van Moolenbroek 		return 0;
62011eaad35SDavid van Moolenbroek 
62111eaad35SDavid van Moolenbroek 	return proc_compare(p1, l1, p2, l2);
62211eaad35SDavid van Moolenbroek }
62311eaad35SDavid van Moolenbroek 
62411eaad35SDavid van Moolenbroek static void
fixhost(struct entry * ep)62511eaad35SDavid van Moolenbroek fixhost(struct entry *ep)
62611eaad35SDavid van Moolenbroek {
62711eaad35SDavid van Moolenbroek 	char host_buf[sizeof(ep->host)];
62811eaad35SDavid van Moolenbroek 	char *p, *x;
62911eaad35SDavid van Moolenbroek 	struct hostent *hp;
63011eaad35SDavid van Moolenbroek 	struct in_addr l;
63111eaad35SDavid van Moolenbroek 
63211eaad35SDavid van Moolenbroek 	strlcpy(host_buf, *ep->host ? ep->host : "-", sizeof(host_buf));
63311eaad35SDavid van Moolenbroek 	p = host_buf;
63411eaad35SDavid van Moolenbroek 
63511eaad35SDavid van Moolenbroek 	/*
63611eaad35SDavid van Moolenbroek 	 * XXX: Historical behavior, ':' in hostname means X display number,
63711eaad35SDavid van Moolenbroek 	 * IPv6 not handled.
63811eaad35SDavid van Moolenbroek 	 */
63911eaad35SDavid van Moolenbroek 	for (x = p; x < &host_buf[sizeof(host_buf)]; x++)
64011eaad35SDavid van Moolenbroek 		if (*x == '\0' || *x == ':')
64111eaad35SDavid van Moolenbroek 			break;
64211eaad35SDavid van Moolenbroek 	if (x == p + sizeof(host_buf) || *x != ':')
64311eaad35SDavid van Moolenbroek 		x = NULL;
64411eaad35SDavid van Moolenbroek 	else
64511eaad35SDavid van Moolenbroek 		*x++ = '\0';
64611eaad35SDavid van Moolenbroek 
64711eaad35SDavid van Moolenbroek 	if (!nflag && inet_aton(p, &l) &&
64811eaad35SDavid van Moolenbroek 	    (hp = gethostbyaddr((char *)&l, sizeof(l), AF_INET))) {
64911eaad35SDavid van Moolenbroek 		if (domain[0] != '\0') {
65011eaad35SDavid van Moolenbroek 			p = hp->h_name;
65111eaad35SDavid van Moolenbroek 			p += strlen(hp->h_name);
65211eaad35SDavid van Moolenbroek 			p -= strlen(domain);
65311eaad35SDavid van Moolenbroek 			if (p > hp->h_name &&
65411eaad35SDavid van Moolenbroek 			    strcasecmp(p, domain) == 0)
65511eaad35SDavid van Moolenbroek 				*p = '\0';
65611eaad35SDavid van Moolenbroek 		}
65711eaad35SDavid van Moolenbroek 		p = hp->h_name;
65811eaad35SDavid van Moolenbroek 	}
65911eaad35SDavid van Moolenbroek 
66011eaad35SDavid van Moolenbroek 	if (x)
66111eaad35SDavid van Moolenbroek 		(void)snprintf(ep->host, sizeof(ep->host), "%s:%s", p, x);
66211eaad35SDavid van Moolenbroek 	else
66311eaad35SDavid van Moolenbroek 
66411eaad35SDavid van Moolenbroek 		strlcpy(ep->host, p, sizeof(ep->host));
66511eaad35SDavid van Moolenbroek }
66611eaad35SDavid van Moolenbroek 
66711eaad35SDavid van Moolenbroek static void
usage(int wcmd)66811eaad35SDavid van Moolenbroek usage(int wcmd)
66911eaad35SDavid van Moolenbroek {
67011eaad35SDavid van Moolenbroek 
67111eaad35SDavid van Moolenbroek 	if (wcmd)
67211eaad35SDavid van Moolenbroek 		(void)fprintf(stderr,
67311eaad35SDavid van Moolenbroek 		    "Usage: %s [-hinw] [-M core] [-N system] [user]\n",
67411eaad35SDavid van Moolenbroek 		    getprogname());
67511eaad35SDavid van Moolenbroek 	else
67611eaad35SDavid van Moolenbroek 		(void)fprintf(stderr, "Usage: %s\n", getprogname());
67711eaad35SDavid van Moolenbroek 	exit(1);
67811eaad35SDavid van Moolenbroek }
679