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