rwho.c revision 99218
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 441590Srgrimes#endif /* not lint */ 451590Srgrimes 4699218Smarkm#include <sys/cdefs.h> 4799218Smarkm__FBSDID("$FreeBSD: head/usr.bin/rwho/rwho.c 99218 2002-07-01 16:40:33Z markm $"); 4899218Smarkm 491590Srgrimes#include <sys/param.h> 501590Srgrimes#include <sys/file.h> 5199218Smarkm 521590Srgrimes#include <protocols/rwhod.h> 5399218Smarkm 5418485Sbde#include <dirent.h> 5527978Scharnier#include <err.h> 5674593Sache#include <langinfo.h> 5720156Sache#include <locale.h> 581590Srgrimes#include <stdio.h> 5927978Scharnier#include <stdlib.h> 6020156Sache#include <string.h> 619992Sache#include <time.h> 6299218Smarkm#include <timeconv.h> 6327978Scharnier#include <unistd.h> 6420156Sache#include <utmp.h> 651590Srgrimes 661590SrgrimesDIR *dirp; 671590Srgrimes 681590Srgrimesstruct whod wd; 691590Srgrimes#define NUSERS 1000 701590Srgrimesstruct myutmp { 7120165Sache char myhost[sizeof(wd.wd_hostname)]; 721590Srgrimes int myidle; 731590Srgrimes struct outmp myutmp; 741590Srgrimes} myutmp[NUSERS]; 751590Srgrimesint nusers; 761590Srgrimes 7799218Smarkm#define WHDRSIZE (ssize_t)(sizeof (wd) - sizeof (wd.wd_we)) 788874Srgrimes/* 791590Srgrimes * this macro should be shared with ruptime. 801590Srgrimes */ 811590Srgrimes#define down(w,now) ((now) - (w)->wd_recvtime > 11 * 60) 821590Srgrimes 831590Srgrimestime_t now; 841590Srgrimesint aflg; 851590Srgrimes 8692921Simpstatic void usage(void); 8792921Simpint utmpcmp(const void *, const void *); 8827978Scharnier 8927978Scharnierint 9099218Smarkmmain(int argc, char *argv[]) 911590Srgrimes{ 921590Srgrimes int ch; 9318485Sbde struct dirent *dp; 9499218Smarkm int width; 9599218Smarkm ssize_t cc; 961590Srgrimes register struct whod *w = &wd; 971590Srgrimes register struct whoent *we; 981590Srgrimes register struct myutmp *mp; 991590Srgrimes int f, n, i; 10074593Sache int d_first; 1011590Srgrimes 10211758Sache (void) setlocale(LC_TIME, ""); 10374593Sache d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 10411758Sache 10524360Simp while ((ch = getopt(argc, argv, "a")) != -1) 1061590Srgrimes switch((char)ch) { 1071590Srgrimes case 'a': 1081590Srgrimes aflg = 1; 1091590Srgrimes break; 1101590Srgrimes case '?': 1111590Srgrimes default: 11227978Scharnier usage(); 1131590Srgrimes } 11435659Ssteve argc -= optind; 11535659Ssteve argv += optind; 11635659Ssteve 11735659Ssteve if (argc != 0) 11835659Ssteve usage(); 11935659Ssteve 12027978Scharnier if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) 12127978Scharnier err(1, "%s", _PATH_RWHODIR); 1221590Srgrimes mp = myutmp; 1231590Srgrimes (void)time(&now); 12427978Scharnier while ((dp = readdir(dirp))) { 1251590Srgrimes if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) 1261590Srgrimes continue; 1271590Srgrimes f = open(dp->d_name, O_RDONLY); 1281590Srgrimes if (f < 0) 1291590Srgrimes continue; 1301590Srgrimes cc = read(f, (char *)&wd, sizeof (struct whod)); 1311590Srgrimes if (cc < WHDRSIZE) { 1321590Srgrimes (void) close(f); 1331590Srgrimes continue; 1341590Srgrimes } 1351590Srgrimes if (down(w,now)) { 1361590Srgrimes (void) close(f); 1371590Srgrimes continue; 1381590Srgrimes } 1391590Srgrimes cc -= WHDRSIZE; 1401590Srgrimes we = w->wd_we; 1411590Srgrimes for (n = cc / sizeof (struct whoent); n > 0; n--) { 1421590Srgrimes if (aflg == 0 && we->we_idle >= 60*60) { 1431590Srgrimes we++; 1441590Srgrimes continue; 1451590Srgrimes } 14627978Scharnier if (nusers >= NUSERS) 14727978Scharnier errx(1, "too many users"); 1481590Srgrimes mp->myutmp = we->we_utmp; mp->myidle = we->we_idle; 1491590Srgrimes (void) strcpy(mp->myhost, w->wd_hostname); 1501590Srgrimes nusers++; we++; mp++; 1511590Srgrimes } 1521590Srgrimes (void) close(f); 1531590Srgrimes } 1541590Srgrimes qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp); 1551590Srgrimes mp = myutmp; 1561590Srgrimes width = 0; 1571590Srgrimes for (i = 0; i < nusers; i++) { 1585239Sats /* append one for the blank and use 8 for the out_line */ 15920165Sache int j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line); 1601590Srgrimes if (j > width) 1611590Srgrimes width = j; 1621590Srgrimes mp++; 1631590Srgrimes } 1641590Srgrimes mp = myutmp; 1651590Srgrimes for (i = 0; i < nusers; i++) { 1669992Sache char buf[BUFSIZ], cbuf[80]; 16789572Sdillon time_t t = _int_to_time(mp->myutmp.out_time); 16874593Sache 16974593Sache strftime(cbuf, sizeof(cbuf), 17074593Sache d_first ? "%e %b %R" : "%b %e %R", 17185639Sdillon localtime(&t)); 17220165Sache (void)sprintf(buf, "%s:%-.*s", mp->myhost, 17320165Sache sizeof(mp->myutmp.out_line), mp->myutmp.out_line); 17474593Sache printf("%-*.*s %-*s %s", 17520165Sache UT_NAMESIZE, sizeof(mp->myutmp.out_name), 1761590Srgrimes mp->myutmp.out_name, 1771590Srgrimes width, 1781590Srgrimes buf, 17974593Sache cbuf); 1801590Srgrimes mp->myidle /= 60; 1811590Srgrimes if (mp->myidle) { 1821590Srgrimes if (aflg) { 1831590Srgrimes if (mp->myidle >= 100*60) 1841590Srgrimes mp->myidle = 100*60 - 1; 1851590Srgrimes if (mp->myidle >= 60) 1861590Srgrimes printf(" %2d", mp->myidle / 60); 1871590Srgrimes else 1881590Srgrimes printf(" "); 1891590Srgrimes } else 1901590Srgrimes printf(" "); 1911590Srgrimes printf(":%02d", mp->myidle % 60); 1921590Srgrimes } 1931590Srgrimes printf("\n"); 1941590Srgrimes mp++; 1951590Srgrimes } 1961590Srgrimes exit(0); 1971590Srgrimes} 1981590Srgrimes 19927978Scharnier 20027978Scharnierstatic void 20199218Smarkmusage(void) 20227978Scharnier{ 20327978Scharnier fprintf(stderr, "usage: rwho [-a]\n"); 20427978Scharnier exit(1); 20527978Scharnier} 20627978Scharnier 20799218Smarkm#define MYUTMP(a) ((const struct myutmp *)(a)) 20835659Ssteve 20927978Scharnierint 21099218Smarkmutmpcmp(const void *u1, const void *u2) 2111590Srgrimes{ 2121590Srgrimes int rc; 2131590Srgrimes 21435659Ssteve rc = strncmp(MYUTMP(u1)->myutmp.out_name, MYUTMP(u2)->myutmp.out_name, 21535659Ssteve sizeof(MYUTMP(u2)->myutmp.out_name)); 2161590Srgrimes if (rc) 2171590Srgrimes return (rc); 21835659Ssteve rc = strcmp(MYUTMP(u1)->myhost, MYUTMP(u2)->myhost); 2191590Srgrimes if (rc) 2201590Srgrimes return (rc); 22135659Ssteve return (strncmp(MYUTMP(u1)->myutmp.out_line, MYUTMP(u2)->myutmp.out_line, 22235659Ssteve sizeof(MYUTMP(u2)->myutmp.out_line))); 2231590Srgrimes} 224