xref: /titanic_50/usr/src/cmd/rpcsvc/rusers.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate /*
25*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
27*7c478bd9Sstevel@tonic-gate  */
28*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
32*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
33*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
36*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
37*7c478bd9Sstevel@tonic-gate  * contributors.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
43*7c478bd9Sstevel@tonic-gate #include <stdio.h>
44*7c478bd9Sstevel@tonic-gate #include <unistd.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
46*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
47*7c478bd9Sstevel@tonic-gate #include <netdir.h>
48*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
49*7c478bd9Sstevel@tonic-gate #include <rpcsvc/rusers.h>
50*7c478bd9Sstevel@tonic-gate #include <string.h>
51*7c478bd9Sstevel@tonic-gate #include <limits.h>
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #define	NMAX	12		/* These are used as field width specifiers */
54*7c478bd9Sstevel@tonic-gate #define	LMAX	8		/* when printing.			    */
55*7c478bd9Sstevel@tonic-gate #define	HMAX	16		/* "Logged in" host name. */
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate #define	MACHINELEN 16		/* length of machine name printed out */
58*7c478bd9Sstevel@tonic-gate #define	NUMENTRIES 256
59*7c478bd9Sstevel@tonic-gate #define	min(a, b) ((a) < (b) ? (a) : (b))
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate struct entry {
62*7c478bd9Sstevel@tonic-gate 	int cnt;
63*7c478bd9Sstevel@tonic-gate 	int idle;		/* set to INT_MAX if not present */
64*7c478bd9Sstevel@tonic-gate 	char *machine;
65*7c478bd9Sstevel@tonic-gate 	utmp_array users;
66*7c478bd9Sstevel@tonic-gate };
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate static int curentry;
69*7c478bd9Sstevel@tonic-gate static int total_entries;
70*7c478bd9Sstevel@tonic-gate static struct entry *entry;
71*7c478bd9Sstevel@tonic-gate static int hflag;		/* host: sort by machine name */
72*7c478bd9Sstevel@tonic-gate static int iflag;		/* idle: sort by idle time */
73*7c478bd9Sstevel@tonic-gate static int uflag;		/* users: sort by number of users */
74*7c478bd9Sstevel@tonic-gate static int lflag;		/* print out long form */
75*7c478bd9Sstevel@tonic-gate static int aflag;		/* all: list all machines */
76*7c478bd9Sstevel@tonic-gate static int dflag;		/* debug: list only first n machines */
77*7c478bd9Sstevel@tonic-gate static int sorted;
78*7c478bd9Sstevel@tonic-gate static int debug;
79*7c478bd9Sstevel@tonic-gate static int debugcnt;
80*7c478bd9Sstevel@tonic-gate static char *nettype;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate static int hcompare(const struct entry *, const struct entry *);
83*7c478bd9Sstevel@tonic-gate static int icompare(const struct entry *, const struct entry *);
84*7c478bd9Sstevel@tonic-gate static int ucompare(const struct entry *, const struct entry *);
85*7c478bd9Sstevel@tonic-gate static int print_info(struct utmpidlearr *, const char *);
86*7c478bd9Sstevel@tonic-gate static int print_info_3(utmp_array *, const char *);
87*7c478bd9Sstevel@tonic-gate static int collectnames(void *, struct netbuf *, struct netconfig *);
88*7c478bd9Sstevel@tonic-gate static int collectnames_3(void *, struct netbuf *, struct netconfig *);
89*7c478bd9Sstevel@tonic-gate static void singlehost(char *);
90*7c478bd9Sstevel@tonic-gate static void printnames(void);
91*7c478bd9Sstevel@tonic-gate static void putline_2(char *, struct utmpidle *);
92*7c478bd9Sstevel@tonic-gate static void putline_3(char *, rusers_utmp *);
93*7c478bd9Sstevel@tonic-gate static void prttime(uint_t, char *);
94*7c478bd9Sstevel@tonic-gate static void usage(void);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate /*
97*7c478bd9Sstevel@tonic-gate  * rusers [-ahilu] [host...]
98*7c478bd9Sstevel@tonic-gate  */
99*7c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])100*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
101*7c478bd9Sstevel@tonic-gate {
102*7c478bd9Sstevel@tonic-gate 	int c;
103*7c478bd9Sstevel@tonic-gate 	uint_t errflag = 0;
104*7c478bd9Sstevel@tonic-gate 	uint_t single = 0;
105*7c478bd9Sstevel@tonic-gate 	struct utmpidlearr utmpidlearr;
106*7c478bd9Sstevel@tonic-gate 	utmp_array	utmp_array_res;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	curentry = 0;
109*7c478bd9Sstevel@tonic-gate 	total_entries = NUMENTRIES;
110*7c478bd9Sstevel@tonic-gate 	entry = malloc(sizeof (struct entry) * total_entries);
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, ":ad:hilun:")) != -1) {
113*7c478bd9Sstevel@tonic-gate 		switch (c) {
114*7c478bd9Sstevel@tonic-gate 		case 'a':
115*7c478bd9Sstevel@tonic-gate 			aflag++;
116*7c478bd9Sstevel@tonic-gate 			break;
117*7c478bd9Sstevel@tonic-gate 		case 'd':
118*7c478bd9Sstevel@tonic-gate 			dflag++;
119*7c478bd9Sstevel@tonic-gate 			debug = atoi(optarg);
120*7c478bd9Sstevel@tonic-gate 			(void) printf("Will collect %d responses.\n", debug);
121*7c478bd9Sstevel@tonic-gate 			break;
122*7c478bd9Sstevel@tonic-gate 		case 'h':
123*7c478bd9Sstevel@tonic-gate 			hflag++;
124*7c478bd9Sstevel@tonic-gate 			sorted++;
125*7c478bd9Sstevel@tonic-gate 			if (iflag || uflag)
126*7c478bd9Sstevel@tonic-gate 				errflag++;
127*7c478bd9Sstevel@tonic-gate 			break;
128*7c478bd9Sstevel@tonic-gate 		case 'i':
129*7c478bd9Sstevel@tonic-gate 			iflag++;
130*7c478bd9Sstevel@tonic-gate 			sorted++;
131*7c478bd9Sstevel@tonic-gate 			if (hflag || uflag)
132*7c478bd9Sstevel@tonic-gate 				errflag++;
133*7c478bd9Sstevel@tonic-gate 			break;
134*7c478bd9Sstevel@tonic-gate 		case 'u':
135*7c478bd9Sstevel@tonic-gate 			uflag++;
136*7c478bd9Sstevel@tonic-gate 			sorted++;
137*7c478bd9Sstevel@tonic-gate 			if (hflag || iflag)
138*7c478bd9Sstevel@tonic-gate 				errflag++;
139*7c478bd9Sstevel@tonic-gate 			break;
140*7c478bd9Sstevel@tonic-gate 		case 'l':
141*7c478bd9Sstevel@tonic-gate 			lflag++;
142*7c478bd9Sstevel@tonic-gate 			break;
143*7c478bd9Sstevel@tonic-gate 		case ':':	/* required operand missing */
144*7c478bd9Sstevel@tonic-gate 			errflag++;
145*7c478bd9Sstevel@tonic-gate 			break;
146*7c478bd9Sstevel@tonic-gate 		case 'n':
147*7c478bd9Sstevel@tonic-gate 			nettype = optarg;
148*7c478bd9Sstevel@tonic-gate 			break;
149*7c478bd9Sstevel@tonic-gate 		default:
150*7c478bd9Sstevel@tonic-gate 		case '?':	/* Unrecognized option */
151*7c478bd9Sstevel@tonic-gate 			errflag++;
152*7c478bd9Sstevel@tonic-gate 			break;
153*7c478bd9Sstevel@tonic-gate 		}
154*7c478bd9Sstevel@tonic-gate 	}
155*7c478bd9Sstevel@tonic-gate 	if (errflag)
156*7c478bd9Sstevel@tonic-gate 		usage();
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	for (; optind < argc; optind++) {
159*7c478bd9Sstevel@tonic-gate 		single++;
160*7c478bd9Sstevel@tonic-gate 		singlehost(argv[optind]);
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 	if (single) {
163*7c478bd9Sstevel@tonic-gate 		if (sorted)
164*7c478bd9Sstevel@tonic-gate 			printnames();
165*7c478bd9Sstevel@tonic-gate 		free(entry);
166*7c478bd9Sstevel@tonic-gate 		exit(0);
167*7c478bd9Sstevel@tonic-gate 	}
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	if (sorted) {
170*7c478bd9Sstevel@tonic-gate 		(void) printf("Collecting responses...\n");
171*7c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
172*7c478bd9Sstevel@tonic-gate 	}
173*7c478bd9Sstevel@tonic-gate 	utmp_array_res.utmp_array_val = NULL;
174*7c478bd9Sstevel@tonic-gate 	utmp_array_res.utmp_array_len = 0;
175*7c478bd9Sstevel@tonic-gate 	(void) printf("Sending broadcast for rusersd protocol version 3...\n");
176*7c478bd9Sstevel@tonic-gate 	(void) rpc_broadcast(RUSERSPROG, RUSERSVERS_3,
177*7c478bd9Sstevel@tonic-gate 		RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
178*7c478bd9Sstevel@tonic-gate 		(xdrproc_t)xdr_utmp_array, (char *)&utmp_array_res,
179*7c478bd9Sstevel@tonic-gate 		(resultproc_t)collectnames_3, nettype);
180*7c478bd9Sstevel@tonic-gate 	utmpidlearr.uia_arr = NULL;
181*7c478bd9Sstevel@tonic-gate 	(void) printf("Sending broadcast for rusersd protocol version 2...\n");
182*7c478bd9Sstevel@tonic-gate 	(void) rpc_broadcast(RUSERSPROG, RUSERSVERS_IDLE,
183*7c478bd9Sstevel@tonic-gate 		RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
184*7c478bd9Sstevel@tonic-gate 		(xdrproc_t)xdr_utmpidlearr, (char *)&utmpidlearr,
185*7c478bd9Sstevel@tonic-gate 		(resultproc_t)collectnames, nettype);
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	if (sorted)
188*7c478bd9Sstevel@tonic-gate 		printnames();
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	free(entry);
191*7c478bd9Sstevel@tonic-gate 	return (0);
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate static void
singlehost(char * name)195*7c478bd9Sstevel@tonic-gate singlehost(char *name)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	enum clnt_stat err;
198*7c478bd9Sstevel@tonic-gate 	struct utmpidlearr utmpidlearr;
199*7c478bd9Sstevel@tonic-gate 	utmp_array	utmp_array_res;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	if (curentry >= total_entries) {
202*7c478bd9Sstevel@tonic-gate 		struct entry *tmp;
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 		total_entries += NUMENTRIES;
205*7c478bd9Sstevel@tonic-gate 		if ((tmp = realloc(entry, sizeof (struct entry)
206*7c478bd9Sstevel@tonic-gate 						* total_entries)) == NULL)
207*7c478bd9Sstevel@tonic-gate 			return;
208*7c478bd9Sstevel@tonic-gate 		entry = tmp;
209*7c478bd9Sstevel@tonic-gate 	}
210*7c478bd9Sstevel@tonic-gate 	utmp_array_res.utmp_array_val = NULL;
211*7c478bd9Sstevel@tonic-gate 	utmp_array_res.utmp_array_len = 0;
212*7c478bd9Sstevel@tonic-gate 	err = rpc_call(name, RUSERSPROG, RUSERSVERS_3,
213*7c478bd9Sstevel@tonic-gate 		RUSERSPROC_NAMES, (xdrproc_t)xdr_void, 0,
214*7c478bd9Sstevel@tonic-gate 		(xdrproc_t)xdr_utmp_array, (char *)&utmp_array_res,
215*7c478bd9Sstevel@tonic-gate 		nettype);
216*7c478bd9Sstevel@tonic-gate 	if (err == RPC_SUCCESS) {
217*7c478bd9Sstevel@tonic-gate 		(void) print_info_3(&utmp_array_res, name);
218*7c478bd9Sstevel@tonic-gate 		return;
219*7c478bd9Sstevel@tonic-gate 	}
220*7c478bd9Sstevel@tonic-gate 	if (err == RPC_PROGVERSMISMATCH) {
221*7c478bd9Sstevel@tonic-gate 		utmpidlearr.uia_arr = NULL;
222*7c478bd9Sstevel@tonic-gate 		err = rpc_call(name, RUSERSPROG, RUSERSVERS_IDLE,
223*7c478bd9Sstevel@tonic-gate 				RUSERSPROC_NAMES, (xdrproc_t)xdr_void, 0,
224*7c478bd9Sstevel@tonic-gate 				(xdrproc_t)xdr_utmpidlearr,
225*7c478bd9Sstevel@tonic-gate 				(char *)&utmpidlearr, nettype);
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 	if (err != RPC_SUCCESS) {
228*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: ", name);
229*7c478bd9Sstevel@tonic-gate 		clnt_perrno(err);
230*7c478bd9Sstevel@tonic-gate 		return;
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 	(void) print_info(&utmpidlearr, name);
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate /*
236*7c478bd9Sstevel@tonic-gate  * Collect responses from RUSERSVERS_IDLE broadcast, convert to
237*7c478bd9Sstevel@tonic-gate  * RUSERSVERS_3 format, and store in entry database.
238*7c478bd9Sstevel@tonic-gate  */
239*7c478bd9Sstevel@tonic-gate static int
collectnames(void * resultsp,struct netbuf * raddrp,struct netconfig * nconf)240*7c478bd9Sstevel@tonic-gate collectnames(void *resultsp, struct netbuf *raddrp, struct netconfig *nconf)
241*7c478bd9Sstevel@tonic-gate {
242*7c478bd9Sstevel@tonic-gate 	struct utmpidlearr utmpidlearr;
243*7c478bd9Sstevel@tonic-gate 	struct entry *entryp, *lim;
244*7c478bd9Sstevel@tonic-gate 	struct nd_hostservlist *hs;
245*7c478bd9Sstevel@tonic-gate 	char host[MACHINELEN + 1];
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	utmpidlearr = *(struct utmpidlearr *)resultsp;
248*7c478bd9Sstevel@tonic-gate 	if (utmpidlearr.uia_cnt < 1 && !aflag)
249*7c478bd9Sstevel@tonic-gate 		return (0);
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	if (netdir_getbyaddr(nconf, &hs, raddrp)) {
252*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
253*7c478bd9Sstevel@tonic-gate 		netdir_perror("netdir_getbyaddr");
254*7c478bd9Sstevel@tonic-gate #endif
255*7c478bd9Sstevel@tonic-gate 		/* netdir routine couldn't resolve addr;just print out uaddr */
256*7c478bd9Sstevel@tonic-gate 		(void) sprintf(host, "%.*s", MACHINELEN,
257*7c478bd9Sstevel@tonic-gate 						taddr2uaddr(nconf, raddrp));
258*7c478bd9Sstevel@tonic-gate 	} else {
259*7c478bd9Sstevel@tonic-gate 		(void) sprintf(host, "%.*s", MACHINELEN,
260*7c478bd9Sstevel@tonic-gate 						hs->h_hostservs->h_host);
261*7c478bd9Sstevel@tonic-gate 		netdir_free((char *)hs, ND_HOSTSERVLIST);
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 	/*
264*7c478bd9Sstevel@tonic-gate 	 * need to realloc more space if we have more than 256 machines
265*7c478bd9Sstevel@tonic-gate 	 * that respond to broadcast
266*7c478bd9Sstevel@tonic-gate 	 */
267*7c478bd9Sstevel@tonic-gate 	if (curentry >= total_entries) {
268*7c478bd9Sstevel@tonic-gate 		struct entry *tmp;
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 		total_entries += NUMENTRIES;
271*7c478bd9Sstevel@tonic-gate 		if ((tmp = realloc(entry, sizeof (struct entry)
272*7c478bd9Sstevel@tonic-gate 						* total_entries)) == NULL)
273*7c478bd9Sstevel@tonic-gate 			return (1);
274*7c478bd9Sstevel@tonic-gate 		entry = tmp;
275*7c478bd9Sstevel@tonic-gate 	}
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	/*
279*7c478bd9Sstevel@tonic-gate 	 * weed out duplicates
280*7c478bd9Sstevel@tonic-gate 	 */
281*7c478bd9Sstevel@tonic-gate 	lim = entry + curentry;
282*7c478bd9Sstevel@tonic-gate 	for (entryp = entry; entryp < lim; entryp++) {
283*7c478bd9Sstevel@tonic-gate 		if (strcmp(entryp->machine, host) == 0)
284*7c478bd9Sstevel@tonic-gate 			return (0);
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 	return (print_info((struct utmpidlearr *)resultsp, host));
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate static int
print_info(struct utmpidlearr * utmpidlearrp,const char * name)290*7c478bd9Sstevel@tonic-gate print_info(struct utmpidlearr *utmpidlearrp, const char *name)
291*7c478bd9Sstevel@tonic-gate {
292*7c478bd9Sstevel@tonic-gate 	utmp_array *iconvert;
293*7c478bd9Sstevel@tonic-gate 	int i, cnt, minidle;
294*7c478bd9Sstevel@tonic-gate 	char host[MACHINELEN + 1];
295*7c478bd9Sstevel@tonic-gate 	char username[NMAX + 1];
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	cnt = utmpidlearrp->uia_cnt;
298*7c478bd9Sstevel@tonic-gate 	(void) sprintf(host, "%.*s", MACHINELEN, name);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	/*
301*7c478bd9Sstevel@tonic-gate 	 * if raw, print this entry out immediately
302*7c478bd9Sstevel@tonic-gate 	 * otherwise store for later sorting
303*7c478bd9Sstevel@tonic-gate 	 */
304*7c478bd9Sstevel@tonic-gate 	if (!sorted) {
305*7c478bd9Sstevel@tonic-gate 		if (lflag && (cnt > 0))
306*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < cnt; i++)
307*7c478bd9Sstevel@tonic-gate 				putline_2(host, utmpidlearrp->uia_arr[i]);
308*7c478bd9Sstevel@tonic-gate 		else {
309*7c478bd9Sstevel@tonic-gate 		    (void) printf("%-*.*s", MACHINELEN, MACHINELEN, host);
310*7c478bd9Sstevel@tonic-gate 		    for (i = 0; i < cnt; i++) {
311*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(username,
312*7c478bd9Sstevel@tonic-gate 				    utmpidlearrp->uia_arr[i]->ui_utmp.ut_name,
313*7c478bd9Sstevel@tonic-gate 				    NMAX + 1);
314*7c478bd9Sstevel@tonic-gate 			(void) printf(" %.*s", NMAX, username);
315*7c478bd9Sstevel@tonic-gate 		    }
316*7c478bd9Sstevel@tonic-gate 		    (void) printf("\n");
317*7c478bd9Sstevel@tonic-gate 		}
318*7c478bd9Sstevel@tonic-gate 		/* store just the name */
319*7c478bd9Sstevel@tonic-gate 		entry[curentry].machine = malloc(MACHINELEN + 1);
320*7c478bd9Sstevel@tonic-gate 		if (entry[curentry].machine == NULL) {
321*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Ran out of memory - exiting\n");
322*7c478bd9Sstevel@tonic-gate 			exit(1);
323*7c478bd9Sstevel@tonic-gate 		}
324*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(entry[curentry].machine, name, MACHINELEN + 1);
325*7c478bd9Sstevel@tonic-gate 		entry[curentry++].cnt = 0;
326*7c478bd9Sstevel@tonic-gate 		if (dflag && (++debugcnt >= debug))
327*7c478bd9Sstevel@tonic-gate 			return (1);
328*7c478bd9Sstevel@tonic-gate 		return (0);
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate 	entry[curentry].machine = malloc(MACHINELEN + 1);
331*7c478bd9Sstevel@tonic-gate 	if (entry[curentry].machine == NULL) {
332*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Ran out of memory - exiting\n");
333*7c478bd9Sstevel@tonic-gate 		exit(1);
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(entry[curentry].machine, name, MACHINELEN + 1);
336*7c478bd9Sstevel@tonic-gate 	entry[curentry].cnt = cnt;
337*7c478bd9Sstevel@tonic-gate 	iconvert = &entry[curentry].users;
338*7c478bd9Sstevel@tonic-gate 	iconvert->utmp_array_len = cnt;
339*7c478bd9Sstevel@tonic-gate 	iconvert->utmp_array_val = malloc(cnt * sizeof (rusers_utmp));
340*7c478bd9Sstevel@tonic-gate 	minidle = INT_MAX;
341*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < cnt; i++) {
342*7c478bd9Sstevel@tonic-gate 		iconvert->utmp_array_val[i].ut_user =
343*7c478bd9Sstevel@tonic-gate 			strdup(utmpidlearrp->uia_arr[i]->ui_utmp.ut_name);
344*7c478bd9Sstevel@tonic-gate 		iconvert->utmp_array_val[i].ut_line =
345*7c478bd9Sstevel@tonic-gate 			strdup(utmpidlearrp->uia_arr[i]->ui_utmp.ut_line);
346*7c478bd9Sstevel@tonic-gate 		iconvert->utmp_array_val[i].ut_host =
347*7c478bd9Sstevel@tonic-gate 			strdup(utmpidlearrp->uia_arr[i]->ui_utmp.ut_host);
348*7c478bd9Sstevel@tonic-gate 		iconvert->utmp_array_val[i].ut_time =
349*7c478bd9Sstevel@tonic-gate 			utmpidlearrp->uia_arr[i]->ui_utmp.ut_time;
350*7c478bd9Sstevel@tonic-gate 		iconvert->utmp_array_val[i].ut_idle =
351*7c478bd9Sstevel@tonic-gate 			utmpidlearrp->uia_arr[i]->ui_idle;
352*7c478bd9Sstevel@tonic-gate 		minidle = min(minidle, utmpidlearrp->uia_arr[i]->ui_idle);
353*7c478bd9Sstevel@tonic-gate 	}
354*7c478bd9Sstevel@tonic-gate 	entry[curentry].idle = minidle;
355*7c478bd9Sstevel@tonic-gate 	curentry++;
356*7c478bd9Sstevel@tonic-gate 	if (dflag && (++debugcnt >= debug))
357*7c478bd9Sstevel@tonic-gate 		return (1);
358*7c478bd9Sstevel@tonic-gate 	return (0);
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate /*
363*7c478bd9Sstevel@tonic-gate  * Collect responses from RUSERSVERS_3 broadcast.
364*7c478bd9Sstevel@tonic-gate  */
365*7c478bd9Sstevel@tonic-gate static int
collectnames_3(void * resultsp,struct netbuf * raddrp,struct netconfig * nconf)366*7c478bd9Sstevel@tonic-gate collectnames_3(void *resultsp, struct netbuf *raddrp, struct netconfig *nconf)
367*7c478bd9Sstevel@tonic-gate {
368*7c478bd9Sstevel@tonic-gate 	utmp_array *uap;
369*7c478bd9Sstevel@tonic-gate 	struct entry *entryp, *lim;
370*7c478bd9Sstevel@tonic-gate 	struct nd_hostservlist *hs;
371*7c478bd9Sstevel@tonic-gate 	char host[MACHINELEN + 1];
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	uap = (utmp_array *)resultsp;
374*7c478bd9Sstevel@tonic-gate 	if (uap->utmp_array_len < 1 && !aflag)
375*7c478bd9Sstevel@tonic-gate 		return (0);
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	if (netdir_getbyaddr(nconf, &hs, raddrp)) {
378*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
379*7c478bd9Sstevel@tonic-gate 	netdir_perror("netdir_getbyaddr");
380*7c478bd9Sstevel@tonic-gate #endif
381*7c478bd9Sstevel@tonic-gate 		/* netdir routine couldn't resolve addr;just print out uaddr */
382*7c478bd9Sstevel@tonic-gate 		(void) sprintf(host, "%.*s", MACHINELEN,
383*7c478bd9Sstevel@tonic-gate 						taddr2uaddr(nconf, raddrp));
384*7c478bd9Sstevel@tonic-gate 	} else {
385*7c478bd9Sstevel@tonic-gate 		(void) sprintf(host, "%.*s", MACHINELEN,
386*7c478bd9Sstevel@tonic-gate 						hs->h_hostservs->h_host);
387*7c478bd9Sstevel@tonic-gate 		netdir_free((char *)hs, ND_HOSTSERVLIST);
388*7c478bd9Sstevel@tonic-gate 	}
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	/*
391*7c478bd9Sstevel@tonic-gate 	 * need to realloc more space if we have more than 256 machines
392*7c478bd9Sstevel@tonic-gate 	 * that respond to broadcast
393*7c478bd9Sstevel@tonic-gate 	 */
394*7c478bd9Sstevel@tonic-gate 	if (curentry >= total_entries) {
395*7c478bd9Sstevel@tonic-gate 		struct entry *tmp;
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 		total_entries += NUMENTRIES;
398*7c478bd9Sstevel@tonic-gate 		if ((tmp = realloc(entry, sizeof (struct entry)
399*7c478bd9Sstevel@tonic-gate 						* total_entries)) == NULL)
400*7c478bd9Sstevel@tonic-gate 			return (1);
401*7c478bd9Sstevel@tonic-gate 		entry = tmp;
402*7c478bd9Sstevel@tonic-gate 	}
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	/*
406*7c478bd9Sstevel@tonic-gate 	 * weed out duplicates
407*7c478bd9Sstevel@tonic-gate 	 */
408*7c478bd9Sstevel@tonic-gate 	lim = entry + curentry;
409*7c478bd9Sstevel@tonic-gate 	for (entryp = entry; entryp < lim; entryp++) {
410*7c478bd9Sstevel@tonic-gate 		if (strcmp(entryp->machine, host) == 0)
411*7c478bd9Sstevel@tonic-gate 			return (0);
412*7c478bd9Sstevel@tonic-gate 	}
413*7c478bd9Sstevel@tonic-gate 	return (print_info_3(uap, host));
414*7c478bd9Sstevel@tonic-gate }
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate static int
print_info_3(utmp_array * uap,const char * name)417*7c478bd9Sstevel@tonic-gate print_info_3(utmp_array *uap, const char *name)
418*7c478bd9Sstevel@tonic-gate {
419*7c478bd9Sstevel@tonic-gate 	int i, cnt, minidle;
420*7c478bd9Sstevel@tonic-gate 	char host[MACHINELEN + 1];
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	cnt = uap->utmp_array_len;
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 	(void) sprintf(host, "%.*s", MACHINELEN, name);
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 	/*
427*7c478bd9Sstevel@tonic-gate 	 * if raw, print this entry out immediately
428*7c478bd9Sstevel@tonic-gate 	 * otherwise store for later sorting
429*7c478bd9Sstevel@tonic-gate 	 */
430*7c478bd9Sstevel@tonic-gate 	if (!sorted) {
431*7c478bd9Sstevel@tonic-gate 		if (lflag && (cnt > 0))
432*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < cnt; i++)
433*7c478bd9Sstevel@tonic-gate 				putline_3(host, &uap->utmp_array_val[i]);
434*7c478bd9Sstevel@tonic-gate 		else {
435*7c478bd9Sstevel@tonic-gate 			(void) printf("%-*.*s", MACHINELEN, MACHINELEN, host);
436*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < cnt; i++)
437*7c478bd9Sstevel@tonic-gate 				(void) printf(" %.*s", NMAX,
438*7c478bd9Sstevel@tonic-gate 				    uap->utmp_array_val[i].ut_user);
439*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
440*7c478bd9Sstevel@tonic-gate 		}
441*7c478bd9Sstevel@tonic-gate 		/* store just the name */
442*7c478bd9Sstevel@tonic-gate 		entry[curentry].machine = malloc(MACHINELEN + 1);
443*7c478bd9Sstevel@tonic-gate 		if (entry[curentry].machine == NULL) {
444*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Ran out of memory - exiting\n");
445*7c478bd9Sstevel@tonic-gate 			exit(1);
446*7c478bd9Sstevel@tonic-gate 		}
447*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(entry[curentry].machine, name, MACHINELEN + 1);
448*7c478bd9Sstevel@tonic-gate 		entry[curentry++].cnt = 0;
449*7c478bd9Sstevel@tonic-gate 		if (dflag && (++debugcnt >= debug))
450*7c478bd9Sstevel@tonic-gate 			return (1);
451*7c478bd9Sstevel@tonic-gate 		return (0);
452*7c478bd9Sstevel@tonic-gate 	}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 	entry[curentry].machine = malloc(MACHINELEN + 1);
455*7c478bd9Sstevel@tonic-gate 	if (entry[curentry].machine == NULL) {
456*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Ran out of memory - exiting\n");
457*7c478bd9Sstevel@tonic-gate 		exit(1);
458*7c478bd9Sstevel@tonic-gate 	}
459*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(entry[curentry].machine, name, MACHINELEN + 1);
460*7c478bd9Sstevel@tonic-gate 	entry[curentry].cnt = cnt;
461*7c478bd9Sstevel@tonic-gate 	entry[curentry].users.utmp_array_len = cnt;
462*7c478bd9Sstevel@tonic-gate 	entry[curentry].users.utmp_array_val = malloc(cnt *
463*7c478bd9Sstevel@tonic-gate 		sizeof (rusers_utmp));
464*7c478bd9Sstevel@tonic-gate 	minidle = INT_MAX;
465*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < cnt; i++) {
466*7c478bd9Sstevel@tonic-gate 		entry[curentry].users.utmp_array_val[i].ut_user =
467*7c478bd9Sstevel@tonic-gate 			strdup(uap->utmp_array_val[i].ut_user);
468*7c478bd9Sstevel@tonic-gate 		entry[curentry].users.utmp_array_val[i].ut_line =
469*7c478bd9Sstevel@tonic-gate 			strdup(uap->utmp_array_val[i].ut_line);
470*7c478bd9Sstevel@tonic-gate 		entry[curentry].users.utmp_array_val[i].ut_host =
471*7c478bd9Sstevel@tonic-gate 			strdup(uap->utmp_array_val[i].ut_host);
472*7c478bd9Sstevel@tonic-gate 		entry[curentry].users.utmp_array_val[i].ut_time =
473*7c478bd9Sstevel@tonic-gate 			uap->utmp_array_val[i].ut_time;
474*7c478bd9Sstevel@tonic-gate 		entry[curentry].users.utmp_array_val[i].ut_idle =
475*7c478bd9Sstevel@tonic-gate 			uap->utmp_array_val[i].ut_idle;
476*7c478bd9Sstevel@tonic-gate 		minidle = min(minidle, uap->utmp_array_val[i].ut_idle);
477*7c478bd9Sstevel@tonic-gate 	}
478*7c478bd9Sstevel@tonic-gate 	entry[curentry].idle = minidle;
479*7c478bd9Sstevel@tonic-gate 	curentry++;
480*7c478bd9Sstevel@tonic-gate 	if (dflag && (++debugcnt >= debug))
481*7c478bd9Sstevel@tonic-gate 		return (1);
482*7c478bd9Sstevel@tonic-gate 	return (0);
483*7c478bd9Sstevel@tonic-gate }
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate static void
printnames(void)486*7c478bd9Sstevel@tonic-gate printnames(void)
487*7c478bd9Sstevel@tonic-gate {
488*7c478bd9Sstevel@tonic-gate 	int i, j;
489*7c478bd9Sstevel@tonic-gate 	int (*compare)(const void *, const void *);
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	/* the name of the machine should already be in the structure */
492*7c478bd9Sstevel@tonic-gate 	if (iflag)
493*7c478bd9Sstevel@tonic-gate 		compare = (int (*)(const void *, const void *))icompare;
494*7c478bd9Sstevel@tonic-gate 	else if (hflag)
495*7c478bd9Sstevel@tonic-gate 		compare = (int (*)(const void *, const void *))hcompare;
496*7c478bd9Sstevel@tonic-gate 	else
497*7c478bd9Sstevel@tonic-gate 		compare = (int (*)(const void *, const void *))ucompare;
498*7c478bd9Sstevel@tonic-gate 	qsort(entry, curentry, sizeof (struct entry), compare);
499*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < curentry; i++) {
500*7c478bd9Sstevel@tonic-gate 		if (!lflag || (entry[i].cnt < 1)) {
501*7c478bd9Sstevel@tonic-gate 			(void) printf("%-*.*s", MACHINELEN,
502*7c478bd9Sstevel@tonic-gate 					MACHINELEN, entry[i].machine);
503*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < entry[i].cnt; j++)
504*7c478bd9Sstevel@tonic-gate 				(void) printf(" %.*s", NMAX,
505*7c478bd9Sstevel@tonic-gate 				    entry[i].users.utmp_array_val[j].ut_user);
506*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
507*7c478bd9Sstevel@tonic-gate 		} else {
508*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < entry[i].cnt; j++)
509*7c478bd9Sstevel@tonic-gate 				putline_3(entry[i].machine,
510*7c478bd9Sstevel@tonic-gate 					&entry[i].users.utmp_array_val[j]);
511*7c478bd9Sstevel@tonic-gate 		}
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate }
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate static int
hcompare(const struct entry * a,const struct entry * b)516*7c478bd9Sstevel@tonic-gate hcompare(const struct entry *a, const struct entry *b)
517*7c478bd9Sstevel@tonic-gate {
518*7c478bd9Sstevel@tonic-gate 	return (strcmp(a->machine, b->machine));
519*7c478bd9Sstevel@tonic-gate }
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate static int
ucompare(const struct entry * a,const struct entry * b)522*7c478bd9Sstevel@tonic-gate ucompare(const struct entry *a, const struct entry *b)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	return (b->cnt - a->cnt);
525*7c478bd9Sstevel@tonic-gate }
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate static int
icompare(const struct entry * a,const struct entry * b)528*7c478bd9Sstevel@tonic-gate icompare(const struct entry *a, const struct entry *b)
529*7c478bd9Sstevel@tonic-gate {
530*7c478bd9Sstevel@tonic-gate 	return (a->idle - b->idle);
531*7c478bd9Sstevel@tonic-gate }
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate static void
putline_2(char * host,struct utmpidle * uip)534*7c478bd9Sstevel@tonic-gate putline_2(char *host, struct utmpidle *uip)
535*7c478bd9Sstevel@tonic-gate {
536*7c478bd9Sstevel@tonic-gate 	char *cbuf;
537*7c478bd9Sstevel@tonic-gate 	struct ru_utmp *up;
538*7c478bd9Sstevel@tonic-gate 	char buf[100];
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	up = &uip->ui_utmp;
541*7c478bd9Sstevel@tonic-gate #define	NAMEMAX	((sizeof (up->ut_name) < NMAX) ? NMAX : sizeof (up->ut_name))
542*7c478bd9Sstevel@tonic-gate #define	NAMEMIN	((sizeof (up->ut_name) > NMAX) ? NMAX : sizeof (up->ut_name))
543*7c478bd9Sstevel@tonic-gate 	/* Try and align this up nicely */
544*7c478bd9Sstevel@tonic-gate #define	LINEMAX	sizeof (up->ut_line)
545*7c478bd9Sstevel@tonic-gate #define	HOSTMAX	sizeof (up->ut_host)
546*7c478bd9Sstevel@tonic-gate 	/*
547*7c478bd9Sstevel@tonic-gate 	 * We copy the strings into a buffer because they aren't strictly
548*7c478bd9Sstevel@tonic-gate 	 * speaking strings but byte arrays (and they may not have a
549*7c478bd9Sstevel@tonic-gate 	 * terminating NULL.
550*7c478bd9Sstevel@tonic-gate 	 */
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 	(void) strncpy(buf, up->ut_name, NAMEMAX);
553*7c478bd9Sstevel@tonic-gate 	buf[NAMEMIN] = '\0';
554*7c478bd9Sstevel@tonic-gate 	(void) printf("%-*.*s ", NAMEMAX, NAMEMAX, buf);
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 	(void) strcpy(buf, host);
557*7c478bd9Sstevel@tonic-gate 	(void) strcat(buf, ":");
558*7c478bd9Sstevel@tonic-gate 	(void) strncat(buf, up->ut_line, LINEMAX);
559*7c478bd9Sstevel@tonic-gate 	buf[MACHINELEN+LINEMAX] = '\0';
560*7c478bd9Sstevel@tonic-gate 	(void) printf("%-*.*s", MACHINELEN+LINEMAX, MACHINELEN+LINEMAX, buf);
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 	cbuf = (char *)ctime(&up->ut_time);
563*7c478bd9Sstevel@tonic-gate 	(void) printf("  %.12s  ", cbuf+4);
564*7c478bd9Sstevel@tonic-gate 	if (uip->ui_idle == INT_MAX)
565*7c478bd9Sstevel@tonic-gate 		(void) printf("    ??");
566*7c478bd9Sstevel@tonic-gate 	else
567*7c478bd9Sstevel@tonic-gate 		prttime(uip->ui_idle, "");
568*7c478bd9Sstevel@tonic-gate 	if (up->ut_host[0]) {
569*7c478bd9Sstevel@tonic-gate 		(void) strncpy(buf, up->ut_host, HOSTMAX);
570*7c478bd9Sstevel@tonic-gate 		buf[HOSTMAX] = '\0';
571*7c478bd9Sstevel@tonic-gate 		(void) printf(" (%.*s)", HOSTMAX, buf);
572*7c478bd9Sstevel@tonic-gate 	}
573*7c478bd9Sstevel@tonic-gate 	(void) putchar('\n');
574*7c478bd9Sstevel@tonic-gate }
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate static void
putline_3(char * host,rusers_utmp * rup)577*7c478bd9Sstevel@tonic-gate putline_3(char *host, rusers_utmp *rup)
578*7c478bd9Sstevel@tonic-gate {
579*7c478bd9Sstevel@tonic-gate 	char *cbuf;
580*7c478bd9Sstevel@tonic-gate 	char buf[100];
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	(void) printf("%-*.*s ", NMAX, NMAX, rup->ut_user);
583*7c478bd9Sstevel@tonic-gate 	(void) strcpy(buf, host);
584*7c478bd9Sstevel@tonic-gate 	(void) strcat(buf, ":");
585*7c478bd9Sstevel@tonic-gate 	(void) strncat(buf, rup->ut_line, LMAX);
586*7c478bd9Sstevel@tonic-gate 	(void) printf("%-*.*s", MACHINELEN+LMAX, MACHINELEN+LMAX, buf);
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	cbuf = (char *)ctime((time_t *)&rup->ut_time);
589*7c478bd9Sstevel@tonic-gate 	(void) printf("  %.12s  ", cbuf+4);
590*7c478bd9Sstevel@tonic-gate 	if (rup->ut_idle == INT_MAX)
591*7c478bd9Sstevel@tonic-gate 		(void) printf("    ??");
592*7c478bd9Sstevel@tonic-gate 	else
593*7c478bd9Sstevel@tonic-gate 		prttime(rup->ut_idle, "");
594*7c478bd9Sstevel@tonic-gate 	if (rup->ut_host[0])
595*7c478bd9Sstevel@tonic-gate 		(void) printf(" (%.*s)", HMAX, rup->ut_host);
596*7c478bd9Sstevel@tonic-gate 	(void) putchar('\n');
597*7c478bd9Sstevel@tonic-gate }
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate /*
600*7c478bd9Sstevel@tonic-gate  * prttime prints a time in hours and minutes.
601*7c478bd9Sstevel@tonic-gate  * The character string tail is printed at the end, obvious
602*7c478bd9Sstevel@tonic-gate  * strings to pass are "", " ", or "am".
603*7c478bd9Sstevel@tonic-gate  */
604*7c478bd9Sstevel@tonic-gate static void
prttime(uint_t tim,char * tail)605*7c478bd9Sstevel@tonic-gate prttime(uint_t tim, char *tail)
606*7c478bd9Sstevel@tonic-gate {
607*7c478bd9Sstevel@tonic-gate 	int didhrs = 0;
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	if (tim >= 60) {
610*7c478bd9Sstevel@tonic-gate 		(void) printf("%3d:", tim/60);
611*7c478bd9Sstevel@tonic-gate 		didhrs++;
612*7c478bd9Sstevel@tonic-gate 	} else {
613*7c478bd9Sstevel@tonic-gate 		(void) printf("    ");
614*7c478bd9Sstevel@tonic-gate 	}
615*7c478bd9Sstevel@tonic-gate 	tim %= 60;
616*7c478bd9Sstevel@tonic-gate 	if (tim > 0 || didhrs) {
617*7c478bd9Sstevel@tonic-gate 		(void) printf(didhrs && tim < 10 ? "%02d" : "%2d", tim);
618*7c478bd9Sstevel@tonic-gate 	} else {
619*7c478bd9Sstevel@tonic-gate 		(void) printf("  ");
620*7c478bd9Sstevel@tonic-gate 	}
621*7c478bd9Sstevel@tonic-gate 	(void) printf("%s", tail);
622*7c478bd9Sstevel@tonic-gate }
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
625*7c478bd9Sstevel@tonic-gate /*
626*7c478bd9Sstevel@tonic-gate  * for debugging
627*7c478bd9Sstevel@tonic-gate  */
628*7c478bd9Sstevel@tonic-gate int
printit(int i)629*7c478bd9Sstevel@tonic-gate printit(int i)
630*7c478bd9Sstevel@tonic-gate {
631*7c478bd9Sstevel@tonic-gate 	int j, v;
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	(void) printf("%12.12s: ", entry[i].machine);
634*7c478bd9Sstevel@tonic-gate 	if (entry[i].cnt) {
635*7c478bd9Sstevel@tonic-gate 		putline_3(entry[i].machine, &entry[i].users.utmp_array_val[0]);
636*7c478bd9Sstevel@tonic-gate 		for (j = 1; j < entry[i].cnt; j++) {
637*7c478bd9Sstevel@tonic-gate 			(void) printf("\t");
638*7c478bd9Sstevel@tonic-gate 			putline_3(entry[i].machine,
639*7c478bd9Sstevel@tonic-gate 				&entry[i].users.utmp_array_val[j]);
640*7c478bd9Sstevel@tonic-gate 		}
641*7c478bd9Sstevel@tonic-gate 	} else
642*7c478bd9Sstevel@tonic-gate 		(void) printf("\n");
643*7c478bd9Sstevel@tonic-gate }
644*7c478bd9Sstevel@tonic-gate #endif
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate static void
usage(void)647*7c478bd9Sstevel@tonic-gate usage(void)
648*7c478bd9Sstevel@tonic-gate {
649*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage: rusers [-ahilu] [host ...]\n");
650*7c478bd9Sstevel@tonic-gate 	free(entry);
651*7c478bd9Sstevel@tonic-gate 	exit(1);
652*7c478bd9Sstevel@tonic-gate }
653