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, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 char copyright[] = 36 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 37 All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 /*static char sccsid[] = "from: @(#)ruptime.c 5.8 (Berkeley) 7/21/90";*/ 42 static char rcsid[] = "$Id: ruptime.c,v 1.4 1994/04/05 02:18:43 cgd Exp $"; 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/file.h> 47 #include <dirent.h> 48 #include <protocols/rwhod.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <errno.h> 53 54 size_t nhosts, hspace = 20; 55 struct hs { 56 struct whod *hs_wd; 57 int hs_nusers; 58 } *hs; 59 struct whod awhod; 60 61 #define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60) 62 #define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we)) 63 64 time_t now; 65 int rflg = 1; 66 int hscmp(), ucmp(), lcmp(), tcmp(); 67 68 main(argc, argv) 69 int argc; 70 char **argv; 71 { 72 extern char *optarg; 73 extern int optind; 74 register struct hs *hsp; 75 register struct whod *wd; 76 register struct whoent *we; 77 register DIR *dirp; 78 struct dirent *dp; 79 int aflg, cc, ch, f, i, maxloadav; 80 char buf[sizeof(struct whod)]; 81 int (*cmp)() = hscmp; 82 time_t time(); 83 char *interval(); 84 85 aflg = 0; 86 while ((ch = getopt(argc, argv, "alrut")) != EOF) 87 switch((char)ch) { 88 case 'a': 89 aflg = 1; 90 break; 91 case 'l': 92 cmp = lcmp; 93 break; 94 case 'r': 95 rflg = -1; 96 break; 97 case 't': 98 cmp = tcmp; 99 break; 100 case 'u': 101 cmp = ucmp; 102 break; 103 default: 104 (void)fprintf(stderr, "usage: ruptime [-alrut]\n"); 105 exit(1); 106 } 107 108 if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) { 109 (void)fprintf(stderr, "ruptime: %s: %s.\n", 110 _PATH_RWHODIR, strerror(errno)); 111 exit(1); 112 } 113 morehosts(); 114 hsp = hs; 115 maxloadav = -1; 116 while (dp = readdir(dirp)) { 117 if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) 118 continue; 119 if ((f = open(dp->d_name, O_RDONLY, 0)) < 0) { 120 (void)fprintf(stderr, "ruptime: %s: %s\n", 121 dp->d_name, strerror(errno)); 122 continue; 123 } 124 cc = read(f, buf, sizeof(struct whod)); 125 (void)close(f); 126 if (cc < WHDRSIZE) 127 continue; 128 if (nhosts == hspace) { 129 morehosts(); 130 hsp = hs + nhosts; 131 } 132 /* NOSTRICT */ 133 hsp->hs_wd = malloc((size_t)WHDRSIZE); 134 wd = (struct whod *)buf; 135 bcopy((char *)wd, (char *)hsp->hs_wd, (size_t)WHDRSIZE); 136 hsp->hs_nusers = 0; 137 for (i = 0; i < 2; i++) 138 if (wd->wd_loadav[i] > maxloadav) 139 maxloadav = wd->wd_loadav[i]; 140 we = (struct whoent *)(buf+cc); 141 while (--we >= wd->wd_we) 142 if (aflg || we->we_idle < 3600) 143 hsp->hs_nusers++; 144 nhosts++; 145 hsp++; 146 } 147 if (!nhosts) { 148 (void)printf("ruptime: no hosts in %s.\n", _PATH_RWHODIR); 149 exit(1); 150 } 151 (void)time(&now); 152 qsort((char *)hs, nhosts, sizeof (hs[0]), cmp); 153 for (i = 0; i < nhosts; i++) { 154 hsp = &hs[i]; 155 if (ISDOWN(hsp)) { 156 (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname, 157 interval(now - hsp->hs_wd->wd_recvtime, "down")); 158 continue; 159 } 160 (void)printf( 161 "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n", 162 hsp->hs_wd->wd_hostname, 163 interval((time_t)hsp->hs_wd->wd_sendtime - 164 (time_t)hsp->hs_wd->wd_boottime, " up"), 165 hsp->hs_nusers, 166 hsp->hs_nusers == 1 ? ", " : "s,", 167 maxloadav >= 1000 ? 5 : 4, 168 hsp->hs_wd->wd_loadav[0] / 100.0, 169 maxloadav >= 1000 ? 5 : 4, 170 hsp->hs_wd->wd_loadav[1] / 100.0, 171 maxloadav >= 1000 ? 5 : 4, 172 hsp->hs_wd->wd_loadav[2] / 100.0); 173 free((void *)hsp->hs_wd); 174 } 175 exit(0); 176 } 177 178 char * 179 interval(tval, updown) 180 time_t tval; 181 char *updown; 182 { 183 static char resbuf[32]; 184 int days, hours, minutes; 185 186 if (tval < 0 || tval > 365*24*60*60) { 187 (void)sprintf(resbuf, " %s ??:??", updown); 188 return(resbuf); 189 } 190 minutes = (tval + 59) / 60; /* round to minutes */ 191 hours = minutes / 60; minutes %= 60; 192 days = hours / 24; hours %= 24; 193 if (days) 194 (void)sprintf(resbuf, "%s %2d+%02d:%02d", 195 updown, days, hours, minutes); 196 else 197 (void)sprintf(resbuf, "%s %2d:%02d", 198 updown, hours, minutes); 199 return(resbuf); 200 } 201 202 /* alphabetical comparison */ 203 hscmp(a1, a2) 204 void *a1, *a2; 205 { 206 struct hs *h1 = a1, *h2 = a2; 207 208 return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname)); 209 } 210 211 /* load average comparison */ 212 lcmp(a1, a2) 213 void *a1, *a2; 214 { 215 register struct hs *h1 = a1, *h2 = a2; 216 217 if (ISDOWN(h1)) 218 if (ISDOWN(h2)) 219 return(tcmp(a1, a2)); 220 else 221 return(rflg); 222 else if (ISDOWN(h2)) 223 return(-rflg); 224 else 225 return(rflg * 226 (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0])); 227 } 228 229 /* number of users comparison */ 230 ucmp(a1, a2) 231 void *a1, *a2; 232 { 233 register struct hs *h1 = a1, *h2 = a2; 234 235 if (ISDOWN(h1)) 236 if (ISDOWN(h2)) 237 return(tcmp(a1, a2)); 238 else 239 return(rflg); 240 else if (ISDOWN(h2)) 241 return(-rflg); 242 else 243 return(rflg * (h2->hs_nusers - h1->hs_nusers)); 244 } 245 246 /* uptime comparison */ 247 tcmp(a1, a2) 248 void *a1, *a2; 249 { 250 register struct hs *h1 = a1, *h2 = a2; 251 252 return(rflg * ( 253 (ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now 254 : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime) 255 - 256 (ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now 257 : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime) 258 )); 259 } 260 261 morehosts() 262 { 263 hs = realloc((char *)hs, (hspace *= 2) * sizeof(*hs)); 264 if (hs == NULL) { 265 (void)fprintf(stderr, "ruptime: %s.\n", strerror(ENOMEM)); 266 exit(1); 267 } 268 } 269