tc.who.c revision 167465
11573Srgrimes/* $Header: /p/tcsh/cvsroot/tcsh/tc.who.c,v 3.51 2006/03/03 22:08:45 amold Exp $ */ 21573Srgrimes/* 31573Srgrimes * tc.who.c: Watch logins and logouts... 41573Srgrimes */ 51573Srgrimes/*- 61573Srgrimes * Copyright (c) 1980, 1991 The Regents of the University of California. 71573Srgrimes * All rights reserved. 81573Srgrimes * 91573Srgrimes * Redistribution and use in source and binary forms, with or without 101573Srgrimes * modification, are permitted provided that the following conditions 111573Srgrimes * are met: 121573Srgrimes * 1. Redistributions of source code must retain the above copyright 131573Srgrimes * notice, this list of conditions and the following disclaimer. 141573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151573Srgrimes * notice, this list of conditions and the following disclaimer in the 161573Srgrimes * documentation and/or other materials provided with the distribution. 171573Srgrimes * 3. Neither the name of the University nor the names of its contributors 181573Srgrimes * may be used to endorse or promote products derived from this software 191573Srgrimes * without specific prior written permission. 201573Srgrimes * 211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311573Srgrimes * SUCH DAMAGE. 321573Srgrimes */ 331573Srgrimes#include "sh.h" 341573Srgrimes 351573SrgrimesRCSID("$tcsh: tc.who.c,v 3.51 2006/03/03 22:08:45 amold Exp $") 361573Srgrimes 371573Srgrimes#include "tc.h" 381573Srgrimes 391573Srgrimes#ifndef HAVENOUTMP 4090045Sobrien/* 4190045Sobrien * kfk 26 Jan 1984 - for login watch functions. 421573Srgrimes */ 431573Srgrimes#include <ctype.h> 441573Srgrimes 451573Srgrimes#ifdef HAVE_UTMPX_H 461573Srgrimes# include <utmpx.h> 471573Srgrimes/* I just redefine a few words here. Changing every occurrence below 481573Srgrimes * seems like too much of work. All UTMP functions have equivalent 491573Srgrimes * UTMPX counterparts, so they can be added all here when needed. 501573Srgrimes * Kimmo Suominen, Oct 14 1991 511573Srgrimes */ 521573Srgrimes# if defined(__UTMPX_FILE) && !defined(UTMPX_FILE) 531573Srgrimes# define TCSH_PATH_UTMP __UTMPX_FILE 541573Srgrimes# elif defined(_PATH_UTMPX) 551573Srgrimes# define TCSH_PATH_UTMP _PATH_UTMPX 561573Srgrimes# elif defined(UTMPX_FILE) 571573Srgrimes# define TCSH_PATH_UTMP UTMPX_FILE 581573Srgrimes# endif /* __UTMPX_FILE && !UTMPX_FILE */ 591573Srgrimes# ifdef TCSH_PATH_UTMP 601573Srgrimes# define utmp utmpx 611573Srgrimes# if defined(HAVE_STRUCT_UTMP_UT_TV) 621573Srgrimes# define ut_time ut_tv.tv_sec 638870Srgrimes# elif defined(HAVE_STRUCT_UTMP_UT_XTIME) 641573Srgrimes# define ut_time ut_xtime 651573Srgrimes# endif 661573Srgrimes# ifdef HAVE_STRUCT_UTMP_UT_USER 671573Srgrimes# define ut_name ut_user 681573Srgrimes# endif 691573Srgrimes# ifdef HAVE_GETUTENT 701573Srgrimes# define getutent getutxent 711573Srgrimes# define setutent setutxent 721573Srgrimes# define endutent endutxent 731573Srgrimes# endif /* HAVE_GETUTENT */ 741573Srgrimes# else 751573Srgrimes# ifdef HAVE_UTMP_H 761573Srgrimes# include <utmp.h> 771573Srgrimes# endif /* WINNT_NATIVE */ 781573Srgrimes# endif /* TCSH_PATH_UTMP */ 791573Srgrimes#else /* !HAVE_UTMPX_H */ 801573Srgrimes# ifdef HAVE_UTMP_H 8119276Sache# include <utmp.h> 8219276Sache# endif /* WINNT_NATIVE */ 831573Srgrimes#endif /* HAVE_UTMPX_H */ 841573Srgrimes 851573Srgrimes#ifndef BROKEN_CC 861573Srgrimes# define UTNAMLEN sizeof(((struct utmp *) 0)->ut_name) 871573Srgrimes# define UTLINLEN sizeof(((struct utmp *) 0)->ut_line) 881573Srgrimes# ifdef HAVE_STRUCT_UTMP_UT_HOST 891573Srgrimes# ifdef _SEQUENT_ 901573Srgrimes# define UTHOSTLEN 100 911573Srgrimes# else 921573Srgrimes# define UTHOSTLEN sizeof(((struct utmp *) 0)->ut_host) 931573Srgrimes# endif 941573Srgrimes# endif /* HAVE_STRUCT_UTMP_UT_HOST */ 951573Srgrimes#else 961573Srgrimes/* give poor cc a little help if it needs it */ 971573Srgrimesstruct utmp __ut; 981573Srgrimes 991573Srgrimes# define UTNAMLEN sizeof(__ut.ut_name) 1001573Srgrimes# define UTLINLEN sizeof(__ut.ut_line) 1011573Srgrimes# ifdef HAVE_STRUCT_UTMP_UT_HOST 1021573Srgrimes# ifdef _SEQUENT_ 1031573Srgrimes# define UTHOSTLEN 100 1041573Srgrimes# else 1051573Srgrimes# define UTHOSTLEN sizeof(__ut.ut_host) 1061573Srgrimes# endif 1071573Srgrimes# endif /* HAVE_STRUCT_UTMP_UT_HOST */ 1081573Srgrimes#endif /* BROKEN_CC */ 1091573Srgrimes 1101573Srgrimes#ifndef TCSH_PATH_UTMP 1111573Srgrimes# ifdef UTMP_FILE 1121573Srgrimes# define TCSH_PATH_UTMP UTMP_FILE 1131573Srgrimes# elif defined(_PATH_UTMP) 1141573Srgrimes# define TCSH_PATH_UTMP _PATH_UTMP 1151573Srgrimes# else 1161573Srgrimes# define TCSH_PATH_UTMP "/etc/utmp" 1171573Srgrimes# endif /* UTMP_FILE */ 1181573Srgrimes#endif /* TCSH_PATH_UTMP */ 1191573Srgrimes 1201573Srgrimes 1211573Srgrimesstruct who { 1221573Srgrimes struct who *who_next; 1231573Srgrimes struct who *who_prev; 1241573Srgrimes char who_name[UTNAMLEN + 1]; 1251573Srgrimes char who_new[UTNAMLEN + 1]; 1261573Srgrimes char who_tty[UTLINLEN + 1]; 1271573Srgrimes#ifdef HAVE_STRUCT_UTMP_UT_HOST 1281573Srgrimes char who_host[UTHOSTLEN + 1]; 1291573Srgrimes#endif /* HAVE_STRUCT_UTMP_UT_HOST */ 1301573Srgrimes time_t who_time; 1311573Srgrimes int who_status; 1321573Srgrimes}; 13390045Sobrien 13490045Sobrienstatic struct who whohead, whotail; 13590045Sobrienstatic time_t watch_period = 0; 13690045Sobrienstatic time_t stlast = 0; 13790045Sobrien#ifdef WHODEBUG 1381573Srgrimesstatic void debugwholist (struct who *, struct who *); 13990045Sobrien#endif 1401573Srgrimesstatic void print_who (struct who *); 14190045Sobrien 14290045Sobrien 14390045Sobrien#define ONLINE 01 14490045Sobrien#define OFFLINE 02 14590045Sobrien#define CHANGED 04 14690045Sobrien#define STMASK 07 14774963Speter#define ANNOUNCE 010 14890045Sobrien#define CLEARED 020 14990045Sobrien 15090045Sobrien/* 15190045Sobrien * Karl Kleinpaste, 26 Jan 1984. 1521573Srgrimes * Initialize the dummy tty list for login watch. 15390045Sobrien * This dummy list eliminates boundary conditions 1541573Srgrimes * when doing pointer-chase searches. 1551573Srgrimes */ 1561573Srgrimesvoid 1571573Srgrimesinitwatch(void) 1581573Srgrimes{ 15990045Sobrien whohead.who_next = &whotail; 1601573Srgrimes whotail.who_prev = &whohead; 1611573Srgrimes stlast = 1; 1621573Srgrimes#ifdef WHODEBUG 16374469Sjlemon debugwholist(NULL, NULL); 16474963Speter#endif /* WHODEBUG */ 1651573Srgrimes} 1661573Srgrimes 1671573Srgrimesvoid 1681573Srgrimesresetwatch(void) 1691573Srgrimes{ 1701573Srgrimes watch_period = 0; 1711573Srgrimes stlast = 0; 1721573Srgrimes} 17380525Smikeh 17474469Sjlemon/* 17580525Smikeh * Karl Kleinpaste, 26 Jan 1984. 17680525Smikeh * Watch /etc/utmp for login/logout changes. 17780525Smikeh */ 17874469Sjlemonvoid 1791573Srgrimeswatch_login(int force) 1801573Srgrimes{ 1811573Srgrimes int comp = -1, alldone; 1821573Srgrimes int firsttime = stlast == 1; 1831573Srgrimes#ifdef HAVE_GETUTENT 18474963Speter struct utmp *uptr; 1851573Srgrimes#else 1861573Srgrimes int utmpfd; 1878870Srgrimes#endif 1881573Srgrimes struct utmp utmp; 1891573Srgrimes struct who *wp, *wpnew; 1901573Srgrimes struct varent *v; 1911573Srgrimes Char **vp = NULL; 1921573Srgrimes time_t t, interval = MAILINTVL; 1931573Srgrimes struct stat sta; 1941573Srgrimes#if defined(HAVE_STRUCT_UTMP_UT_HOST) && defined(_SEQUENT_) 1951573Srgrimes char *host, *ut_find_host(); 1961573Srgrimes#endif 1971573Srgrimes#ifdef WINNT_NATIVE 1988870Srgrimes static int ncbs_posted = 0; 1998870Srgrimes USE(utmp); 2001573Srgrimes USE(utmpfd); 2011573Srgrimes USE(sta); 2021573Srgrimes USE(wpnew); 2031573Srgrimes#endif /* WINNT_NATIVE */ 20474469Sjlemon 2051573Srgrimes /* stop SIGINT, lest our login list get trashed. */ 20674469Sjlemon pintr_disabled++; 2071573Srgrimes cleanup_push(&pintr_disabled, disabled_cleanup); 2081573Srgrimes 2091573Srgrimes v = adrof(STRwatch); 2101573Srgrimes if ((v == NULL || v->vec == NULL) && !force) { 2111573Srgrimes cleanup_until(&pintr_disabled); 2121573Srgrimes return; /* no names to watch */ 2131573Srgrimes } 21474963Speter if (!force) { 21574963Speter trim(vp = v->vec); 2161573Srgrimes if (blklen(vp) % 2) /* odd # args: 1st == # minutes. */ 2171573Srgrimes interval = (number(*vp)) ? (getn(*vp++) * 60) : MAILINTVL; 21874469Sjlemon } 2191573Srgrimes else 2201573Srgrimes interval = 0; 2211573Srgrimes 2221573Srgrimes (void) time(&t); 2231573Srgrimes#ifdef WINNT_NATIVE 2241573Srgrimes /* 22574469Sjlemon * Since NCB_ASTATs take time, start em async at least 90 secs 2261573Srgrimes * before we are due -amol 6/5/97 2271573Srgrimes */ 22874469Sjlemon if (!ncbs_posted) { 2291573Srgrimes time_t tdiff = t - watch_period; 2301573Srgrimes if (!watch_period || ((tdiff > 0) && (tdiff > (interval - 90)))) { 23174469Sjlemon start_ncbs(vp); 2321573Srgrimes ncbs_posted = 1; 2331573Srgrimes } 2341573Srgrimes } 2351573Srgrimes#endif /* WINNT_NATIVE */ 2361573Srgrimes if (t - watch_period < interval) { 2371573Srgrimes cleanup_until(&pintr_disabled); 2381573Srgrimes return; /* not long enough yet... */ 2391573Srgrimes } 24074963Speter watch_period = t; 24174963Speter#ifdef WINNT_NATIVE 2421573Srgrimes ncbs_posted = 0; 2431573Srgrimes#else /* !WINNT_NATIVE */ 24474469Sjlemon 2451573Srgrimes /* 2461573Srgrimes * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 2471573Srgrimes * Don't open utmp all the time, stat it first... 2481573Srgrimes */ 24974963Speter if (stat(TCSH_PATH_UTMP, &sta)) { 2501573Srgrimes if (!force) 2511573Srgrimes xprintf(CGETS(26, 1, 2521573Srgrimes "cannot stat %s. Please \"unset watch\".\n"), 2531573Srgrimes TCSH_PATH_UTMP); 25474963Speter cleanup_until(&pintr_disabled); 2551573Srgrimes return; 2561573Srgrimes } 2571573Srgrimes if (stlast == sta.st_mtime) { 2581573Srgrimes cleanup_until(&pintr_disabled); 2591573Srgrimes return; 2601573Srgrimes } 2611573Srgrimes stlast = sta.st_mtime; 2621573Srgrimes#ifdef HAVE_GETUTENT 2631573Srgrimes setutent(); 2648870Srgrimes#else 2651573Srgrimes if ((utmpfd = xopen(TCSH_PATH_UTMP, O_RDONLY|O_LARGEFILE)) < 0) { 2661573Srgrimes if (!force) 2671573Srgrimes xprintf(CGETS(26, 2, 2681573Srgrimes "%s cannot be opened. Please \"unset watch\".\n"), 2691573Srgrimes TCSH_PATH_UTMP); 2701573Srgrimes cleanup_until(&pintr_disabled); 2711573Srgrimes return; 2721573Srgrimes } 2731573Srgrimes cleanup_push(&utmpfd, open_cleanup); 2741573Srgrimes#endif 2751573Srgrimes 2761573Srgrimes /* 2771573Srgrimes * xterm clears the entire utmp entry - mark everyone on the status list 2781573Srgrimes * OFFLINE or we won't notice X "logouts" 2791573Srgrimes */ 2801573Srgrimes for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) 28174469Sjlemon wp->who_status = OFFLINE | CLEARED; 2821573Srgrimes 2831573Srgrimes /* 2841573Srgrimes * Read in the utmp file, sort the entries, and update existing entries or 2851573Srgrimes * add new entries to the status list. 2861573Srgrimes */ 2871573Srgrimes#ifdef HAVE_GETUTENT 2881573Srgrimes while ((uptr = getutent()) != NULL) { 2891573Srgrimes memcpy(&utmp, uptr, sizeof (utmp)); 2901573Srgrimes#else 2911573Srgrimes while (xread(utmpfd, &utmp, sizeof utmp) == sizeof utmp) { 2928870Srgrimes#endif 2931573Srgrimes 2941573Srgrimes# ifdef DEAD_PROCESS 2951573Srgrimes# ifndef IRIS4D 2961573Srgrimes if (utmp.ut_type != USER_PROCESS) 2971573Srgrimes continue; 2981573Srgrimes# else 2991573Srgrimes /* Why is that? Cause the utmp file is always corrupted??? */ 3001573Srgrimes if (utmp.ut_type != USER_PROCESS && utmp.ut_type != DEAD_PROCESS) 3011573Srgrimes continue; 3021573Srgrimes# endif /* IRIS4D */ 3031573Srgrimes# endif /* DEAD_PROCESS */ 3041573Srgrimes 3051573Srgrimes if (utmp.ut_name[0] == '\0' && utmp.ut_line[0] == '\0') 3061573Srgrimes continue; /* completely void entry */ 3071573Srgrimes# ifdef DEAD_PROCESS 3081573Srgrimes if (utmp.ut_type == DEAD_PROCESS && utmp.ut_line[0] == '\0') 3091573Srgrimes continue; 3101573Srgrimes# endif /* DEAD_PROCESS */ 3111573Srgrimes wp = whohead.who_next; 3121573Srgrimes while (wp->who_next && (comp = strncmp(wp->who_tty, utmp.ut_line, UTLINLEN)) < 0) 3131573Srgrimes wp = wp->who_next;/* find that tty! */ 3141573Srgrimes 3151573Srgrimes if (wp->who_next && comp == 0) { /* found the tty... */ 3161573Srgrimes if (utmp.ut_time < wp->who_time) 3178870Srgrimes continue; 3181573Srgrimes# ifdef DEAD_PROCESS 3191573Srgrimes if (utmp.ut_type == DEAD_PROCESS) { 3201573Srgrimes wp->who_time = utmp.ut_time; 3211573Srgrimes wp->who_status = OFFLINE; 3221573Srgrimes } 3231573Srgrimes else 3241573Srgrimes# endif /* DEAD_PROCESS */ 3251573Srgrimes if (utmp.ut_name[0] == '\0') { 3261573Srgrimes wp->who_time = utmp.ut_time; 3271573Srgrimes wp->who_status = OFFLINE; 32874469Sjlemon } 3291573Srgrimes else if (strncmp(utmp.ut_name, wp->who_name, UTNAMLEN) == 0) { 3301573Srgrimes /* someone is logged in */ 3311573Srgrimes wp->who_time = utmp.ut_time; 3321573Srgrimes wp->who_status = ONLINE | ANNOUNCE; /* same guy */ 3331573Srgrimes } 3341573Srgrimes else { 3351573Srgrimes (void) strncpy(wp->who_new, utmp.ut_name, UTNAMLEN); 3361573Srgrimes# ifdef HAVE_STRUCT_UTMP_UT_HOST 3371573Srgrimes# ifdef _SEQUENT_ 3381573Srgrimes host = ut_find_host(wp->who_tty); 3391573Srgrimes if (host) 3401573Srgrimes (void) strncpy(wp->who_host, host, UTHOSTLEN); 3411573Srgrimes else 3421573Srgrimes wp->who_host[0] = 0; 3431573Srgrimes# else 3441573Srgrimes (void) strncpy(wp->who_host, utmp.ut_host, UTHOSTLEN); 3451573Srgrimes# endif 3461573Srgrimes# endif /* HAVE_STRUCT_UTMP_UT_HOST */ 3471573Srgrimes wp->who_time = utmp.ut_time; 34824158Simp if (wp->who_name[0] == '\0') 3491573Srgrimes wp->who_status = ONLINE; 3501573Srgrimes else 35124158Simp wp->who_status = CHANGED; 3521573Srgrimes } 3531573Srgrimes } 3541573Srgrimes else { /* new tty in utmp */ 3551573Srgrimes wpnew = xcalloc(1, sizeof *wpnew); 3561573Srgrimes (void) strncpy(wpnew->who_tty, utmp.ut_line, UTLINLEN); 35724158Simp# ifdef HAVE_STRUCT_UTMP_UT_HOST 3581573Srgrimes# ifdef _SEQUENT_ 3591573Srgrimes host = ut_find_host(wpnew->who_tty); 3601573Srgrimes if (host) 3611573Srgrimes (void) strncpy(wpnew->who_host, host, UTHOSTLEN); 36224158Simp else 36324158Simp wpnew->who_host[0] = 0; 36424158Simp# else 36524158Simp (void) strncpy(wpnew->who_host, utmp.ut_host, UTHOSTLEN); 36624158Simp# endif 36724158Simp# endif /* HAVE_STRUCT_UTMP_UT_HOST */ 3681573Srgrimes wpnew->who_time = utmp.ut_time; 3691573Srgrimes# ifdef DEAD_PROCESS 3701573Srgrimes if (utmp.ut_type == DEAD_PROCESS) 3711573Srgrimes wpnew->who_status = OFFLINE; 3721573Srgrimes else 3738870Srgrimes# endif /* DEAD_PROCESS */ 37428820Simp if (utmp.ut_name[0] == '\0') 37528820Simp wpnew->who_status = OFFLINE; 37628820Simp else { 3771573Srgrimes (void) strncpy(wpnew->who_new, utmp.ut_name, UTNAMLEN); 37833664Sjb wpnew->who_status = ONLINE; 37933664Sjb } 38033664Sjb# ifdef WHODEBUG 38133664Sjb debugwholist(wpnew, wp); 38233664Sjb# endif /* WHODEBUG */ 38328836Sache 38428836Sache wpnew->who_next = wp; /* link in a new 'who' */ 38528836Sache wpnew->who_prev = wp->who_prev; 38628836Sache wpnew->who_prev->who_next = wpnew; 38728836Sache wp->who_prev = wpnew; /* linked in now */ 3881573Srgrimes } 3891573Srgrimes } 3901573Srgrimes#ifdef HAVE_GETUTENT 3911573Srgrimes endutent(); 3921573Srgrimes#else 3931573Srgrimes cleanup_until(&utmpfd); 3941573Srgrimes#endif 3951573Srgrimes# if defined(HAVE_STRUCT_UTMP_UT_HOST) && defined(_SEQUENT_) 3961573Srgrimes endutent(); 3971573Srgrimes# endif 3981573Srgrimes#endif /* !WINNT_NATIVE */ 3991573Srgrimes 4001573Srgrimes if (force || vp == NULL) { 4011573Srgrimes cleanup_until(&pintr_disabled); 40224158Simp return; 4031573Srgrimes } 4048870Srgrimes 4051573Srgrimes /* 40624158Simp * The state of all logins is now known, so we can search the user's list 4071573Srgrimes * of watchables to print the interesting ones. 40824158Simp */ 4091573Srgrimes for (alldone = 0; !alldone && *vp != NULL && **vp != '\0' && 4101573Srgrimes *(vp + 1) != NULL && **(vp + 1) != '\0'; 4111573Srgrimes vp += 2) { /* args used in pairs... */ 4121573Srgrimes 4138870Srgrimes if (eq(*vp, STRany) && eq(*(vp + 1), STRany)) 4141573Srgrimes alldone = 1; 4151573Srgrimes 4161573Srgrimes for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) { 4171573Srgrimes if (wp->who_status & ANNOUNCE || 4181573Srgrimes (!eq(STRany, vp[0]) && 4191573Srgrimes !Gmatch(str2short(wp->who_name), vp[0]) && 4201573Srgrimes !Gmatch(str2short(wp->who_new), vp[0])) || 4211573Srgrimes (!Gmatch(str2short(wp->who_tty), vp[1]) && 42274469Sjlemon !eq(STRany, vp[1]))) 4231573Srgrimes continue; /* entry doesn't qualify */ 4241573Srgrimes /* already printed or not right one to print */ 42574469Sjlemon 4261573Srgrimes 4271573Srgrimes if (wp->who_status & CLEARED) {/* utmp entry was cleared */ 4281573Srgrimes wp->who_time = watch_period; 42974963Speter wp->who_status &= ~CLEARED; 4301573Srgrimes } 43174963Speter 4321573Srgrimes if ((wp->who_status & OFFLINE) && 4331573Srgrimes (wp->who_name[0] != '\0')) { 4341573Srgrimes if (!firsttime) 4351573Srgrimes print_who(wp); 4361573Srgrimes wp->who_name[0] = '\0'; 4371573Srgrimes wp->who_status |= ANNOUNCE; 4381573Srgrimes continue; 4391573Srgrimes } 4401573Srgrimes if (wp->who_status & ONLINE) { 4411573Srgrimes if (!firsttime) 4421573Srgrimes print_who(wp); 4431573Srgrimes (void) strcpy(wp->who_name, wp->who_new); 4441573Srgrimes wp->who_status |= ANNOUNCE; 4451573Srgrimes continue; 4461573Srgrimes } 4471573Srgrimes if (wp->who_status & CHANGED) { 4481573Srgrimes if (!firsttime) 4491573Srgrimes print_who(wp); 4501573Srgrimes (void) strcpy(wp->who_name, wp->who_new); 4511573Srgrimes wp->who_status |= ANNOUNCE; 4521573Srgrimes continue; 4531573Srgrimes } 4541573Srgrimes } 4551573Srgrimes } 4561573Srgrimes cleanup_until(&pintr_disabled); 4571573Srgrimes} 4581573Srgrimes 4591573Srgrimes#ifdef WHODEBUG 4601573Srgrimesstatic void 4611573Srgrimesdebugwholist(struct who *new, struct who *wp) 4621573Srgrimes{ 4631573Srgrimes struct who *a; 4641573Srgrimes 4651573Srgrimes a = whohead.who_next; 4661573Srgrimes while (a->who_next != NULL) { 4671573Srgrimes xprintf("%s/%s -> ", a->who_name, a->who_tty); 4681573Srgrimes a = a->who_next; 4691573Srgrimes } 4701573Srgrimes xprintf("TAIL\n"); 4718870Srgrimes if (a != &whotail) { 4721573Srgrimes xprintf(CGETS(26, 3, "BUG! last element is not whotail!\n")); 4731573Srgrimes abort(); 4741573Srgrimes } 4751573Srgrimes a = whotail.who_prev; 4761573Srgrimes xprintf(CGETS(26, 4, "backward: ")); 4771573Srgrimes while (a->who_prev != NULL) { 4781573Srgrimes xprintf("%s/%s -> ", a->who_name, a->who_tty); 4791573Srgrimes a = a->who_prev; 4801573Srgrimes } 4811573Srgrimes xprintf("HEAD\n"); 4821573Srgrimes if (a != &whohead) { 4831573Srgrimes xprintf(CGETS(26, 5, "BUG! first element is not whohead!\n")); 4841573Srgrimes abort(); 4851573Srgrimes } 4861573Srgrimes if (new) 48774469Sjlemon xprintf(CGETS(26, 6, "new: %s/%s\n"), new->who_name, new->who_tty); 4881573Srgrimes if (wp) 4891573Srgrimes xprintf("wp: %s/%s\n", wp->who_name, wp->who_tty); 4901573Srgrimes} 4918870Srgrimes#endif /* WHODEBUG */ 4921573Srgrimes 4931573Srgrimes 4941573Srgrimesstatic void 4951573Srgrimesprint_who(struct who *wp) 4968870Srgrimes{ 4978870Srgrimes#ifdef HAVE_STRUCT_UTMP_UT_HOST 4981573Srgrimes Char *cp = str2short(CGETS(26, 7, "%n has %a %l from %m.")); 4991573Srgrimes#else 50074469Sjlemon Char *cp = str2short(CGETS(26, 8, "%n has %a %l.")); 5018870Srgrimes#endif /* HAVE_STRUCT_UTMP_UT_HOST */ 5021573Srgrimes struct varent *vp = adrof(STRwho); 5031573Srgrimes Char *str; 5041573Srgrimes 5051573Srgrimes if (vp && vp->vec && vp->vec[0]) 5061573Srgrimes cp = vp->vec[0]; 5071573Srgrimes 5081573Srgrimes str = tprintf(FMT_WHO, cp, NULL, wp->who_time, wp); 5091573Srgrimes cleanup_push(str, xfree); 5101573Srgrimes for (cp = str; *cp;) 5111573Srgrimes xputwchar(*cp++); 5121573Srgrimes cleanup_until(str); 5131573Srgrimes xputchar('\n'); 5141573Srgrimes} /* end print_who */ 51574469Sjlemon 5161573Srgrimes 5171573Srgrimeschar * 51874469Sjlemonwho_info(ptr_t ptr, int c) 5191573Srgrimes{ 52074963Speter struct who *wp = ptr; 5211573Srgrimes char *wbuf; 5221573Srgrimes#ifdef HAVE_STRUCT_UTMP_UT_HOST 5231573Srgrimes char *wb; 5241573Srgrimes int flg; 52574963Speter char *pb; 52674963Speter#endif /* HAVE_STRUCT_UTMP_UT_HOST */ 5271573Srgrimes 5281573Srgrimes switch (c) { 5291573Srgrimes case 'n': /* user name */ 5301573Srgrimes switch (wp->who_status & STMASK) { 5311573Srgrimes case ONLINE: 5321573Srgrimes case CHANGED: 5331573Srgrimes return strsave(wp->who_new); 5341573Srgrimes case OFFLINE: 53574963Speter return strsave(wp->who_name); 53674963Speter default: 5371573Srgrimes break; 53874469Sjlemon } 5391573Srgrimes break; 5401573Srgrimes 5411573Srgrimes case 'a': 5421573Srgrimes switch (wp->who_status & STMASK) { 5431573Srgrimes case ONLINE: 5441573Srgrimes return strsave(CGETS(26, 9, "logged on")); 5451573Srgrimes case OFFLINE: 5461573Srgrimes return strsave(CGETS(26, 10, "logged off")); 5471573Srgrimes case CHANGED: 5481573Srgrimes return xasprintf(CGETS(26, 11, "replaced %s on"), wp->who_name); 5491573Srgrimes default: 5501573Srgrimes break; 5511573Srgrimes } 5521573Srgrimes break; 5538870Srgrimes 5541573Srgrimes#ifdef HAVE_STRUCT_UTMP_UT_HOST 5551573Srgrimes case 'm': 5561573Srgrimes if (wp->who_host[0] == '\0') 5571573Srgrimes return strsave(CGETS(26, 12, "local")); 5581573Srgrimes else { 55974963Speter pb = wp->who_host; 56074963Speter wbuf = xmalloc(strlen(pb) + 1); 5611573Srgrimes wb = wbuf; 5621573Srgrimes /* the ':' stuff is for <host>:<display>.<screen> */ 5631573Srgrimes for (flg = isdigit((unsigned char)*pb) ? '\0' : '.'; 5641573Srgrimes *pb != '\0' && (*pb != flg || ((pb = strchr(pb, ':')) != 0)); 56574469Sjlemon pb++) { 5661573Srgrimes if (*pb == ':') 5671573Srgrimes flg = '\0'; 5681573Srgrimes *wb++ = isupper((unsigned char)*pb) ? 5691573Srgrimes tolower((unsigned char)*pb) : *pb; 5701573Srgrimes } 5711573Srgrimes *wb = '\0'; 5721573Srgrimes return wbuf; 5731573Srgrimes } 57474963Speter 57574963Speter case 'M': 5761573Srgrimes if (wp->who_host[0] == '\0') 5771573Srgrimes return strsave(CGETS(26, 12, "local")); 5781573Srgrimes else { 5791573Srgrimes pb = wp->who_host; 5801573Srgrimes wbuf = xmalloc(strlen(pb) + 1); 5811573Srgrimes wb = wbuf; 58274963Speter for (; *pb != '\0'; pb++) 58374963Speter *wb++ = isupper((unsigned char)*pb) ? 58474963Speter tolower((unsigned char)*pb) : *pb; 5851573Srgrimes *wb = '\0'; 58674963Speter return wbuf; 5871573Srgrimes } 58874963Speter#endif /* HAVE_STRUCT_UTMP_UT_HOST */ 58974963Speter 5901573Srgrimes case 'l': 5911573Srgrimes return strsave(wp->who_tty); 5921573Srgrimes 5931573Srgrimes default: 5941573Srgrimes wbuf = xmalloc(3); 59574963Speter wbuf[0] = '%'; 59674963Speter wbuf[1] = (char) c; 5971573Srgrimes wbuf[2] = '\0'; 59874469Sjlemon return wbuf; 5991573Srgrimes } 60090045Sobrien return NULL; 6011573Srgrimes} 6021573Srgrimes 6031573Srgrimesvoid 6041573Srgrimes/*ARGSUSED*/ 6051573Srgrimesdolog(Char **v, struct command *c) 6061573Srgrimes{ 6071573Srgrimes struct who *wp; 6081573Srgrimes struct varent *vp; 6091573Srgrimes 6101573Srgrimes USE(v); 6111573Srgrimes USE(c); 6121573Srgrimes vp = adrof(STRwatch); /* lint insists vp isn't used unless we */ 61374963Speter if (vp == NULL) /* unless we assign it outside the if */ 61474963Speter stderror(ERR_NOWATCH); 6151573Srgrimes resetwatch(); 6161573Srgrimes wp = whohead.who_next; 6178870Srgrimes while (wp->who_next != NULL) { 6181573Srgrimes wp->who_name[0] = '\0'; 6191573Srgrimes wp = wp->who_next; 6201573Srgrimes } 62174921Speter} 62274918Speter 6231573Srgrimes# ifdef HAVE_STRUCT_UTMP_UT_HOST 6241573Srgrimessize_t 6251573Srgrimesutmphostsize(void) 6261573Srgrimes{ 6271573Srgrimes return UTHOSTLEN; 6281573Srgrimes} 6291573Srgrimes 6301573Srgrimeschar * 6311573Srgrimesutmphost(void) 6321573Srgrimes{ 6331573Srgrimes char *tty = short2str(varval(STRtty)); 6341573Srgrimes struct who *wp; 6351573Srgrimes char *host = NULL; 6361573Srgrimes 6371573Srgrimes watch_login(1); 63890045Sobrien 63990045Sobrien for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) { 6401573Srgrimes if (strcmp(tty, wp->who_tty) == 0) 6411573Srgrimes host = wp->who_host; 6421573Srgrimes wp->who_name[0] = '\0'; 6431573Srgrimes } 64474963Speter resetwatch(); 64574963Speter return host; 64674963Speter} 64774963Speter# endif /* HAVE_STRUCT_UTMP_UT_HOST */ 6481573Srgrimes 6491573Srgrimes#ifdef WINNT_NATIVE 6501573Srgrimesvoid add_to_who_list(name, mach_nm) 6511573Srgrimes char *name; 65274963Speter char *mach_nm; 65374963Speter{ 6541573Srgrimes 6551573Srgrimes struct who *wp, *wpnew; 6561573Srgrimes int comp = -1; 6571573Srgrimes 6581573Srgrimes wp = whohead.who_next; 6591573Srgrimes while (wp->who_next && (comp = strncmp(wp->who_tty,mach_nm,UTLINLEN)) < 0) 6601573Srgrimes wp = wp->who_next;/* find that tty! */ 6611573Srgrimes 6621573Srgrimes if (wp->who_next && comp == 0) { /* found the tty... */ 6631573Srgrimes 6641573Srgrimes if (*name == '\0') { 6651573Srgrimes wp->who_time = 0; 6661573Srgrimes wp->who_status = OFFLINE; 6671573Srgrimes } 6681573Srgrimes else if (strncmp(name, wp->who_name, UTNAMLEN) == 0) { 6691573Srgrimes /* someone is logged in */ 6701573Srgrimes wp->who_time = 0; 6711573Srgrimes wp->who_status = 0; /* same guy */ 6721573Srgrimes } 6731573Srgrimes else { 6741573Srgrimes (void) strncpy(wp->who_new, name, UTNAMLEN); 6751573Srgrimes wp->who_time = 0; 6761573Srgrimes if (wp->who_name[0] == '\0') 6771573Srgrimes wp->who_status = ONLINE; 6781573Srgrimes else 6791573Srgrimes wp->who_status = CHANGED; 6801573Srgrimes } 68174469Sjlemon } 6821573Srgrimes else { 6831573Srgrimes wpnew = xcalloc(1, sizeof *wpnew); 68474469Sjlemon (void) strncpy(wpnew->who_tty, mach_nm, UTLINLEN); 6851573Srgrimes wpnew->who_time = 0; 68690045Sobrien if (*name == '\0') 68790045Sobrien wpnew->who_status = OFFLINE; 68874918Speter else { 6891573Srgrimes (void) strncpy(wpnew->who_new, name, UTNAMLEN); 6901573Srgrimes wpnew->who_status = ONLINE; 6911573Srgrimes } 69280525Smikeh#ifdef WHODEBUG 69380525Smikeh debugwholist(wpnew, wp); 69480525Smikeh#endif /* WHODEBUG */ 69580525Smikeh 69674307Sjlemon wpnew->who_next = wp; /* link in a new 'who' */ 6971573Srgrimes wpnew->who_prev = wp->who_prev; 6988870Srgrimes wpnew->who_prev->who_next = wpnew; 6991573Srgrimes wp->who_prev = wpnew; /* linked in now */ 7001573Srgrimes } 70174918Speter} 70274918Speter#endif /* WINNT_NATIVE */ 70374918Speter#endif /* HAVENOUTMP */ 70474918Speter