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.5 (Berkeley) 08/25/88"; 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 RWHODIR "/usr/spool/rwho" 44 #define down(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60) 45 46 time_t now; 47 int rflg = 1; 48 int hscmp(), ucmp(), lcmp(), tcmp(); 49 50 main(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 153 char * 154 interval(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 177 hscmp(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 */ 186 lcmp(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 */ 204 ucmp(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 */ 221 tcmp(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 } 232