new version distinguishing between rtentries and ortentries
[unix-history] / usr / src / usr.bin / ruptime / ruptime.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18#ifndef lint
19char copyright[] =
20"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
21 All rights reserved.\n";
22#endif /* not lint */
23
24#ifndef lint
25static char sccsid[] = "@(#)ruptime.c 5.5 (Berkeley) %G%";
26#endif /* not lint */
27
28#include <sys/param.h>
29#include <sys/dir.h>
30#include <sys/file.h>
31#include <protocols/rwhod.h>
32#include <stdio.h>
33
34#define NHOSTS 100
35int nhosts;
36struct hs {
37 struct whod *hs_wd;
38 int hs_nusers;
39} hs[NHOSTS];
40struct whod awhod;
41
42#define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we))
43#define RWHODIR "/usr/spool/rwho"
44#define down(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60)
45
46time_t now;
47int rflg = 1;
48int hscmp(), ucmp(), lcmp(), tcmp();
49
50main(argc, argv)
51 int argc;
52 char **argv;
53{
54 extern char *optarg;
55 extern int optind;
56 register struct hs *hsp = hs;
57 register struct whod *wd;
58 register struct whoent *we;
59 register DIR *dirp;
60 struct direct *dp;
61 int aflg, cc, ch, f, i, maxloadav;
62 char buf[sizeof(struct whod)];
63 int (*cmp)() = hscmp;
64 time_t time();
65 char *interval(), *malloc();
66
67 aflg = 0;
68 maxloadav = -1;
69 while ((ch = getopt(argc, argv, "alrut")) != EOF)
70 switch((char)ch) {
71 case 'a':
72 aflg = 1;
73 break;
74 case 'l':
75 cmp = lcmp;
76 break;
77 case 'r':
78 rflg = -1;
79 break;
80 case 't':
81 cmp = tcmp;
82 break;
83 case 'u':
84 cmp = ucmp;
85 break;
86 default:
87 fprintf(stderr, "usage: ruptime [-alrut]\n");
88 exit(1);
89 }
90
91 if (chdir(RWHODIR) || (dirp = opendir(".")) == NULL) {
92 perror(RWHODIR);
93 exit(1);
94 }
95 while (dp = readdir(dirp)) {
96 if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
97 continue;
98 if (nhosts == NHOSTS) {
99 fprintf(stderr, "ruptime: too many hosts\n");
100 exit(1);
101 }
102 f = open(dp->d_name, O_RDONLY, 0);
103 if (f > 0) {
104 cc = read(f, buf, sizeof(struct whod));
105 if (cc >= WHDRSIZE) {
106 /* NOSTRICT */
107 hsp->hs_wd = (struct whod *)malloc(WHDRSIZE);
108 wd = (struct whod *)buf;
109 bcopy(wd, hsp->hs_wd, WHDRSIZE);
110 hsp->hs_nusers = 0;
111 for (i = 0; i < 2; i++)
112 if (wd->wd_loadav[i] > maxloadav)
113 maxloadav = wd->wd_loadav[i];
114 we = (struct whoent *)(buf+cc);
115 while (--we >= wd->wd_we)
116 if (aflg || we->we_idle < 3600)
117 hsp->hs_nusers++;
118 nhosts++; hsp++;
119 }
120 (void)close(f);
121 }
122 }
123 if (!nhosts) {
124 printf("ruptime: no hosts!?!\n");
125 exit(1);
126 }
127 qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
128 (void)time(&now);
129 for (i = 0; i < nhosts; i++) {
130 hsp = &hs[i];
131 if (down(hsp)) {
132 printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
133 interval(now - hsp->hs_wd->wd_recvtime, "down"));
134 continue;
135 }
136 printf("%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n",
137 hsp->hs_wd->wd_hostname,
138 interval(hsp->hs_wd->wd_sendtime -
139 hsp->hs_wd->wd_boottime, " up"),
140 hsp->hs_nusers,
141 hsp->hs_nusers == 1 ? ", " : "s,",
142 maxloadav >= 1000 ? 5 : 4,
143 hsp->hs_wd->wd_loadav[0] / 100.0,
144 maxloadav >= 1000 ? 5 : 4,
145 hsp->hs_wd->wd_loadav[1] / 100.0,
146 maxloadav >= 1000 ? 5 : 4,
147 hsp->hs_wd->wd_loadav[2] / 100.0);
148 cfree(hsp->hs_wd);
149 }
150 exit(0);
151}
152
153char *
154interval(tval, updown)
155 time_t tval;
156 char *updown;
157{
158 static char resbuf[32];
159 int days, hours, minutes;
160
161 if (tval < 0 || tval > 365*24*60*60) {
162 (void)sprintf(resbuf, " %s ??:??", updown);
163 return(resbuf);
164 }
165 minutes = (tval + 59) / 60; /* round to minutes */
166 hours = minutes / 60; minutes %= 60;
167 days = hours / 24; hours %= 24;
168 if (days)
169 (void)sprintf(resbuf, "%s %2d+%02d:%02d",
170 updown, days, hours, minutes);
171 else
172 (void)sprintf(resbuf, "%s %2d:%02d",
173 updown, hours, minutes);
174 return(resbuf);
175}
176
177hscmp(h1, h2)
178 struct hs *h1, *h2;
179{
180 return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
181}
182
183/*
184 * Compare according to load average.
185 */
186lcmp(h1, h2)
187 struct hs *h1, *h2;
188{
189 if (down(h1))
190 if (down(h2))
191 return(tcmp(h1, h2));
192 else
193 return(rflg);
194 else if (down(h2))
195 return(-rflg);
196 else
197 return(rflg *
198 (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
199}
200
201/*
202 * Compare according to number of users.
203 */
204ucmp(h1, h2)
205 struct hs *h1, *h2;
206{
207 if (down(h1))
208 if (down(h2))
209 return(tcmp(h1, h2));
210 else
211 return(rflg);
212 else if (down(h2))
213 return(-rflg);
214 else
215 return(rflg * (h2->hs_nusers - h1->hs_nusers));
216}
217
218/*
219 * Compare according to uptime.
220 */
221tcmp(h1, h2)
222 struct hs *h1, *h2;
223{
224 return(rflg * (
225 (down(h2) ? h2->hs_wd->wd_recvtime - now
226 : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
227 -
228 (down(h1) ? h1->hs_wd->wd_recvtime - now
229 : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
230 ));
231}