static void ruptime(const char *host, int aflg, int (*cmp)(const void *, const void *)) { struct hs *hsp; struct whod *wd; struct whoent *we; struct dirent *dp; const char *hostname; int fd, i, maxloadav; size_t hspace; ssize_t cc; rewinddir(dirp); hsp = NULL; maxloadav = -1; (void)time(&now); for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) { if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0) continue; if ((fd = open(dp->d_name, O_RDONLY, 0)) < 0) { warn("%s", dp->d_name); continue; } if (nhosts == hspace) { if ((hs = realloc(hs, (hspace += 40) * sizeof(*hs))) == NULL) err(1, NULL); hsp = hs + nhosts; } wd = &hsp->hs_wd; cc = read(fd, wd, sizeof(*wd)); (void)close(fd); if (cc < (ssize_t)WHDRSIZE) continue; if (host != NULL) { hostname = wd->wd_hostname; if (strcasecmp(hostname, host) != 0) continue; } if (LEFTEARTH(wd->wd_recvtime)) continue; for (i = 0; i < 2; i++) if (wd->wd_loadav[i] > maxloadav) maxloadav = wd->wd_loadav[i]; for (hsp->hs_nusers = 0, we = &wd->wd_we[0]; (char *)(we + 1) <= (char *)wd + cc; we++) if (aflg || we->we_idle < 3600) ++hsp->hs_nusers; ++hsp; ++nhosts; } if (nhosts == 0) { if (host == NULL) errx(1, "no hosts in %s", _PATH_RWHODIR); else warnx("host %s not in %s", host, _PATH_RWHODIR); } qsort(hs, nhosts, sizeof(hs[0]), cmp); for (i = 0; i < (int)nhosts; i++) { hsp = &hs[i]; wd = &hsp->hs_wd; if (ISDOWN(hsp)) { (void)printf("%-25.25s%s\n", wd->wd_hostname, interval(now - hsp->hs_wd.wd_recvtime, "down")); continue; } (void)printf( "%-25.25s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n", wd->wd_hostname, interval((time_t)wd->wd_sendtime - (time_t)wd->wd_boottime, " up"), hsp->hs_nusers, hsp->hs_nusers == 1 ? ", " : "s,", maxloadav >= 1000 ? 5 : 4, wd->wd_loadav[0] / 100.0, maxloadav >= 1000 ? 5 : 4, wd->wd_loadav[1] / 100.0, maxloadav >= 1000 ? 5 : 4, wd->wd_loadav[2] / 100.0); } free(hs); hs = NULL; }
int main(int argc, char *argv[]) { struct dirent *dp; struct hs *hsp = NULL; struct whod *wd; struct whoent *we; DIR *dirp; size_t hspace; int aflg, ch, fd, maxloadav; char buf[sizeof(struct whod)]; int (*cmp)(const void *, const void *); u_int cc, i; aflg = 0; cmp = hscmp; while ((ch = getopt(argc, argv, "alrut")) != -1) switch (ch) { case 'a': aflg = 1; break; case 'l': cmp = lcmp; break; case 'r': rflg = -1; break; case 't': cmp = tcmp; break; case 'u': cmp = ucmp; break; default: usage(); } argc -= optind; argv += optind; if (argc != 0) usage(); if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) err(1, "%s", _PATH_RWHODIR); maxloadav = -1; for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) { if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) continue; if ((fd = open(dp->d_name, O_RDONLY, 0)) < 0) { warn("%s", dp->d_name); continue; } cc = read(fd, buf, sizeof(struct whod)); (void)close(fd); if (cc < WHDRSIZE) continue; if (LEFTEARTH(((struct whod *)buf)->wd_recvtime)) continue; if (nhosts == hspace) { hspace += 40; if ((hs = realloc(hs, hspace * sizeof(*hs))) == NULL) err(1, NULL); hsp = hs + nhosts; } if ((hsp->hs_wd = malloc((size_t)WHDRSIZE)) == NULL) err(1, NULL); memmove(hsp->hs_wd, buf, (size_t)WHDRSIZE); for (wd = (struct whod *)buf, i = 0; i < 2; ++i) if (wd->wd_loadav[i] > maxloadav) maxloadav = wd->wd_loadav[i]; for (hsp->hs_nusers = 0, we = (struct whoent *)(buf + cc); --we >= wd->wd_we;) if (aflg || we->we_idle < 3600) ++hsp->hs_nusers; ++hsp; ++nhosts; } if (nhosts == 0) errx(1, "no hosts in %s", _PATH_RWHODIR); (void)time(&now); qsort(hs, nhosts, sizeof(hs[0]), cmp); for (i = 0; i < nhosts; i++) { hsp = &hs[i]; if (ISDOWN(hsp)) { (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname, interval(now - hsp->hs_wd->wd_recvtime, "down")); continue; } (void)printf( "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n", hsp->hs_wd->wd_hostname, interval((time_t)hsp->hs_wd->wd_sendtime - (time_t)hsp->hs_wd->wd_boottime, " up"), hsp->hs_nusers, hsp->hs_nusers == 1 ? ", " : "s,", maxloadav >= 1000 ? 5 : 4, hsp->hs_wd->wd_loadav[0] / 100.0, maxloadav >= 1000 ? 5 : 4, hsp->hs_wd->wd_loadav[1] / 100.0, maxloadav >= 1000 ? 5 : 4, hsp->hs_wd->wd_loadav[2] / 100.0); } exit(0); }