Home | History | Annotate | Line # | Download | only in ruptime
ruptime.c revision 1.9
      1 /*	$NetBSD: ruptime.c,v 1.9 2000/12/31 17:35:20 ad Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1983, 1993, 1994
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 #ifndef lint
     38 __COPYRIGHT("@(#) Copyright (c) 1983, 1993, 1994\n\
     39 	The Regents of the University of California.  All rights reserved.\n");
     40 #endif /* not lint */
     41 
     42 #ifndef lint
     43 /*static char sccsid[] = "from: @(#)ruptime.c	8.2 (Berkeley) 4/5/94";*/
     44 __RCSID("$NetBSD: ruptime.c,v 1.9 2000/12/31 17:35:20 ad Exp $");
     45 #endif /* not lint */
     46 
     47 #include <sys/param.h>
     48 
     49 #include <protocols/rwhod.h>
     50 
     51 #include <dirent.h>
     52 #include <err.h>
     53 #include <errno.h>
     54 #include <fcntl.h>
     55 #include <stdio.h>
     56 #include <stdlib.h>
     57 #include <string.h>
     58 #include <time.h>
     59 #include <tzfile.h>
     60 #include <unistd.h>
     61 
     62 struct hs {
     63 	struct	whod *hs_wd;
     64 	int	hs_nusers;
     65 } *hs;
     66 struct	whod awhod;
     67 
     68 #define	ISDOWN(h)		(now - (h)->hs_wd->wd_recvtime > 11 * 60)
     69 #define	WHDRSIZE	(sizeof (awhod) - sizeof (awhod.wd_we))
     70 
     71 size_t nhosts;
     72 time_t now;
     73 int rflg = 1;
     74 
     75 int	 hscmp __P((const void *, const void *));
     76 char	*interval __P((time_t, char *));
     77 int	 lcmp __P((const void *, const void *));
     78 int	 main __P((int, char **));
     79 void	 morehosts __P((void));
     80 int	 tcmp __P((const void *, const void *));
     81 int	 ucmp __P((const void *, const void *));
     82 void	 usage __P((void));
     83 
     84 int
     85 main(argc, argv)
     86 	int argc;
     87 	char **argv;
     88 {
     89 	struct dirent *dp;
     90 	struct hs *hsp;
     91 	struct whod *wd;
     92 	struct whoent *we;
     93 	DIR *dirp;
     94 	size_t hspace;
     95 	int aflg, cc, ch, fd, i, maxloadav;
     96 	char buf[sizeof(struct whod)];
     97 	int (*cmp) __P((const void *, const void *));
     98 
     99 	hsp = NULL;
    100 	aflg = 0;
    101 	cmp = hscmp;
    102 	while ((ch = getopt(argc, argv, "alrut")) != -1)
    103 		switch (ch) {
    104 		case 'a':
    105 			aflg = 1;
    106 			break;
    107 		case 'l':
    108 			cmp = lcmp;
    109 			break;
    110 		case 'r':
    111 			rflg = -1;
    112 			break;
    113 		case 't':
    114 			cmp = tcmp;
    115 			break;
    116 		case 'u':
    117 			cmp = ucmp;
    118 			break;
    119 		default:
    120 			usage();
    121 		}
    122 	argc -= optind;
    123 	argv += optind;
    124 
    125 	if (argc != 0)
    126 		usage();
    127 
    128 	if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
    129 		err(1, "%s", _PATH_RWHODIR);
    130 
    131 	maxloadav = -1;
    132 	for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) {
    133 		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
    134 			continue;
    135 		if ((fd = open(dp->d_name, O_RDONLY, 0)) < 0) {
    136 			warn("%s", dp->d_name);
    137 			continue;
    138 		}
    139 		cc = read(fd, buf, sizeof(struct whod));
    140 		(void)close(fd);
    141 
    142 		if (cc < WHDRSIZE)
    143 			continue;
    144 		if (nhosts == hspace) {
    145 			if ((hs =
    146 			    realloc(hs, (hspace += 40) * sizeof(*hs))) == NULL)
    147 				err(1, "realloc");
    148 			hsp = hs + nhosts;
    149 		}
    150 
    151 		if ((hsp->hs_wd = malloc((size_t)WHDRSIZE)) == NULL)
    152 			err(1, "malloc");
    153 		memmove(hsp->hs_wd, buf, (size_t)WHDRSIZE);
    154 
    155 		for (wd = (struct whod *)buf, i = 0; i < 2; ++i)
    156 			if (wd->wd_loadav[i] > maxloadav)
    157 				maxloadav = wd->wd_loadav[i];
    158 
    159 		for (hsp->hs_nusers = 0,
    160 		    we = (struct whoent *)(buf + cc); --we >= wd->wd_we;)
    161 			if (aflg || we->we_idle < 3600)
    162 				++hsp->hs_nusers;
    163 		++hsp;
    164 		++nhosts;
    165 	}
    166 	if (nhosts == 0)
    167 		errx(0, "no hosts in %s.", _PATH_RWHODIR);
    168 
    169 	(void)time(&now);
    170 	qsort(hs, nhosts, sizeof (hs[0]), cmp);
    171 	for (i = 0; i < nhosts; i++) {
    172 		hsp = &hs[i];
    173 		if (ISDOWN(hsp)) {
    174 			(void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
    175 			    interval(now - hsp->hs_wd->wd_recvtime, "down"));
    176 			continue;
    177 		}
    178 		(void)printf(
    179 		    "%-12.12s%s,  %4d user%s  load %*.2f, %*.2f, %*.2f\n",
    180 		    hsp->hs_wd->wd_hostname,
    181 		    interval((time_t)hsp->hs_wd->wd_sendtime -
    182 			(time_t)hsp->hs_wd->wd_boottime, "  up"),
    183 		    hsp->hs_nusers,
    184 		    hsp->hs_nusers == 1 ? ", " : "s,",
    185 		    maxloadav >= 1000 ? 5 : 4,
    186 			hsp->hs_wd->wd_loadav[0] / 100.0,
    187 		    maxloadav >= 1000 ? 5 : 4,
    188 		        hsp->hs_wd->wd_loadav[1] / 100.0,
    189 		    maxloadav >= 1000 ? 5 : 4,
    190 		        hsp->hs_wd->wd_loadav[2] / 100.0);
    191 	}
    192 	exit(0);
    193 }
    194 
    195 char *
    196 interval(tval, updown)
    197 	time_t tval;
    198 	char *updown;
    199 {
    200 	static char resbuf[32];
    201 	int days, hours, minutes;
    202 
    203 	if (tval < 0) {
    204 		(void)snprintf(resbuf, sizeof(resbuf), "   %s ??:??", updown);
    205 		return (resbuf);
    206 	}
    207 						/* round to minutes. */
    208 	minutes = (tval + (SECSPERMIN - 1)) / SECSPERMIN;
    209 	hours = minutes / MINSPERHOUR;
    210 	minutes %= MINSPERHOUR;
    211 	days = hours / HOURSPERDAY;
    212 	hours %= HOURSPERDAY;
    213 	if (days)
    214 		(void)snprintf(resbuf, sizeof(resbuf),
    215 		    "%s%4d+%02d:%02d", updown, days, hours, minutes);
    216 	else
    217 		(void)snprintf(resbuf, sizeof(resbuf),
    218 		    "%s     %2d:%02d", updown, hours, minutes);
    219 	return (resbuf);
    220 }
    221 
    222 #define	HS(a)	((struct hs *)(a))
    223 
    224 /* Alphabetical comparison. */
    225 int
    226 hscmp(a1, a2)
    227 	const void *a1, *a2;
    228 {
    229 	return (rflg *
    230 	    strcmp(HS(a1)->hs_wd->wd_hostname, HS(a2)->hs_wd->wd_hostname));
    231 }
    232 
    233 /* Load average comparison. */
    234 int
    235 lcmp(a1, a2)
    236 	const void *a1, *a2;
    237 {
    238 	if (ISDOWN(HS(a1))) {
    239 		if (ISDOWN(HS(a2)))
    240 			return (tcmp(a1, a2));
    241 		else
    242 			return (rflg);
    243 	} else if (ISDOWN(HS(a2))) {
    244 		return (-rflg);
    245 	} else
    246 		return (rflg *
    247 		   (HS(a2)->hs_wd->wd_loadav[0] - HS(a1)->hs_wd->wd_loadav[0]));
    248 }
    249 
    250 /* Number of users comparison. */
    251 int
    252 ucmp(a1, a2)
    253 	const void *a1, *a2;
    254 {
    255 	if (ISDOWN(HS(a1))) {
    256 		if (ISDOWN(HS(a2)))
    257 			return (tcmp(a1, a2));
    258 		else
    259 			return (rflg);
    260 	} else if (ISDOWN(HS(a2))) {
    261 		return (-rflg);
    262 	} else
    263 		return (rflg * (HS(a2)->hs_nusers - HS(a1)->hs_nusers));
    264 }
    265 
    266 /* Uptime comparison. */
    267 int
    268 tcmp(a1, a2)
    269 	const void *a1, *a2;
    270 {
    271 	return (rflg * (
    272 		(ISDOWN(HS(a2)) ? HS(a2)->hs_wd->wd_recvtime - now
    273 		    : HS(a2)->hs_wd->wd_sendtime - HS(a2)->hs_wd->wd_boottime)
    274 		-
    275 		(ISDOWN(HS(a1)) ? HS(a1)->hs_wd->wd_recvtime - now
    276 		    : HS(a1)->hs_wd->wd_sendtime - HS(a1)->hs_wd->wd_boottime)
    277 	));
    278 }
    279 
    280 void
    281 usage()
    282 {
    283 	(void)fprintf(stderr, "usage: ruptime [-alrut]\n");
    284 	exit(1);
    285 }
    286