rwho.c revision 252596
1186904Ssam/*- 2186904Ssam * Copyright (c) 1983, 1993 The Regents of the University of California. 3186904Ssam * All rights reserved. 4186904Ssam * 5186904Ssam * Redistribution and use in source and binary forms, with or without 6186904Ssam * modification, are permitted provided that the following conditions 7186904Ssam * are met: 8186904Ssam * 1. Redistributions of source code must retain the above copyright 9186904Ssam * notice, this list of conditions and the following disclaimer. 10186904Ssam * 2. Redistributions in binary form must reproduce the above copyright 11186904Ssam * notice, this list of conditions and the following disclaimer in the 12186904Ssam * documentation and/or other materials provided with the distribution. 13186904Ssam * 4. Neither the name of the University nor the names of its contributors 14186904Ssam * may be used to endorse or promote products derived from this software 15186904Ssam * without specific prior written permission. 16186904Ssam * 17186904Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18186904Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19186904Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20186904Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21186904Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22186904Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23186904Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24186904Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25186904Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26186904Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27186904Ssam * SUCH DAMAGE. 28186904Ssam */ 29186904Ssam 30186904Ssam#ifndef lint 31186904Ssamstatic const char copyright[] = 32186904Ssam"@(#) Copyright (c) 1983, 1993\n\ 33186904Ssam The Regents of the University of California. All rights reserved.\n"; 34186904Ssam#endif /* not lint */ 35186904Ssam 36186904Ssam#ifndef lint 37186904Ssam#if 0 38186904Ssamstatic char sccsid[] = "@(#)rwho.c 8.1 (Berkeley) 6/6/93"; 39186904Ssam#endif 40186904Ssam#endif /* not lint */ 41186904Ssam 42186904Ssam#include <sys/cdefs.h> 43186904Ssam__FBSDID("$FreeBSD: head/usr.bin/rwho/rwho.c 252596 2013-07-03 20:28:33Z pjd $"); 44186904Ssam 45186904Ssam#include <sys/param.h> 46186904Ssam#include <sys/file.h> 47186904Ssam 48186904Ssam#include <protocols/rwhod.h> 49186904Ssam 50186904Ssam#include <dirent.h> 51186904Ssam#include <err.h> 52186904Ssam#include <langinfo.h> 53186904Ssam#include <locale.h> 54186904Ssam#include <stdio.h> 55186904Ssam#include <stdlib.h> 56186904Ssam#include <string.h> 57186904Ssam#include <time.h> 58186904Ssam#include <timeconv.h> 59186904Ssam#include <unistd.h> 60186904Ssam 61186904Ssam#define NUSERS 1000 62186904Ssam#define WHDRSIZE (ssize_t)(sizeof (wd) - sizeof (wd.wd_we)) 63186904Ssam/* 64186904Ssam * this macro should be shared with ruptime. 65186904Ssam */ 66186904Ssam#define down(w,now) ((now) - (w)->wd_recvtime > 11 * 60) 67186904Ssam 68186904Ssamstatic DIR *dirp; 69186904Ssamstatic struct whod wd; 70186904Ssamstatic int nusers; 71186904Ssamstatic struct myutmp { 72186904Ssam char myhost[sizeof(wd.wd_hostname)]; 73186904Ssam int myidle; 74186904Ssam struct outmp myutmp; 75186904Ssam} myutmp[NUSERS]; 76186904Ssam 77186904Ssamstatic time_t now; 78186904Ssamstatic int aflg; 79186904Ssam 80186904Ssamstatic void usage(void); 81187899Ssamstatic int utmpcmp(const void *, const void *); 82187899Ssam 83187899Ssamint 84188782Ssammain(int argc, char *argv[]) 85188782Ssam{ 86188782Ssam int ch; 87188782Ssam struct dirent *dp; 88188782Ssam int width; 89188782Ssam ssize_t cc; 90187899Ssam struct whod *w; 91187899Ssam struct whoent *we; 92187899Ssam struct myutmp *mp; 93187899Ssam int f, n, i; 94187899Ssam int d_first; 95187899Ssam 96186904Ssam w = &wd; 97186904Ssam (void) setlocale(LC_TIME, ""); 98186904Ssam d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 99186904Ssam 100186904Ssam while ((ch = getopt(argc, argv, "a")) != -1) { 101186904Ssam switch ((char)ch) { 102186904Ssam case 'a': 103186904Ssam aflg = 1; 104186904Ssam break; 105186904Ssam case '?': 106186904Ssam default: 107186904Ssam usage(); 108186904Ssam } 109187899Ssam } 110187899Ssam argc -= optind; 111187899Ssam argv += optind; 112187899Ssam 113187899Ssam if (argc != 0) 114187899Ssam usage(); 115187899Ssam 116186904Ssam if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) 117186904Ssam err(1, "%s", _PATH_RWHODIR); 118186904Ssam mp = myutmp; 119186904Ssam (void) time(&now); 120186904Ssam while ((dp = readdir(dirp)) != NULL) { 121186904Ssam if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0) 122186904Ssam continue; 123186904Ssam f = open(dp->d_name, O_RDONLY); 124186904Ssam if (f < 0) 125186904Ssam continue; 126186904Ssam cc = read(f, (char *)&wd, sizeof (struct whod)); 127186904Ssam if (cc < WHDRSIZE) { 128186904Ssam (void) close(f); 129186904Ssam continue; 130186904Ssam } 131186904Ssam if (down(w,now) != 0) { 132186904Ssam (void) close(f); 133186904Ssam continue; 134186904Ssam } 135186904Ssam cc -= WHDRSIZE; 136186904Ssam we = w->wd_we; 137186904Ssam for (n = cc / sizeof (struct whoent); n > 0; n--) { 138186904Ssam if (aflg == 0 && we->we_idle >= 60 * 60) { 139186904Ssam we++; 140186904Ssam continue; 141186904Ssam } 142186904Ssam if (nusers >= NUSERS) 143186904Ssam errx(1, "too many users"); 144189980Ssam mp->myutmp = we->we_utmp; 145186904Ssam mp->myidle = we->we_idle; 146186904Ssam (void) strcpy(mp->myhost, w->wd_hostname); 147186904Ssam nusers++; 148186904Ssam we++; 149186904Ssam mp++; 150186904Ssam } 151187899Ssam (void) close(f); 152187899Ssam } 153187899Ssam qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp); 154187899Ssam mp = myutmp; 155187899Ssam width = 0; 156187899Ssam for (i = 0; i < nusers; i++) { 157188782Ssam /* append one for the blank and use 8 for the out_line */ 158188782Ssam int j; 159186904Ssam 160186904Ssam j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line); 161186904Ssam if (j > width) 162186904Ssam width = j; 163186904Ssam mp++; 164186904Ssam } 165186904Ssam mp = myutmp; 166186904Ssam for (i = 0; i < nusers; i++) { 167186904Ssam char buf[BUFSIZ], cbuf[80]; 168186904Ssam time_t t; 169186904Ssam 170186904Ssam t = _int_to_time(mp->myutmp.out_time); 171186904Ssam strftime(cbuf, sizeof(cbuf), 172186904Ssam d_first ? "%e %b %R" : "%b %e %R", 173186904Ssam localtime(&t)); 174186904Ssam (void) sprintf(buf, "%s:%-.*s", mp->myhost, 175186904Ssam (int)sizeof(mp->myutmp.out_line), mp->myutmp.out_line); 176186904Ssam printf("%-*.*s %-*s %s", 177186904Ssam (int)sizeof(mp->myutmp.out_name), 178186904Ssam (int)sizeof(mp->myutmp.out_name), 179186904Ssam mp->myutmp.out_name, 180186904Ssam width, 181186904Ssam buf, 182186904Ssam cbuf); 183186904Ssam mp->myidle /= 60; 184188467Ssam if (mp->myidle != 0) { 185188467Ssam if (aflg != 0) { 186188467Ssam if (mp->myidle >= 100 * 60) 187188467Ssam mp->myidle = 100 * 60 - 1; 188188467Ssam if (mp->myidle >= 60) 189188467Ssam printf(" %2d", mp->myidle / 60); 190188467Ssam else 191188467Ssam printf(" "); 192188467Ssam } else { 193186904Ssam printf(" "); 194186904Ssam } 195186904Ssam printf(":%02d", mp->myidle % 60); 196186904Ssam } 197186904Ssam printf("\n"); 198186904Ssam mp++; 199186904Ssam } 200188467Ssam exit(0); 201186904Ssam} 202186904Ssam 203186904Ssam 204188467Ssamstatic void 205186904Ssamusage(void) 206186904Ssam{ 207186904Ssam fprintf(stderr, "usage: rwho [-a]\n"); 208186904Ssam exit(1); 209186904Ssam} 210186904Ssam 211186904Ssam#define MYUTMP(a) ((const struct myutmp *)(a)) 212186904Ssam 213186904Ssamstatic int 214186904Ssamutmpcmp(const void *u1, const void *u2) 215186904Ssam{ 216186904Ssam int rc; 217186904Ssam 218186904Ssam rc = strncmp(MYUTMP(u1)->myutmp.out_name, MYUTMP(u2)->myutmp.out_name, 219186904Ssam sizeof(MYUTMP(u2)->myutmp.out_name)); 220186904Ssam if (rc != 0) 221186904Ssam return (rc); 222188467Ssam rc = strcmp(MYUTMP(u1)->myhost, MYUTMP(u2)->myhost); 223188467Ssam if (rc != 0) 224188467Ssam return (rc); 225188467Ssam return (strncmp(MYUTMP(u1)->myutmp.out_line, MYUTMP(u2)->myutmp.out_line, 226186904Ssam sizeof(MYUTMP(u2)->myutmp.out_line))); 227186904Ssam} 228186904Ssam