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