rwho.c revision 85639
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 * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3527978Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4127978Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)rwho.c 8.1 (Berkeley) 6/6/93"; 4327978Scharnier#endif 4427978Scharnierstatic const char rcsid[] = 4550477Speter "$FreeBSD: head/usr.bin/rwho/rwho.c 85639 2001-10-28 20:26:54Z dillon $"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes#include <sys/param.h> 491590Srgrimes#include <sys/file.h> 501590Srgrimes#include <protocols/rwhod.h> 5118485Sbde#include <dirent.h> 5227978Scharnier#include <err.h> 5374593Sache#include <langinfo.h> 5420156Sache#include <locale.h> 551590Srgrimes#include <stdio.h> 5627978Scharnier#include <stdlib.h> 5720156Sache#include <string.h> 589992Sache#include <time.h> 5927978Scharnier#include <unistd.h> 6020156Sache#include <utmp.h> 611590Srgrimes 621590SrgrimesDIR *dirp; 631590Srgrimes 641590Srgrimesstruct whod wd; 651590Srgrimesint utmpcmp(); 661590Srgrimes#define NUSERS 1000 671590Srgrimesstruct myutmp { 6820165Sache char myhost[sizeof(wd.wd_hostname)]; 691590Srgrimes int myidle; 701590Srgrimes struct outmp myutmp; 711590Srgrimes} myutmp[NUSERS]; 721590Srgrimesint nusers; 731590Srgrimes 741590Srgrimes#define WHDRSIZE (sizeof (wd) - sizeof (wd.wd_we)) 758874Srgrimes/* 761590Srgrimes * this macro should be shared with ruptime. 771590Srgrimes */ 781590Srgrimes#define down(w,now) ((now) - (w)->wd_recvtime > 11 * 60) 791590Srgrimes 801590Srgrimestime_t now; 811590Srgrimesint aflg; 821590Srgrimes 8327978Scharnierstatic void usage __P((void)); 8435659Ssteveint utmpcmp __P((const void *, const void *)); 8527978Scharnier 8627978Scharnierint 871590Srgrimesmain(argc, argv) 881590Srgrimes int argc; 891590Srgrimes char **argv; 901590Srgrimes{ 911590Srgrimes int ch; 9218485Sbde struct dirent *dp; 931590Srgrimes int cc, width; 941590Srgrimes register struct whod *w = &wd; 951590Srgrimes register struct whoent *we; 961590Srgrimes register struct myutmp *mp; 971590Srgrimes int f, n, i; 9874593Sache int d_first; 991590Srgrimes 10011758Sache (void) setlocale(LC_TIME, ""); 10174593Sache d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 10211758Sache 10324360Simp while ((ch = getopt(argc, argv, "a")) != -1) 1041590Srgrimes switch((char)ch) { 1051590Srgrimes case 'a': 1061590Srgrimes aflg = 1; 1071590Srgrimes break; 1081590Srgrimes case '?': 1091590Srgrimes default: 11027978Scharnier usage(); 1111590Srgrimes } 11235659Ssteve argc -= optind; 11335659Ssteve argv += optind; 11435659Ssteve 11535659Ssteve if (argc != 0) 11635659Ssteve usage(); 11735659Ssteve 11827978Scharnier if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) 11927978Scharnier err(1, "%s", _PATH_RWHODIR); 1201590Srgrimes mp = myutmp; 1211590Srgrimes (void)time(&now); 12227978Scharnier while ((dp = readdir(dirp))) { 1231590Srgrimes if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) 1241590Srgrimes continue; 1251590Srgrimes f = open(dp->d_name, O_RDONLY); 1261590Srgrimes if (f < 0) 1271590Srgrimes continue; 1281590Srgrimes cc = read(f, (char *)&wd, sizeof (struct whod)); 1291590Srgrimes if (cc < WHDRSIZE) { 1301590Srgrimes (void) close(f); 1311590Srgrimes continue; 1321590Srgrimes } 1331590Srgrimes if (down(w,now)) { 1341590Srgrimes (void) close(f); 1351590Srgrimes continue; 1361590Srgrimes } 1371590Srgrimes cc -= WHDRSIZE; 1381590Srgrimes we = w->wd_we; 1391590Srgrimes for (n = cc / sizeof (struct whoent); n > 0; n--) { 1401590Srgrimes if (aflg == 0 && we->we_idle >= 60*60) { 1411590Srgrimes we++; 1421590Srgrimes continue; 1431590Srgrimes } 14427978Scharnier if (nusers >= NUSERS) 14527978Scharnier errx(1, "too many users"); 1461590Srgrimes mp->myutmp = we->we_utmp; mp->myidle = we->we_idle; 1471590Srgrimes (void) strcpy(mp->myhost, w->wd_hostname); 1481590Srgrimes nusers++; we++; mp++; 1491590Srgrimes } 1501590Srgrimes (void) close(f); 1511590Srgrimes } 1521590Srgrimes qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp); 1531590Srgrimes mp = myutmp; 1541590Srgrimes width = 0; 1551590Srgrimes for (i = 0; i < nusers; i++) { 1565239Sats /* append one for the blank and use 8 for the out_line */ 15720165Sache int j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line); 1581590Srgrimes if (j > width) 1591590Srgrimes width = j; 1601590Srgrimes mp++; 1611590Srgrimes } 1621590Srgrimes mp = myutmp; 1631590Srgrimes for (i = 0; i < nusers; i++) { 1649992Sache char buf[BUFSIZ], cbuf[80]; 16585639Sdillon time_t t = int_to_time(mp->myutmp.out_time); 16674593Sache 16774593Sache strftime(cbuf, sizeof(cbuf), 16874593Sache d_first ? "%e %b %R" : "%b %e %R", 16985639Sdillon localtime(&t)); 17020165Sache (void)sprintf(buf, "%s:%-.*s", mp->myhost, 17120165Sache sizeof(mp->myutmp.out_line), mp->myutmp.out_line); 17274593Sache printf("%-*.*s %-*s %s", 17320165Sache UT_NAMESIZE, sizeof(mp->myutmp.out_name), 1741590Srgrimes mp->myutmp.out_name, 1751590Srgrimes width, 1761590Srgrimes buf, 17774593Sache cbuf); 1781590Srgrimes mp->myidle /= 60; 1791590Srgrimes if (mp->myidle) { 1801590Srgrimes if (aflg) { 1811590Srgrimes if (mp->myidle >= 100*60) 1821590Srgrimes mp->myidle = 100*60 - 1; 1831590Srgrimes if (mp->myidle >= 60) 1841590Srgrimes printf(" %2d", mp->myidle / 60); 1851590Srgrimes else 1861590Srgrimes printf(" "); 1871590Srgrimes } else 1881590Srgrimes printf(" "); 1891590Srgrimes printf(":%02d", mp->myidle % 60); 1901590Srgrimes } 1911590Srgrimes printf("\n"); 1921590Srgrimes mp++; 1931590Srgrimes } 1941590Srgrimes exit(0); 1951590Srgrimes} 1961590Srgrimes 19727978Scharnier 19827978Scharnierstatic void 19927978Scharnierusage() 20027978Scharnier{ 20127978Scharnier fprintf(stderr, "usage: rwho [-a]\n"); 20227978Scharnier exit(1); 20327978Scharnier} 20427978Scharnier 20535659Ssteve#define MYUTMP(a) ((struct myutmp *)(a)) 20635659Ssteve 20727978Scharnierint 2081590Srgrimesutmpcmp(u1, u2) 20935659Ssteve const void *u1, *u2; 2101590Srgrimes{ 2111590Srgrimes int rc; 2121590Srgrimes 21335659Ssteve rc = strncmp(MYUTMP(u1)->myutmp.out_name, MYUTMP(u2)->myutmp.out_name, 21435659Ssteve sizeof(MYUTMP(u2)->myutmp.out_name)); 2151590Srgrimes if (rc) 2161590Srgrimes return (rc); 21735659Ssteve rc = strcmp(MYUTMP(u1)->myhost, MYUTMP(u2)->myhost); 2181590Srgrimes if (rc) 2191590Srgrimes return (rc); 22035659Ssteve return (strncmp(MYUTMP(u1)->myutmp.out_line, MYUTMP(u2)->myutmp.out_line, 22135659Ssteve sizeof(MYUTMP(u2)->myutmp.out_line))); 2221590Srgrimes} 223