integrate Steve Hayman's version; now POSIX 1003.2 D11.2 compliant
[unix-history] / usr / src / usr.bin / ruptime / ruptime.c
CommitLineData
22e155fc 1/*
e8dcae5f
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
6d936b27 5 * %sccs.include.redist.c%
22e155fc
DF
6 */
7
8#ifndef lint
9char copyright[] =
e8dcae5f 10"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
22e155fc 11 All rights reserved.\n";
e8dcae5f 12#endif /* not lint */
22e155fc 13
be0e2d23 14#ifndef lint
6e9687a6 15static char sccsid[] = "@(#)ruptime.c 5.8 (Berkeley) %G%";
e8dcae5f 16#endif /* not lint */
be0e2d23 17
ed0072ae 18#include <sys/param.h>
7123e2dc 19#include <sys/dir.h>
e8dcae5f 20#include <sys/file.h>
6e9687a6 21#include <sys/errno.h>
5a7285fa 22#include <protocols/rwhod.h>
e8dcae5f 23#include <stdio.h>
6e9687a6
KB
24#include <stdlib.h>
25#include <string.h>
be0e2d23 26
6e9687a6 27size_t nhosts, hspace = 20;
e8dcae5f 28struct hs {
be0e2d23
BJ
29 struct whod *hs_wd;
30 int hs_nusers;
6e9687a6 31} *hs;
be0e2d23 32struct whod awhod;
be0e2d23 33
6e9687a6 34#define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60)
be0e2d23
BJ
35#define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we))
36
6e9687a6
KB
37time_t now;
38int rflg = 1;
39int hscmp(), ucmp(), lcmp(), tcmp();
508c25be 40
be0e2d23
BJ
41main(argc, argv)
42 int argc;
43 char **argv;
44{
e8dcae5f
KB
45 extern char *optarg;
46 extern int optind;
6e9687a6 47 register struct hs *hsp;
be0e2d23
BJ
48 register struct whod *wd;
49 register struct whoent *we;
e8dcae5f
KB
50 register DIR *dirp;
51 struct direct *dp;
52 int aflg, cc, ch, f, i, maxloadav;
53 char buf[sizeof(struct whod)];
508c25be 54 int (*cmp)() = hscmp;
e8dcae5f 55 time_t time();
6e9687a6 56 char *interval();
e8dcae5f
KB
57
58 aflg = 0;
e8dcae5f
KB
59 while ((ch = getopt(argc, argv, "alrut")) != EOF)
60 switch((char)ch) {
61 case 'a':
62 aflg = 1;
63 break;
64 case 'l':
65 cmp = lcmp;
66 break;
67 case 'r':
68 rflg = -1;
69 break;
70 case 't':
71 cmp = tcmp;
72 break;
73 case 'u':
74 cmp = ucmp;
75 break;
76 default:
6e9687a6 77 (void)fprintf(stderr, "usage: ruptime [-alrut]\n");
e8dcae5f
KB
78 exit(1);
79 }
be0e2d23 80
435e8dff 81 if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) {
6e9687a6
KB
82 (void)fprintf(stderr, "ruptime: %s: %s.\n",
83 _PATH_RWHODIR, strerror(errno));
be0e2d23
BJ
84 exit(1);
85 }
6e9687a6
KB
86 morehosts();
87 hsp = hs;
88 maxloadav = -1;
b9484359 89 while (dp = readdir(dirp)) {
e8dcae5f 90 if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
be0e2d23 91 continue;
6e9687a6
KB
92 if ((f = open(dp->d_name, O_RDONLY, 0)) < 0) {
93 (void)fprintf(stderr, "ruptime: %s: %s\n",
94 dp->d_name, strerror(errno));
95 continue;
be0e2d23 96 }
6e9687a6
KB
97 cc = read(f, buf, sizeof(struct whod));
98 (void)close(f);
99 if (cc < WHDRSIZE)
100 continue;
101 if (nhosts == hspace) {
102 morehosts();
103 hsp = hs + nhosts;
be0e2d23 104 }
6e9687a6
KB
105 /* NOSTRICT */
106 hsp->hs_wd = malloc((size_t)WHDRSIZE);
107 wd = (struct whod *)buf;
108 bcopy((char *)wd, (char *)hsp->hs_wd, (size_t)WHDRSIZE);
109 hsp->hs_nusers = 0;
110 for (i = 0; i < 2; i++)
111 if (wd->wd_loadav[i] > maxloadav)
112 maxloadav = wd->wd_loadav[i];
113 we = (struct whoent *)(buf+cc);
114 while (--we >= wd->wd_we)
115 if (aflg || we->we_idle < 3600)
116 hsp->hs_nusers++;
117 nhosts++;
118 hsp++;
be0e2d23 119 }
e8dcae5f 120 if (!nhosts) {
6e9687a6 121 (void)printf("ruptime: no hosts in %s.\n", _PATH_RWHODIR);
be0e2d23
BJ
122 exit(1);
123 }
e8dcae5f
KB
124 qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
125 (void)time(&now);
be0e2d23
BJ
126 for (i = 0; i < nhosts; i++) {
127 hsp = &hs[i];
6e9687a6
KB
128 if (ISDOWN(hsp)) {
129 (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
be0e2d23
BJ
130 interval(now - hsp->hs_wd->wd_recvtime, "down"));
131 continue;
132 }
6e9687a6
KB
133 (void)printf(
134 "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n",
be0e2d23 135 hsp->hs_wd->wd_hostname,
6e9687a6
KB
136 interval((time_t)hsp->hs_wd->wd_sendtime -
137 (time_t)hsp->hs_wd->wd_boottime, " up"),
be0e2d23
BJ
138 hsp->hs_nusers,
139 hsp->hs_nusers == 1 ? ", " : "s,",
acf8f1b2
BJ
140 maxloadav >= 1000 ? 5 : 4,
141 hsp->hs_wd->wd_loadav[0] / 100.0,
142 maxloadav >= 1000 ? 5 : 4,
143 hsp->hs_wd->wd_loadav[1] / 100.0,
144 maxloadav >= 1000 ? 5 : 4,
145 hsp->hs_wd->wd_loadav[2] / 100.0);
6e9687a6 146 free((void *)hsp->hs_wd);
be0e2d23
BJ
147 }
148 exit(0);
149}
150
151char *
e8dcae5f
KB
152interval(tval, updown)
153 time_t tval;
be0e2d23
BJ
154 char *updown;
155{
156 static char resbuf[32];
157 int days, hours, minutes;
158
e8dcae5f
KB
159 if (tval < 0 || tval > 365*24*60*60) {
160 (void)sprintf(resbuf, " %s ??:??", updown);
161 return(resbuf);
be0e2d23 162 }
e8dcae5f 163 minutes = (tval + 59) / 60; /* round to minutes */
be0e2d23
BJ
164 hours = minutes / 60; minutes %= 60;
165 days = hours / 24; hours %= 24;
166 if (days)
e8dcae5f 167 (void)sprintf(resbuf, "%s %2d+%02d:%02d",
be0e2d23
BJ
168 updown, days, hours, minutes);
169 else
e8dcae5f 170 (void)sprintf(resbuf, "%s %2d:%02d",
be0e2d23 171 updown, hours, minutes);
e8dcae5f 172 return(resbuf);
be0e2d23
BJ
173}
174
6e9687a6
KB
175/* alphabetical comparison */
176hscmp(a1, a2)
177 void *a1, *a2;
be0e2d23 178{
6e9687a6
KB
179 struct hs *h1 = a1, *h2 = a2;
180
e8dcae5f 181 return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
be0e2d23 182}
508c25be 183
6e9687a6
KB
184/* load average comparison */
185lcmp(a1, a2)
186 void *a1, *a2;
508c25be 187{
6e9687a6
KB
188 register struct hs *h1 = a1, *h2 = a2;
189
190 if (ISDOWN(h1))
191 if (ISDOWN(h2))
192 return(tcmp(a1, a2));
508c25be 193 else
e8dcae5f 194 return(rflg);
6e9687a6 195 else if (ISDOWN(h2))
e8dcae5f 196 return(-rflg);
508c25be 197 else
e8dcae5f 198 return(rflg *
44bbb118 199 (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
508c25be
EC
200}
201
6e9687a6
KB
202/* number of users comparison */
203ucmp(a1, a2)
204 void *a1, *a2;
508c25be 205{
6e9687a6
KB
206 register struct hs *h1 = a1, *h2 = a2;
207
208 if (ISDOWN(h1))
209 if (ISDOWN(h2))
210 return(tcmp(a1, a2));
508c25be 211 else
e8dcae5f 212 return(rflg);
6e9687a6 213 else if (ISDOWN(h2))
e8dcae5f 214 return(-rflg);
508c25be 215 else
e8dcae5f 216 return(rflg * (h2->hs_nusers - h1->hs_nusers));
508c25be
EC
217}
218
6e9687a6
KB
219/* uptime comparison */
220tcmp(a1, a2)
221 void *a1, *a2;
508c25be 222{
6e9687a6
KB
223 register struct hs *h1 = a1, *h2 = a2;
224
e8dcae5f 225 return(rflg * (
6e9687a6 226 (ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now
de3b21e8 227 : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
508c25be 228 -
6e9687a6 229 (ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now
de3b21e8 230 : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
44bbb118 231 ));
508c25be 232}
6e9687a6
KB
233
234morehosts()
235{
236 hs = realloc((char *)hs, (hspace *= 2) * sizeof(*hs));
237 if (hs == NULL) {
238 (void)fprintf(stderr, "ruptime: %s.\n", strerror(ENOMEM));
239 exit(1);
240 }
241}