11590Srgrimes/* 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3127978Scharnierstatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 361590Srgrimes#ifndef lint 3727978Scharnier#if 0 381590Srgrimesstatic char sccsid[] = "@(#)rwho.c 8.1 (Berkeley) 6/6/93"; 3927978Scharnier#endif 401590Srgrimes#endif /* not lint */ 411590Srgrimes 4299218Smarkm#include <sys/cdefs.h> 4399218Smarkm__FBSDID("$FreeBSD$"); 4499218Smarkm 451590Srgrimes#include <sys/param.h> 461590Srgrimes#include <sys/file.h> 4799218Smarkm 481590Srgrimes#include <protocols/rwhod.h> 4999218Smarkm 5018485Sbde#include <dirent.h> 5127978Scharnier#include <err.h> 5274593Sache#include <langinfo.h> 5320156Sache#include <locale.h> 541590Srgrimes#include <stdio.h> 5527978Scharnier#include <stdlib.h> 5620156Sache#include <string.h> 579992Sache#include <time.h> 5899218Smarkm#include <timeconv.h> 5927978Scharnier#include <unistd.h> 601590Srgrimes 611590SrgrimesDIR *dirp; 621590Srgrimes 631590Srgrimesstruct whod wd; 641590Srgrimes#define NUSERS 1000 651590Srgrimesstruct myutmp { 6620165Sache char myhost[sizeof(wd.wd_hostname)]; 671590Srgrimes int myidle; 681590Srgrimes struct outmp myutmp; 691590Srgrimes} myutmp[NUSERS]; 701590Srgrimesint nusers; 711590Srgrimes 7299218Smarkm#define WHDRSIZE (ssize_t)(sizeof (wd) - sizeof (wd.wd_we)) 738874Srgrimes/* 741590Srgrimes * this macro should be shared with ruptime. 751590Srgrimes */ 761590Srgrimes#define down(w,now) ((now) - (w)->wd_recvtime > 11 * 60) 771590Srgrimes 781590Srgrimestime_t now; 791590Srgrimesint aflg; 801590Srgrimes 8192921Simpstatic void usage(void); 8292921Simpint utmpcmp(const void *, const void *); 8327978Scharnier 8427978Scharnierint 8599218Smarkmmain(int argc, char *argv[]) 861590Srgrimes{ 871590Srgrimes int ch; 8818485Sbde struct dirent *dp; 8999218Smarkm int width; 9099218Smarkm ssize_t cc; 911590Srgrimes register struct whod *w = &wd; 921590Srgrimes register struct whoent *we; 931590Srgrimes register struct myutmp *mp; 941590Srgrimes int f, n, i; 9574593Sache int d_first; 961590Srgrimes 9711758Sache (void) setlocale(LC_TIME, ""); 9874593Sache d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 9911758Sache 10024360Simp while ((ch = getopt(argc, argv, "a")) != -1) 1011590Srgrimes switch((char)ch) { 1021590Srgrimes case 'a': 1031590Srgrimes aflg = 1; 1041590Srgrimes break; 1051590Srgrimes case '?': 1061590Srgrimes default: 10727978Scharnier usage(); 1081590Srgrimes } 10935659Ssteve argc -= optind; 11035659Ssteve argv += optind; 11135659Ssteve 11235659Ssteve if (argc != 0) 11335659Ssteve usage(); 11435659Ssteve 11527978Scharnier if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) 11627978Scharnier err(1, "%s", _PATH_RWHODIR); 1171590Srgrimes mp = myutmp; 1181590Srgrimes (void)time(&now); 11927978Scharnier while ((dp = readdir(dirp))) { 1201590Srgrimes if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) 1211590Srgrimes continue; 1221590Srgrimes f = open(dp->d_name, O_RDONLY); 1231590Srgrimes if (f < 0) 1241590Srgrimes continue; 1251590Srgrimes cc = read(f, (char *)&wd, sizeof (struct whod)); 1261590Srgrimes if (cc < WHDRSIZE) { 1271590Srgrimes (void) close(f); 1281590Srgrimes continue; 1291590Srgrimes } 1301590Srgrimes if (down(w,now)) { 1311590Srgrimes (void) close(f); 1321590Srgrimes continue; 1331590Srgrimes } 1341590Srgrimes cc -= WHDRSIZE; 1351590Srgrimes we = w->wd_we; 1361590Srgrimes for (n = cc / sizeof (struct whoent); n > 0; n--) { 1371590Srgrimes if (aflg == 0 && we->we_idle >= 60*60) { 1381590Srgrimes we++; 1391590Srgrimes continue; 1401590Srgrimes } 14127978Scharnier if (nusers >= NUSERS) 14227978Scharnier errx(1, "too many users"); 1431590Srgrimes mp->myutmp = we->we_utmp; mp->myidle = we->we_idle; 1441590Srgrimes (void) strcpy(mp->myhost, w->wd_hostname); 1451590Srgrimes nusers++; we++; mp++; 1461590Srgrimes } 1471590Srgrimes (void) close(f); 1481590Srgrimes } 1491590Srgrimes qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp); 1501590Srgrimes mp = myutmp; 1511590Srgrimes width = 0; 1521590Srgrimes for (i = 0; i < nusers; i++) { 1535239Sats /* append one for the blank and use 8 for the out_line */ 15420165Sache int j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line); 1551590Srgrimes if (j > width) 1561590Srgrimes width = j; 1571590Srgrimes mp++; 1581590Srgrimes } 1591590Srgrimes mp = myutmp; 1601590Srgrimes for (i = 0; i < nusers; i++) { 1619992Sache char buf[BUFSIZ], cbuf[80]; 16289572Sdillon time_t t = _int_to_time(mp->myutmp.out_time); 16374593Sache 16474593Sache strftime(cbuf, sizeof(cbuf), 16574593Sache d_first ? "%e %b %R" : "%b %e %R", 16685639Sdillon localtime(&t)); 16720165Sache (void)sprintf(buf, "%s:%-.*s", mp->myhost, 168229209Sdim (int)sizeof(mp->myutmp.out_line), mp->myutmp.out_line); 16974593Sache printf("%-*.*s %-*s %s", 170229209Sdim (int)sizeof(mp->myutmp.out_name), 171229209Sdim (int)sizeof(mp->myutmp.out_name), 1721590Srgrimes mp->myutmp.out_name, 1731590Srgrimes width, 1741590Srgrimes buf, 17574593Sache cbuf); 1761590Srgrimes mp->myidle /= 60; 1771590Srgrimes if (mp->myidle) { 1781590Srgrimes if (aflg) { 1791590Srgrimes if (mp->myidle >= 100*60) 1801590Srgrimes mp->myidle = 100*60 - 1; 1811590Srgrimes if (mp->myidle >= 60) 1821590Srgrimes printf(" %2d", mp->myidle / 60); 1831590Srgrimes else 1841590Srgrimes printf(" "); 1851590Srgrimes } else 1861590Srgrimes printf(" "); 1871590Srgrimes printf(":%02d", mp->myidle % 60); 1881590Srgrimes } 1891590Srgrimes printf("\n"); 1901590Srgrimes mp++; 1911590Srgrimes } 1921590Srgrimes exit(0); 1931590Srgrimes} 1941590Srgrimes 19527978Scharnier 19627978Scharnierstatic void 19799218Smarkmusage(void) 19827978Scharnier{ 19927978Scharnier fprintf(stderr, "usage: rwho [-a]\n"); 20027978Scharnier exit(1); 20127978Scharnier} 20227978Scharnier 20399218Smarkm#define MYUTMP(a) ((const struct myutmp *)(a)) 20435659Ssteve 20527978Scharnierint 20699218Smarkmutmpcmp(const void *u1, const void *u2) 2071590Srgrimes{ 2081590Srgrimes int rc; 2091590Srgrimes 21035659Ssteve rc = strncmp(MYUTMP(u1)->myutmp.out_name, MYUTMP(u2)->myutmp.out_name, 21135659Ssteve sizeof(MYUTMP(u2)->myutmp.out_name)); 2121590Srgrimes if (rc) 2131590Srgrimes return (rc); 21435659Ssteve rc = strcmp(MYUTMP(u1)->myhost, MYUTMP(u2)->myhost); 2151590Srgrimes if (rc) 2161590Srgrimes return (rc); 21735659Ssteve return (strncmp(MYUTMP(u1)->myutmp.out_line, MYUTMP(u2)->myutmp.out_line, 21835659Ssteve sizeof(MYUTMP(u2)->myutmp.out_line))); 2191590Srgrimes} 220