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 19 char 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 25 static char sccsid[] = "@(#)ruptime.c 5.6 (Berkeley) 05/11/89"; 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 35 int nhosts; 36 struct hs { 37 struct whod *hs_wd; 38 int hs_nusers; 39 } hs[NHOSTS]; 40 struct whod awhod; 41 42 #define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we)) 43 #define down(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60) 44 45 time_t now; 46 int rflg = 1; 47 int hscmp(), ucmp(), lcmp(), tcmp(); 48 49 main(argc, argv) 50 int argc; 51 char **argv; 52 { 53 extern char *optarg; 54 extern int optind; 55 register struct hs *hsp = hs; 56 register struct whod *wd; 57 register struct whoent *we; 58 register DIR *dirp; 59 struct direct *dp; 60 int aflg, cc, ch, f, i, maxloadav; 61 char buf[sizeof(struct whod)]; 62 int (*cmp)() = hscmp; 63 time_t time(); 64 char *interval(), *malloc(); 65 66 aflg = 0; 67 maxloadav = -1; 68 while ((ch = getopt(argc, argv, "alrut")) != EOF) 69 switch((char)ch) { 70 case 'a': 71 aflg = 1; 72 break; 73 case 'l': 74 cmp = lcmp; 75 break; 76 case 'r': 77 rflg = -1; 78 break; 79 case 't': 80 cmp = tcmp; 81 break; 82 case 'u': 83 cmp = ucmp; 84 break; 85 default: 86 fprintf(stderr, "usage: ruptime [-alrut]\n"); 87 exit(1); 88 } 89 90 if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) { 91 perror(_PATH_RWHODIR); 92 exit(1); 93 } 94 while (dp = readdir(dirp)) { 95 if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) 96 continue; 97 if (nhosts == NHOSTS) { 98 fprintf(stderr, "ruptime: too many hosts\n"); 99 exit(1); 100 } 101 f = open(dp->d_name, O_RDONLY, 0); 102 if (f > 0) { 103 cc = read(f, buf, sizeof(struct whod)); 104 if (cc >= WHDRSIZE) { 105 /* NOSTRICT */ 106 hsp->hs_wd = (struct whod *)malloc(WHDRSIZE); 107 wd = (struct whod *)buf; 108 bcopy(wd, hsp->hs_wd, 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++; hsp++; 118 } 119 (void)close(f); 120 } 121 } 122 if (!nhosts) { 123 printf("ruptime: no hosts!?!\n"); 124 exit(1); 125 } 126 qsort((char *)hs, nhosts, sizeof (hs[0]), cmp); 127 (void)time(&now); 128 for (i = 0; i < nhosts; i++) { 129 hsp = &hs[i]; 130 if (down(hsp)) { 131 printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname, 132 interval(now - hsp->hs_wd->wd_recvtime, "down")); 133 continue; 134 } 135 printf("%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n", 136 hsp->hs_wd->wd_hostname, 137 interval(hsp->hs_wd->wd_sendtime - 138 hsp->hs_wd->wd_boottime, " up"), 139 hsp->hs_nusers, 140 hsp->hs_nusers == 1 ? ", " : "s,", 141 maxloadav >= 1000 ? 5 : 4, 142 hsp->hs_wd->wd_loadav[0] / 100.0, 143 maxloadav >= 1000 ? 5 : 4, 144 hsp->hs_wd->wd_loadav[1] / 100.0, 145 maxloadav >= 1000 ? 5 : 4, 146 hsp->hs_wd->wd_loadav[2] / 100.0); 147 cfree(hsp->hs_wd); 148 } 149 exit(0); 150 } 151 152 char * 153 interval(tval, updown) 154 time_t tval; 155 char *updown; 156 { 157 static char resbuf[32]; 158 int days, hours, minutes; 159 160 if (tval < 0 || tval > 365*24*60*60) { 161 (void)sprintf(resbuf, " %s ??:??", updown); 162 return(resbuf); 163 } 164 minutes = (tval + 59) / 60; /* round to minutes */ 165 hours = minutes / 60; minutes %= 60; 166 days = hours / 24; hours %= 24; 167 if (days) 168 (void)sprintf(resbuf, "%s %2d+%02d:%02d", 169 updown, days, hours, minutes); 170 else 171 (void)sprintf(resbuf, "%s %2d:%02d", 172 updown, hours, minutes); 173 return(resbuf); 174 } 175 176 hscmp(h1, h2) 177 struct hs *h1, *h2; 178 { 179 return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname)); 180 } 181 182 /* 183 * Compare according to load average. 184 */ 185 lcmp(h1, h2) 186 struct hs *h1, *h2; 187 { 188 if (down(h1)) 189 if (down(h2)) 190 return(tcmp(h1, h2)); 191 else 192 return(rflg); 193 else if (down(h2)) 194 return(-rflg); 195 else 196 return(rflg * 197 (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0])); 198 } 199 200 /* 201 * Compare according to number of users. 202 */ 203 ucmp(h1, h2) 204 struct hs *h1, *h2; 205 { 206 if (down(h1)) 207 if (down(h2)) 208 return(tcmp(h1, h2)); 209 else 210 return(rflg); 211 else if (down(h2)) 212 return(-rflg); 213 else 214 return(rflg * (h2->hs_nusers - h1->hs_nusers)); 215 } 216 217 /* 218 * Compare according to uptime. 219 */ 220 tcmp(h1, h2) 221 struct hs *h1, *h2; 222 { 223 return(rflg * ( 224 (down(h2) ? h2->hs_wd->wd_recvtime - now 225 : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime) 226 - 227 (down(h1) ? h1->hs_wd->wd_recvtime - now 228 : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime) 229 )); 230 } 231