1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1983, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)ruptime.c 8.1 (Berkeley) 06/06/93"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/dir.h> 20 #include <sys/file.h> 21 #include <sys/errno.h> 22 #include <protocols/rwhod.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 size_t nhosts, hspace = 20; 28 struct hs { 29 struct whod *hs_wd; 30 int hs_nusers; 31 } *hs; 32 struct whod awhod; 33 34 #define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60) 35 #define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we)) 36 37 time_t now; 38 int rflg = 1; 39 int hscmp(), ucmp(), lcmp(), tcmp(); 40 41 main(argc, argv) 42 int argc; 43 char **argv; 44 { 45 extern char *optarg; 46 extern int optind; 47 register struct hs *hsp; 48 register struct whod *wd; 49 register struct whoent *we; 50 register DIR *dirp; 51 struct direct *dp; 52 int aflg, cc, ch, f, i, maxloadav; 53 char buf[sizeof(struct whod)]; 54 int (*cmp)() = hscmp; 55 time_t time(); 56 char *interval(); 57 58 aflg = 0; 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: 77 (void)fprintf(stderr, "usage: ruptime [-alrut]\n"); 78 exit(1); 79 } 80 81 if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) { 82 (void)fprintf(stderr, "ruptime: %s: %s.\n", 83 _PATH_RWHODIR, strerror(errno)); 84 exit(1); 85 } 86 morehosts(); 87 hsp = hs; 88 maxloadav = -1; 89 while (dp = readdir(dirp)) { 90 if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) 91 continue; 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; 96 } 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; 104 } 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++; 119 } 120 if (!nhosts) { 121 (void)printf("ruptime: no hosts in %s.\n", _PATH_RWHODIR); 122 exit(1); 123 } 124 qsort((char *)hs, nhosts, sizeof (hs[0]), cmp); 125 (void)time(&now); 126 for (i = 0; i < nhosts; i++) { 127 hsp = &hs[i]; 128 if (ISDOWN(hsp)) { 129 (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname, 130 interval(now - hsp->hs_wd->wd_recvtime, "down")); 131 continue; 132 } 133 (void)printf( 134 "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n", 135 hsp->hs_wd->wd_hostname, 136 interval((time_t)hsp->hs_wd->wd_sendtime - 137 (time_t)hsp->hs_wd->wd_boottime, " up"), 138 hsp->hs_nusers, 139 hsp->hs_nusers == 1 ? ", " : "s,", 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); 146 free((void *)hsp->hs_wd); 147 } 148 exit(0); 149 } 150 151 char * 152 interval(tval, updown) 153 time_t tval; 154 char *updown; 155 { 156 static char resbuf[32]; 157 int days, hours, minutes; 158 159 if (tval < 0 || tval > 365*24*60*60) { 160 (void)sprintf(resbuf, " %s ??:??", updown); 161 return(resbuf); 162 } 163 minutes = (tval + 59) / 60; /* round to minutes */ 164 hours = minutes / 60; minutes %= 60; 165 days = hours / 24; hours %= 24; 166 if (days) 167 (void)sprintf(resbuf, "%s %2d+%02d:%02d", 168 updown, days, hours, minutes); 169 else 170 (void)sprintf(resbuf, "%s %2d:%02d", 171 updown, hours, minutes); 172 return(resbuf); 173 } 174 175 /* alphabetical comparison */ 176 hscmp(a1, a2) 177 void *a1, *a2; 178 { 179 struct hs *h1 = a1, *h2 = a2; 180 181 return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname)); 182 } 183 184 /* load average comparison */ 185 lcmp(a1, a2) 186 void *a1, *a2; 187 { 188 register struct hs *h1 = a1, *h2 = a2; 189 190 if (ISDOWN(h1)) 191 if (ISDOWN(h2)) 192 return(tcmp(a1, a2)); 193 else 194 return(rflg); 195 else if (ISDOWN(h2)) 196 return(-rflg); 197 else 198 return(rflg * 199 (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0])); 200 } 201 202 /* number of users comparison */ 203 ucmp(a1, a2) 204 void *a1, *a2; 205 { 206 register struct hs *h1 = a1, *h2 = a2; 207 208 if (ISDOWN(h1)) 209 if (ISDOWN(h2)) 210 return(tcmp(a1, a2)); 211 else 212 return(rflg); 213 else if (ISDOWN(h2)) 214 return(-rflg); 215 else 216 return(rflg * (h2->hs_nusers - h1->hs_nusers)); 217 } 218 219 /* uptime comparison */ 220 tcmp(a1, a2) 221 void *a1, *a2; 222 { 223 register struct hs *h1 = a1, *h2 = a2; 224 225 return(rflg * ( 226 (ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now 227 : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime) 228 - 229 (ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now 230 : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime) 231 )); 232 } 233 234 morehosts() 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 } 242