1*19d2e3deSDmitry Chagin /* $Header: /p/tcsh/cvsroot/tcsh/tc.who.c,v 3.59 2012/11/15 02:55:08 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * tc.who.c: Watch logins and logouts... 4c80476e4SDavid E. O'Brien */ 5c80476e4SDavid E. O'Brien /*- 6c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 7c80476e4SDavid E. O'Brien * All rights reserved. 8c80476e4SDavid E. O'Brien * 9c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 10c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 11c80476e4SDavid E. O'Brien * are met: 12c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 13c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 14c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 16c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1729301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 18c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 19c80476e4SDavid E. O'Brien * without specific prior written permission. 20c80476e4SDavid E. O'Brien * 21c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c80476e4SDavid E. O'Brien * SUCH DAMAGE. 32c80476e4SDavid E. O'Brien */ 33c80476e4SDavid E. O'Brien #include "sh.h" 34c80476e4SDavid E. O'Brien 35*19d2e3deSDmitry Chagin RCSID("$tcsh: tc.who.c,v 3.59 2012/11/15 02:55:08 christos Exp $") 36c80476e4SDavid E. O'Brien 37c80476e4SDavid E. O'Brien #include "tc.h" 38c80476e4SDavid E. O'Brien 39c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP 40c80476e4SDavid E. O'Brien /* 41c80476e4SDavid E. O'Brien * kfk 26 Jan 1984 - for login watch functions. 42c80476e4SDavid E. O'Brien */ 43c80476e4SDavid E. O'Brien #include <ctype.h> 44c80476e4SDavid E. O'Brien 4523338178SMark Peek #ifdef HAVE_UTMPX_H 46c80476e4SDavid E. O'Brien # include <utmpx.h> 479ccc37e3SMark Peek # define UTNAMLEN sizeof(((struct utmpx *) 0)->ut_name) 489ccc37e3SMark Peek # define UTLINLEN sizeof(((struct utmpx *) 0)->ut_line) 499ccc37e3SMark Peek # ifdef HAVE_STRUCT_UTMPX_UT_HOST 509ccc37e3SMark Peek # define UTHOSTLEN sizeof(((struct utmpx *) 0)->ut_host) 519ccc37e3SMark Peek # endif 52c80476e4SDavid E. O'Brien /* I just redefine a few words here. Changing every occurrence below 53c80476e4SDavid E. O'Brien * seems like too much of work. All UTMP functions have equivalent 54c80476e4SDavid E. O'Brien * UTMPX counterparts, so they can be added all here when needed. 55c80476e4SDavid E. O'Brien * Kimmo Suominen, Oct 14 1991 56c80476e4SDavid E. O'Brien */ 573b6eaa7bSAndrey A. Chernov # if defined(__UTMPX_FILE) && !defined(UTMPX_FILE) 5823338178SMark Peek # define TCSH_PATH_UTMP __UTMPX_FILE 59b2d5d167SMark Peek # elif defined(_PATH_UTMPX) 6023338178SMark Peek # define TCSH_PATH_UTMP _PATH_UTMPX 6123338178SMark Peek # elif defined(UTMPX_FILE) 6223338178SMark Peek # define TCSH_PATH_UTMP UTMPX_FILE 639ccc37e3SMark Peek # elif __FreeBSD_version >= 900000 649ccc37e3SMark Peek # /* Why isn't this defined somewhere? */ 659ccc37e3SMark Peek # define TCSH_PATH_UTMP "/var/run/utx.active" 669ccc37e3SMark Peek # elif defined(__hpux) 679ccc37e3SMark Peek # define TCSH_PATH_UTMP "/etc/utmpx" 68*19d2e3deSDmitry Chagin # elif defined(IBMAIX) && defined(UTMP_FILE) 69*19d2e3deSDmitry Chagin # define TCSH_PATH_UTMP UTMP_FILE 709ccc37e3SMark Peek # endif 719ccc37e3SMark Peek # if defined(TCSH_PATH_UTMP) || !defined(HAVE_UTMP_H) 72c80476e4SDavid E. O'Brien # define utmp utmpx 739ccc37e3SMark Peek # define TCSH_USE_UTMPX 749ccc37e3SMark Peek # if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT) 759ccc37e3SMark Peek # define getutent getutxent 769ccc37e3SMark Peek # define setutent setutxent 779ccc37e3SMark Peek # define endutent endutxent 789ccc37e3SMark Peek # endif /* HAVE_GETUTENT || HAVE_GETUTXENT */ 799ccc37e3SMark Peek # if defined(HAVE_STRUCT_UTMPX_UT_TV) 809ccc37e3SMark Peek # define ut_time ut_tv.tv_sec 819ccc37e3SMark Peek # elif defined(HAVE_STRUCT_UTMPX_UT_XTIME) 829ccc37e3SMark Peek # define ut_time ut_xtime 839ccc37e3SMark Peek # endif 849ccc37e3SMark Peek # if defined(HAVE_STRUCT_UTMPX_UT_USER) 859ccc37e3SMark Peek # define ut_name ut_user 869ccc37e3SMark Peek # endif 879ccc37e3SMark Peek # endif /* TCSH_PATH_UTMP || !HAVE_UTMP_H */ 889ccc37e3SMark Peek #endif /* HAVE_UTMPX_H */ 899ccc37e3SMark Peek 909ccc37e3SMark Peek #if !defined(TCSH_USE_UTMPX) && defined(HAVE_UTMP_H) 919ccc37e3SMark Peek # include <utmp.h> 9223338178SMark Peek # if defined(HAVE_STRUCT_UTMP_UT_TV) 933b6eaa7bSAndrey A. Chernov # define ut_time ut_tv.tv_sec 9423338178SMark Peek # elif defined(HAVE_STRUCT_UTMP_UT_XTIME) 95c80476e4SDavid E. O'Brien # define ut_time ut_xtime 9623338178SMark Peek # endif 979ccc37e3SMark Peek # if defined(HAVE_STRUCT_UTMP_UT_USER) 9823338178SMark Peek # define ut_name ut_user 9923338178SMark Peek # endif 100c80476e4SDavid E. O'Brien # ifndef BROKEN_CC 101c80476e4SDavid E. O'Brien # define UTNAMLEN sizeof(((struct utmp *) 0)->ut_name) 102c80476e4SDavid E. O'Brien # define UTLINLEN sizeof(((struct utmp *) 0)->ut_line) 10323338178SMark Peek # ifdef HAVE_STRUCT_UTMP_UT_HOST 104c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 105c80476e4SDavid E. O'Brien # define UTHOSTLEN 100 106c80476e4SDavid E. O'Brien # else 107c80476e4SDavid E. O'Brien # define UTHOSTLEN sizeof(((struct utmp *) 0)->ut_host) 108c80476e4SDavid E. O'Brien # endif 10923338178SMark Peek # endif /* HAVE_STRUCT_UTMP_UT_HOST */ 110c80476e4SDavid E. O'Brien # else 111c80476e4SDavid E. O'Brien /* give poor cc a little help if it needs it */ 112c80476e4SDavid E. O'Brien struct utmp __ut; 113c80476e4SDavid E. O'Brien # define UTNAMLEN sizeof(__ut.ut_name) 114c80476e4SDavid E. O'Brien # define UTLINLEN sizeof(__ut.ut_line) 11523338178SMark Peek # ifdef HAVE_STRUCT_UTMP_UT_HOST 116c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 117c80476e4SDavid E. O'Brien # define UTHOSTLEN 100 118c80476e4SDavid E. O'Brien # else 119c80476e4SDavid E. O'Brien # define UTHOSTLEN sizeof(__ut.ut_host) 120c80476e4SDavid E. O'Brien # endif 12123338178SMark Peek # endif /* HAVE_STRUCT_UTMP_UT_HOST */ 122c80476e4SDavid E. O'Brien # endif /* BROKEN_CC */ 12323338178SMark Peek # ifndef TCSH_PATH_UTMP 124c80476e4SDavid E. O'Brien # ifdef UTMP_FILE 12523338178SMark Peek # define TCSH_PATH_UTMP UTMP_FILE 12623338178SMark Peek # elif defined(_PATH_UTMP) 12723338178SMark Peek # define TCSH_PATH_UTMP _PATH_UTMP 128c80476e4SDavid E. O'Brien # else 12923338178SMark Peek # define TCSH_PATH_UTMP "/etc/utmp" 130c80476e4SDavid E. O'Brien # endif /* UTMP_FILE */ 13123338178SMark Peek # endif /* TCSH_PATH_UTMP */ 1329ccc37e3SMark Peek #endif /* !TCSH_USE_UTMPX && HAVE_UTMP_H */ 133c80476e4SDavid E. O'Brien 1349ccc37e3SMark Peek #ifndef UTNAMLEN 1359ccc37e3SMark Peek #define UTNAMLEN 64 1369ccc37e3SMark Peek #endif 1379ccc37e3SMark Peek #ifndef UTLINLEN 1389ccc37e3SMark Peek #define UTLINLEN 64 1399ccc37e3SMark Peek #endif 140c80476e4SDavid E. O'Brien 141c80476e4SDavid E. O'Brien struct who { 142c80476e4SDavid E. O'Brien struct who *who_next; 143c80476e4SDavid E. O'Brien struct who *who_prev; 144c80476e4SDavid E. O'Brien char who_name[UTNAMLEN + 1]; 145c80476e4SDavid E. O'Brien char who_new[UTNAMLEN + 1]; 146c80476e4SDavid E. O'Brien char who_tty[UTLINLEN + 1]; 1479ccc37e3SMark Peek #ifdef UTHOSTLEN 148c80476e4SDavid E. O'Brien char who_host[UTHOSTLEN + 1]; 1499ccc37e3SMark Peek #endif /* UTHOSTLEN */ 150c80476e4SDavid E. O'Brien time_t who_time; 151c80476e4SDavid E. O'Brien int who_status; 152c80476e4SDavid E. O'Brien }; 153c80476e4SDavid E. O'Brien 154c80476e4SDavid E. O'Brien static struct who whohead, whotail; 155c80476e4SDavid E. O'Brien static time_t watch_period = 0; 156c80476e4SDavid E. O'Brien static time_t stlast = 0; 157c80476e4SDavid E. O'Brien #ifdef WHODEBUG 15845e5710bSMark Peek static void debugwholist (struct who *, struct who *); 159c80476e4SDavid E. O'Brien #endif 16045e5710bSMark Peek static void print_who (struct who *); 161c80476e4SDavid E. O'Brien 162c80476e4SDavid E. O'Brien 163c80476e4SDavid E. O'Brien #define ONLINE 01 164c80476e4SDavid E. O'Brien #define OFFLINE 02 165c80476e4SDavid E. O'Brien #define CHANGED 04 166c80476e4SDavid E. O'Brien #define STMASK 07 167c80476e4SDavid E. O'Brien #define ANNOUNCE 010 16845e5710bSMark Peek #define CLEARED 020 169c80476e4SDavid E. O'Brien 170c80476e4SDavid E. O'Brien /* 171c80476e4SDavid E. O'Brien * Karl Kleinpaste, 26 Jan 1984. 172c80476e4SDavid E. O'Brien * Initialize the dummy tty list for login watch. 173c80476e4SDavid E. O'Brien * This dummy list eliminates boundary conditions 174c80476e4SDavid E. O'Brien * when doing pointer-chase searches. 175c80476e4SDavid E. O'Brien */ 176c80476e4SDavid E. O'Brien void 17745e5710bSMark Peek initwatch(void) 178c80476e4SDavid E. O'Brien { 179c80476e4SDavid E. O'Brien whohead.who_next = &whotail; 180c80476e4SDavid E. O'Brien whotail.who_prev = &whohead; 181c80476e4SDavid E. O'Brien stlast = 1; 182c80476e4SDavid E. O'Brien #ifdef WHODEBUG 183c80476e4SDavid E. O'Brien debugwholist(NULL, NULL); 184c80476e4SDavid E. O'Brien #endif /* WHODEBUG */ 185c80476e4SDavid E. O'Brien } 186c80476e4SDavid E. O'Brien 187c80476e4SDavid E. O'Brien void 18845e5710bSMark Peek resetwatch(void) 189c80476e4SDavid E. O'Brien { 190c80476e4SDavid E. O'Brien watch_period = 0; 191c80476e4SDavid E. O'Brien stlast = 0; 192c80476e4SDavid E. O'Brien } 193c80476e4SDavid E. O'Brien 194c80476e4SDavid E. O'Brien /* 195c80476e4SDavid E. O'Brien * Karl Kleinpaste, 26 Jan 1984. 196c80476e4SDavid E. O'Brien * Watch /etc/utmp for login/logout changes. 197c80476e4SDavid E. O'Brien */ 198c80476e4SDavid E. O'Brien void 19945e5710bSMark Peek watch_login(int force) 200c80476e4SDavid E. O'Brien { 20123338178SMark Peek int comp = -1, alldone; 202c80476e4SDavid E. O'Brien int firsttime = stlast == 1; 2039ccc37e3SMark Peek #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT) 20423338178SMark Peek struct utmp *uptr; 20523338178SMark Peek #else 20623338178SMark Peek int utmpfd; 20723338178SMark Peek #endif 208c80476e4SDavid E. O'Brien struct utmp utmp; 209c80476e4SDavid E. O'Brien struct who *wp, *wpnew; 210c80476e4SDavid E. O'Brien struct varent *v; 211c80476e4SDavid E. O'Brien Char **vp = NULL; 212c80476e4SDavid E. O'Brien time_t t, interval = MAILINTVL; 213c80476e4SDavid E. O'Brien struct stat sta; 21423338178SMark Peek #if defined(HAVE_STRUCT_UTMP_UT_HOST) && defined(_SEQUENT_) 215c80476e4SDavid E. O'Brien char *host, *ut_find_host(); 216c80476e4SDavid E. O'Brien #endif 2173b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 218c80476e4SDavid E. O'Brien static int ncbs_posted = 0; 219c80476e4SDavid E. O'Brien USE(utmp); 220c80476e4SDavid E. O'Brien USE(utmpfd); 221c80476e4SDavid E. O'Brien USE(sta); 222c80476e4SDavid E. O'Brien USE(wpnew); 2233b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 224c80476e4SDavid E. O'Brien 225c80476e4SDavid E. O'Brien /* stop SIGINT, lest our login list get trashed. */ 22645e5710bSMark Peek pintr_disabled++; 22745e5710bSMark Peek cleanup_push(&pintr_disabled, disabled_cleanup); 228c80476e4SDavid E. O'Brien 229c80476e4SDavid E. O'Brien v = adrof(STRwatch); 23029301572SMark Peek if ((v == NULL || v->vec == NULL) && !force) { 23145e5710bSMark Peek cleanup_until(&pintr_disabled); 232c80476e4SDavid E. O'Brien return; /* no names to watch */ 233c80476e4SDavid E. O'Brien } 234c80476e4SDavid E. O'Brien if (!force) { 235c80476e4SDavid E. O'Brien trim(vp = v->vec); 236c80476e4SDavid E. O'Brien if (blklen(vp) % 2) /* odd # args: 1st == # minutes. */ 237c80476e4SDavid E. O'Brien interval = (number(*vp)) ? (getn(*vp++) * 60) : MAILINTVL; 238c80476e4SDavid E. O'Brien } 239c80476e4SDavid E. O'Brien else 240c80476e4SDavid E. O'Brien interval = 0; 241c80476e4SDavid E. O'Brien 242c80476e4SDavid E. O'Brien (void) time(&t); 2433b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 244c80476e4SDavid E. O'Brien /* 245c80476e4SDavid E. O'Brien * Since NCB_ASTATs take time, start em async at least 90 secs 246c80476e4SDavid E. O'Brien * before we are due -amol 6/5/97 247c80476e4SDavid E. O'Brien */ 248c80476e4SDavid E. O'Brien if (!ncbs_posted) { 24945e5710bSMark Peek time_t tdiff = t - watch_period; 250c80476e4SDavid E. O'Brien if (!watch_period || ((tdiff > 0) && (tdiff > (interval - 90)))) { 251c80476e4SDavid E. O'Brien start_ncbs(vp); 252c80476e4SDavid E. O'Brien ncbs_posted = 1; 253c80476e4SDavid E. O'Brien } 254c80476e4SDavid E. O'Brien } 2553b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 256c80476e4SDavid E. O'Brien if (t - watch_period < interval) { 25745e5710bSMark Peek cleanup_until(&pintr_disabled); 258c80476e4SDavid E. O'Brien return; /* not long enough yet... */ 259c80476e4SDavid E. O'Brien } 260c80476e4SDavid E. O'Brien watch_period = t; 2613b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 262c80476e4SDavid E. O'Brien ncbs_posted = 0; 2633b6eaa7bSAndrey A. Chernov #else /* !WINNT_NATIVE */ 264c80476e4SDavid E. O'Brien 265c80476e4SDavid E. O'Brien /* 266c80476e4SDavid E. O'Brien * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 267c80476e4SDavid E. O'Brien * Don't open utmp all the time, stat it first... 268c80476e4SDavid E. O'Brien */ 26923338178SMark Peek if (stat(TCSH_PATH_UTMP, &sta)) { 270dc86a98eSDavid E. O'Brien if (!force) 271dc86a98eSDavid E. O'Brien xprintf(CGETS(26, 1, 272dc86a98eSDavid E. O'Brien "cannot stat %s. Please \"unset watch\".\n"), 27323338178SMark Peek TCSH_PATH_UTMP); 27445e5710bSMark Peek cleanup_until(&pintr_disabled); 275c80476e4SDavid E. O'Brien return; 276c80476e4SDavid E. O'Brien } 277c80476e4SDavid E. O'Brien if (stlast == sta.st_mtime) { 27845e5710bSMark Peek cleanup_until(&pintr_disabled); 279c80476e4SDavid E. O'Brien return; 280c80476e4SDavid E. O'Brien } 281c80476e4SDavid E. O'Brien stlast = sta.st_mtime; 2829ccc37e3SMark Peek #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT) 28323338178SMark Peek setutent(); 28423338178SMark Peek #else 28545e5710bSMark Peek if ((utmpfd = xopen(TCSH_PATH_UTMP, O_RDONLY|O_LARGEFILE)) < 0) { 286dc86a98eSDavid E. O'Brien if (!force) 287dc86a98eSDavid E. O'Brien xprintf(CGETS(26, 2, 288dc86a98eSDavid E. O'Brien "%s cannot be opened. Please \"unset watch\".\n"), 28923338178SMark Peek TCSH_PATH_UTMP); 29045e5710bSMark Peek cleanup_until(&pintr_disabled); 291c80476e4SDavid E. O'Brien return; 292c80476e4SDavid E. O'Brien } 29345e5710bSMark Peek cleanup_push(&utmpfd, open_cleanup); 29423338178SMark Peek #endif 295c80476e4SDavid E. O'Brien 296c80476e4SDavid E. O'Brien /* 297c80476e4SDavid E. O'Brien * xterm clears the entire utmp entry - mark everyone on the status list 298c80476e4SDavid E. O'Brien * OFFLINE or we won't notice X "logouts" 299c80476e4SDavid E. O'Brien */ 30045e5710bSMark Peek for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) 30145e5710bSMark Peek wp->who_status = OFFLINE | CLEARED; 302c80476e4SDavid E. O'Brien 303c80476e4SDavid E. O'Brien /* 304c80476e4SDavid E. O'Brien * Read in the utmp file, sort the entries, and update existing entries or 305c80476e4SDavid E. O'Brien * add new entries to the status list. 306c80476e4SDavid E. O'Brien */ 3079ccc37e3SMark Peek #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT) 30823338178SMark Peek while ((uptr = getutent()) != NULL) { 30923338178SMark Peek memcpy(&utmp, uptr, sizeof (utmp)); 31023338178SMark Peek #else 31145e5710bSMark Peek while (xread(utmpfd, &utmp, sizeof utmp) == sizeof utmp) { 31223338178SMark Peek #endif 313c80476e4SDavid E. O'Brien 314c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 315c80476e4SDavid E. O'Brien # ifndef IRIS4D 316c80476e4SDavid E. O'Brien if (utmp.ut_type != USER_PROCESS) 317c80476e4SDavid E. O'Brien continue; 318c80476e4SDavid E. O'Brien # else 319c80476e4SDavid E. O'Brien /* Why is that? Cause the utmp file is always corrupted??? */ 320c80476e4SDavid E. O'Brien if (utmp.ut_type != USER_PROCESS && utmp.ut_type != DEAD_PROCESS) 321c80476e4SDavid E. O'Brien continue; 322c80476e4SDavid E. O'Brien # endif /* IRIS4D */ 323c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 324c80476e4SDavid E. O'Brien 325c80476e4SDavid E. O'Brien if (utmp.ut_name[0] == '\0' && utmp.ut_line[0] == '\0') 326c80476e4SDavid E. O'Brien continue; /* completely void entry */ 327c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 328c80476e4SDavid E. O'Brien if (utmp.ut_type == DEAD_PROCESS && utmp.ut_line[0] == '\0') 329c80476e4SDavid E. O'Brien continue; 330c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 331c80476e4SDavid E. O'Brien wp = whohead.who_next; 332c80476e4SDavid E. O'Brien while (wp->who_next && (comp = strncmp(wp->who_tty, utmp.ut_line, UTLINLEN)) < 0) 333c80476e4SDavid E. O'Brien wp = wp->who_next;/* find that tty! */ 334c80476e4SDavid E. O'Brien 335c80476e4SDavid E. O'Brien if (wp->who_next && comp == 0) { /* found the tty... */ 33645e5710bSMark Peek if (utmp.ut_time < wp->who_time) 33745e5710bSMark Peek continue; 338c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 339c80476e4SDavid E. O'Brien if (utmp.ut_type == DEAD_PROCESS) { 340c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 341c80476e4SDavid E. O'Brien wp->who_status = OFFLINE; 342c80476e4SDavid E. O'Brien } 343c80476e4SDavid E. O'Brien else 344c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 345c80476e4SDavid E. O'Brien if (utmp.ut_name[0] == '\0') { 346c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 347c80476e4SDavid E. O'Brien wp->who_status = OFFLINE; 348c80476e4SDavid E. O'Brien } 349c80476e4SDavid E. O'Brien else if (strncmp(utmp.ut_name, wp->who_name, UTNAMLEN) == 0) { 350c80476e4SDavid E. O'Brien /* someone is logged in */ 351c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 35245e5710bSMark Peek wp->who_status = ONLINE | ANNOUNCE; /* same guy */ 353c80476e4SDavid E. O'Brien } 354c80476e4SDavid E. O'Brien else { 355c80476e4SDavid E. O'Brien (void) strncpy(wp->who_new, utmp.ut_name, UTNAMLEN); 3569ccc37e3SMark Peek # ifdef UTHOSTLEN 357c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 358c80476e4SDavid E. O'Brien host = ut_find_host(wp->who_tty); 359c80476e4SDavid E. O'Brien if (host) 360c80476e4SDavid E. O'Brien (void) strncpy(wp->who_host, host, UTHOSTLEN); 361c80476e4SDavid E. O'Brien else 362c80476e4SDavid E. O'Brien wp->who_host[0] = 0; 363c80476e4SDavid E. O'Brien # else 364c80476e4SDavid E. O'Brien (void) strncpy(wp->who_host, utmp.ut_host, UTHOSTLEN); 365c80476e4SDavid E. O'Brien # endif 3669ccc37e3SMark Peek # endif /* UTHOSTLEN */ 367c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 368c80476e4SDavid E. O'Brien if (wp->who_name[0] == '\0') 369c80476e4SDavid E. O'Brien wp->who_status = ONLINE; 370c80476e4SDavid E. O'Brien else 371c80476e4SDavid E. O'Brien wp->who_status = CHANGED; 372c80476e4SDavid E. O'Brien } 373c80476e4SDavid E. O'Brien } 374c80476e4SDavid E. O'Brien else { /* new tty in utmp */ 37545e5710bSMark Peek wpnew = xcalloc(1, sizeof *wpnew); 376c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_tty, utmp.ut_line, UTLINLEN); 3779ccc37e3SMark Peek # ifdef UTHOSTLEN 378c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 379c80476e4SDavid E. O'Brien host = ut_find_host(wpnew->who_tty); 380c80476e4SDavid E. O'Brien if (host) 381c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_host, host, UTHOSTLEN); 382c80476e4SDavid E. O'Brien else 383c80476e4SDavid E. O'Brien wpnew->who_host[0] = 0; 384c80476e4SDavid E. O'Brien # else 385c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_host, utmp.ut_host, UTHOSTLEN); 386c80476e4SDavid E. O'Brien # endif 3879ccc37e3SMark Peek # endif /* UTHOSTLEN */ 388c80476e4SDavid E. O'Brien wpnew->who_time = utmp.ut_time; 389c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 390c80476e4SDavid E. O'Brien if (utmp.ut_type == DEAD_PROCESS) 391c80476e4SDavid E. O'Brien wpnew->who_status = OFFLINE; 392c80476e4SDavid E. O'Brien else 393c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 394c80476e4SDavid E. O'Brien if (utmp.ut_name[0] == '\0') 395c80476e4SDavid E. O'Brien wpnew->who_status = OFFLINE; 396c80476e4SDavid E. O'Brien else { 397c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_new, utmp.ut_name, UTNAMLEN); 398c80476e4SDavid E. O'Brien wpnew->who_status = ONLINE; 399c80476e4SDavid E. O'Brien } 400c80476e4SDavid E. O'Brien # ifdef WHODEBUG 401c80476e4SDavid E. O'Brien debugwholist(wpnew, wp); 402c80476e4SDavid E. O'Brien # endif /* WHODEBUG */ 403c80476e4SDavid E. O'Brien 404c80476e4SDavid E. O'Brien wpnew->who_next = wp; /* link in a new 'who' */ 405c80476e4SDavid E. O'Brien wpnew->who_prev = wp->who_prev; 406c80476e4SDavid E. O'Brien wpnew->who_prev->who_next = wpnew; 407c80476e4SDavid E. O'Brien wp->who_prev = wpnew; /* linked in now */ 408c80476e4SDavid E. O'Brien } 409c80476e4SDavid E. O'Brien } 4109ccc37e3SMark Peek #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT) 41123338178SMark Peek endutent(); 41223338178SMark Peek #else 41345e5710bSMark Peek cleanup_until(&utmpfd); 41423338178SMark Peek #endif 4153b6eaa7bSAndrey A. Chernov #endif /* !WINNT_NATIVE */ 416c80476e4SDavid E. O'Brien 41745e5710bSMark Peek if (force || vp == NULL) { 41845e5710bSMark Peek cleanup_until(&pintr_disabled); 419c80476e4SDavid E. O'Brien return; 42045e5710bSMark Peek } 421c80476e4SDavid E. O'Brien 422c80476e4SDavid E. O'Brien /* 423c80476e4SDavid E. O'Brien * The state of all logins is now known, so we can search the user's list 424c80476e4SDavid E. O'Brien * of watchables to print the interesting ones. 425c80476e4SDavid E. O'Brien */ 426c80476e4SDavid E. O'Brien for (alldone = 0; !alldone && *vp != NULL && **vp != '\0' && 427c80476e4SDavid E. O'Brien *(vp + 1) != NULL && **(vp + 1) != '\0'; 428c80476e4SDavid E. O'Brien vp += 2) { /* args used in pairs... */ 429c80476e4SDavid E. O'Brien 430c80476e4SDavid E. O'Brien if (eq(*vp, STRany) && eq(*(vp + 1), STRany)) 431c80476e4SDavid E. O'Brien alldone = 1; 432c80476e4SDavid E. O'Brien 433c80476e4SDavid E. O'Brien for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) { 434c80476e4SDavid E. O'Brien if (wp->who_status & ANNOUNCE || 435c80476e4SDavid E. O'Brien (!eq(STRany, vp[0]) && 436c80476e4SDavid E. O'Brien !Gmatch(str2short(wp->who_name), vp[0]) && 437c80476e4SDavid E. O'Brien !Gmatch(str2short(wp->who_new), vp[0])) || 438c80476e4SDavid E. O'Brien (!Gmatch(str2short(wp->who_tty), vp[1]) && 439c80476e4SDavid E. O'Brien !eq(STRany, vp[1]))) 440c80476e4SDavid E. O'Brien continue; /* entry doesn't qualify */ 441c80476e4SDavid E. O'Brien /* already printed or not right one to print */ 442c80476e4SDavid E. O'Brien 443c80476e4SDavid E. O'Brien 44445e5710bSMark Peek if (wp->who_status & CLEARED) {/* utmp entry was cleared */ 445c80476e4SDavid E. O'Brien wp->who_time = watch_period; 44645e5710bSMark Peek wp->who_status &= ~CLEARED; 44745e5710bSMark Peek } 448c80476e4SDavid E. O'Brien 449c80476e4SDavid E. O'Brien if ((wp->who_status & OFFLINE) && 450c80476e4SDavid E. O'Brien (wp->who_name[0] != '\0')) { 451c80476e4SDavid E. O'Brien if (!firsttime) 452c80476e4SDavid E. O'Brien print_who(wp); 453c80476e4SDavid E. O'Brien wp->who_name[0] = '\0'; 454c80476e4SDavid E. O'Brien wp->who_status |= ANNOUNCE; 455c80476e4SDavid E. O'Brien continue; 456c80476e4SDavid E. O'Brien } 457c80476e4SDavid E. O'Brien if (wp->who_status & ONLINE) { 458c80476e4SDavid E. O'Brien if (!firsttime) 459c80476e4SDavid E. O'Brien print_who(wp); 460c80476e4SDavid E. O'Brien (void) strcpy(wp->who_name, wp->who_new); 461c80476e4SDavid E. O'Brien wp->who_status |= ANNOUNCE; 462c80476e4SDavid E. O'Brien continue; 463c80476e4SDavid E. O'Brien } 464c80476e4SDavid E. O'Brien if (wp->who_status & CHANGED) { 465c80476e4SDavid E. O'Brien if (!firsttime) 466c80476e4SDavid E. O'Brien print_who(wp); 467c80476e4SDavid E. O'Brien (void) strcpy(wp->who_name, wp->who_new); 468c80476e4SDavid E. O'Brien wp->who_status |= ANNOUNCE; 469c80476e4SDavid E. O'Brien continue; 470c80476e4SDavid E. O'Brien } 471c80476e4SDavid E. O'Brien } 472c80476e4SDavid E. O'Brien } 47345e5710bSMark Peek cleanup_until(&pintr_disabled); 474c80476e4SDavid E. O'Brien } 475c80476e4SDavid E. O'Brien 476c80476e4SDavid E. O'Brien #ifdef WHODEBUG 477c80476e4SDavid E. O'Brien static void 47845e5710bSMark Peek debugwholist(struct who *new, struct who *wp) 479c80476e4SDavid E. O'Brien { 48023338178SMark Peek struct who *a; 481c80476e4SDavid E. O'Brien 482c80476e4SDavid E. O'Brien a = whohead.who_next; 483c80476e4SDavid E. O'Brien while (a->who_next != NULL) { 484c80476e4SDavid E. O'Brien xprintf("%s/%s -> ", a->who_name, a->who_tty); 485c80476e4SDavid E. O'Brien a = a->who_next; 486c80476e4SDavid E. O'Brien } 487c80476e4SDavid E. O'Brien xprintf("TAIL\n"); 488c80476e4SDavid E. O'Brien if (a != &whotail) { 489c80476e4SDavid E. O'Brien xprintf(CGETS(26, 3, "BUG! last element is not whotail!\n")); 490c80476e4SDavid E. O'Brien abort(); 491c80476e4SDavid E. O'Brien } 492c80476e4SDavid E. O'Brien a = whotail.who_prev; 493c80476e4SDavid E. O'Brien xprintf(CGETS(26, 4, "backward: ")); 494c80476e4SDavid E. O'Brien while (a->who_prev != NULL) { 495c80476e4SDavid E. O'Brien xprintf("%s/%s -> ", a->who_name, a->who_tty); 496c80476e4SDavid E. O'Brien a = a->who_prev; 497c80476e4SDavid E. O'Brien } 498c80476e4SDavid E. O'Brien xprintf("HEAD\n"); 499c80476e4SDavid E. O'Brien if (a != &whohead) { 500c80476e4SDavid E. O'Brien xprintf(CGETS(26, 5, "BUG! first element is not whohead!\n")); 501c80476e4SDavid E. O'Brien abort(); 502c80476e4SDavid E. O'Brien } 503c80476e4SDavid E. O'Brien if (new) 504c80476e4SDavid E. O'Brien xprintf(CGETS(26, 6, "new: %s/%s\n"), new->who_name, new->who_tty); 505c80476e4SDavid E. O'Brien if (wp) 506c80476e4SDavid E. O'Brien xprintf("wp: %s/%s\n", wp->who_name, wp->who_tty); 507c80476e4SDavid E. O'Brien } 508c80476e4SDavid E. O'Brien #endif /* WHODEBUG */ 509c80476e4SDavid E. O'Brien 510c80476e4SDavid E. O'Brien 511c80476e4SDavid E. O'Brien static void 51245e5710bSMark Peek print_who(struct who *wp) 513c80476e4SDavid E. O'Brien { 5149ccc37e3SMark Peek #ifdef UTHOSTLEN 515c80476e4SDavid E. O'Brien Char *cp = str2short(CGETS(26, 7, "%n has %a %l from %m.")); 516c80476e4SDavid E. O'Brien #else 517c80476e4SDavid E. O'Brien Char *cp = str2short(CGETS(26, 8, "%n has %a %l.")); 5189ccc37e3SMark Peek #endif /* UTHOSTLEN */ 519c80476e4SDavid E. O'Brien struct varent *vp = adrof(STRwho); 52045e5710bSMark Peek Char *str; 521c80476e4SDavid E. O'Brien 52229301572SMark Peek if (vp && vp->vec && vp->vec[0]) 523c80476e4SDavid E. O'Brien cp = vp->vec[0]; 524c80476e4SDavid E. O'Brien 52545e5710bSMark Peek str = tprintf(FMT_WHO, cp, NULL, wp->who_time, wp); 52645e5710bSMark Peek cleanup_push(str, xfree); 52745e5710bSMark Peek for (cp = str; *cp;) 52823338178SMark Peek xputwchar(*cp++); 52945e5710bSMark Peek cleanup_until(str); 530c80476e4SDavid E. O'Brien xputchar('\n'); 531c80476e4SDavid E. O'Brien } /* end print_who */ 532c80476e4SDavid E. O'Brien 533c80476e4SDavid E. O'Brien 53445e5710bSMark Peek char * 53545e5710bSMark Peek who_info(ptr_t ptr, int c) 536c80476e4SDavid E. O'Brien { 53745e5710bSMark Peek struct who *wp = ptr; 53845e5710bSMark Peek char *wbuf; 5399ccc37e3SMark Peek #ifdef UTHOSTLEN 54045e5710bSMark Peek char *wb; 541c80476e4SDavid E. O'Brien int flg; 542c80476e4SDavid E. O'Brien char *pb; 5439ccc37e3SMark Peek #endif /* UTHOSTLEN */ 544c80476e4SDavid E. O'Brien 545c80476e4SDavid E. O'Brien switch (c) { 546c80476e4SDavid E. O'Brien case 'n': /* user name */ 547c80476e4SDavid E. O'Brien switch (wp->who_status & STMASK) { 548c80476e4SDavid E. O'Brien case ONLINE: 549c80476e4SDavid E. O'Brien case CHANGED: 55045e5710bSMark Peek return strsave(wp->who_new); 551c80476e4SDavid E. O'Brien case OFFLINE: 55245e5710bSMark Peek return strsave(wp->who_name); 553c80476e4SDavid E. O'Brien default: 554c80476e4SDavid E. O'Brien break; 555c80476e4SDavid E. O'Brien } 556c80476e4SDavid E. O'Brien break; 557c80476e4SDavid E. O'Brien 558c80476e4SDavid E. O'Brien case 'a': 559c80476e4SDavid E. O'Brien switch (wp->who_status & STMASK) { 560c80476e4SDavid E. O'Brien case ONLINE: 56145e5710bSMark Peek return strsave(CGETS(26, 9, "logged on")); 562c80476e4SDavid E. O'Brien case OFFLINE: 56345e5710bSMark Peek return strsave(CGETS(26, 10, "logged off")); 564c80476e4SDavid E. O'Brien case CHANGED: 56545e5710bSMark Peek return xasprintf(CGETS(26, 11, "replaced %s on"), wp->who_name); 566c80476e4SDavid E. O'Brien default: 567c80476e4SDavid E. O'Brien break; 568c80476e4SDavid E. O'Brien } 569c80476e4SDavid E. O'Brien break; 570c80476e4SDavid E. O'Brien 5719ccc37e3SMark Peek #ifdef UTHOSTLEN 572c80476e4SDavid E. O'Brien case 'm': 573c80476e4SDavid E. O'Brien if (wp->who_host[0] == '\0') 57445e5710bSMark Peek return strsave(CGETS(26, 12, "local")); 575c80476e4SDavid E. O'Brien else { 57645e5710bSMark Peek pb = wp->who_host; 57745e5710bSMark Peek wbuf = xmalloc(strlen(pb) + 1); 57845e5710bSMark Peek wb = wbuf; 579c80476e4SDavid E. O'Brien /* the ':' stuff is for <host>:<display>.<screen> */ 58045e5710bSMark Peek for (flg = isdigit((unsigned char)*pb) ? '\0' : '.'; 58123338178SMark Peek *pb != '\0' && (*pb != flg || ((pb = strchr(pb, ':')) != 0)); 582c80476e4SDavid E. O'Brien pb++) { 583c80476e4SDavid E. O'Brien if (*pb == ':') 584c80476e4SDavid E. O'Brien flg = '\0'; 58523338178SMark Peek *wb++ = isupper((unsigned char)*pb) ? 58623338178SMark Peek tolower((unsigned char)*pb) : *pb; 587c80476e4SDavid E. O'Brien } 588c80476e4SDavid E. O'Brien *wb = '\0'; 589c80476e4SDavid E. O'Brien return wbuf; 590c80476e4SDavid E. O'Brien } 591c80476e4SDavid E. O'Brien 592c80476e4SDavid E. O'Brien case 'M': 593c80476e4SDavid E. O'Brien if (wp->who_host[0] == '\0') 59445e5710bSMark Peek return strsave(CGETS(26, 12, "local")); 595c80476e4SDavid E. O'Brien else { 59645e5710bSMark Peek pb = wp->who_host; 59745e5710bSMark Peek wbuf = xmalloc(strlen(pb) + 1); 59845e5710bSMark Peek wb = wbuf; 59945e5710bSMark Peek for (; *pb != '\0'; pb++) 60023338178SMark Peek *wb++ = isupper((unsigned char)*pb) ? 60123338178SMark Peek tolower((unsigned char)*pb) : *pb; 602c80476e4SDavid E. O'Brien *wb = '\0'; 603c80476e4SDavid E. O'Brien return wbuf; 604c80476e4SDavid E. O'Brien } 6059ccc37e3SMark Peek #endif /* UTHOSTLEN */ 606c80476e4SDavid E. O'Brien 607c80476e4SDavid E. O'Brien case 'l': 60845e5710bSMark Peek return strsave(wp->who_tty); 609c80476e4SDavid E. O'Brien 610c80476e4SDavid E. O'Brien default: 61145e5710bSMark Peek wbuf = xmalloc(3); 612c80476e4SDavid E. O'Brien wbuf[0] = '%'; 613c80476e4SDavid E. O'Brien wbuf[1] = (char) c; 614c80476e4SDavid E. O'Brien wbuf[2] = '\0'; 615c80476e4SDavid E. O'Brien return wbuf; 616c80476e4SDavid E. O'Brien } 617c80476e4SDavid E. O'Brien return NULL; 618c80476e4SDavid E. O'Brien } 619c80476e4SDavid E. O'Brien 620c80476e4SDavid E. O'Brien void 621c80476e4SDavid E. O'Brien /*ARGSUSED*/ 62245e5710bSMark Peek dolog(Char **v, struct command *c) 623c80476e4SDavid E. O'Brien { 624c80476e4SDavid E. O'Brien struct who *wp; 625c80476e4SDavid E. O'Brien struct varent *vp; 626c80476e4SDavid E. O'Brien 627c80476e4SDavid E. O'Brien USE(v); 628c80476e4SDavid E. O'Brien USE(c); 629c80476e4SDavid E. O'Brien vp = adrof(STRwatch); /* lint insists vp isn't used unless we */ 630c80476e4SDavid E. O'Brien if (vp == NULL) /* unless we assign it outside the if */ 631c80476e4SDavid E. O'Brien stderror(ERR_NOWATCH); 632c80476e4SDavid E. O'Brien resetwatch(); 633c80476e4SDavid E. O'Brien wp = whohead.who_next; 634c80476e4SDavid E. O'Brien while (wp->who_next != NULL) { 635c80476e4SDavid E. O'Brien wp->who_name[0] = '\0'; 636c80476e4SDavid E. O'Brien wp = wp->who_next; 637c80476e4SDavid E. O'Brien } 638c80476e4SDavid E. O'Brien } 639c80476e4SDavid E. O'Brien 6409ccc37e3SMark Peek # ifdef UTHOSTLEN 6413b6eaa7bSAndrey A. Chernov size_t 64245e5710bSMark Peek utmphostsize(void) 6433b6eaa7bSAndrey A. Chernov { 6443b6eaa7bSAndrey A. Chernov return UTHOSTLEN; 6453b6eaa7bSAndrey A. Chernov } 6463b6eaa7bSAndrey A. Chernov 647c80476e4SDavid E. O'Brien char * 64845e5710bSMark Peek utmphost(void) 649c80476e4SDavid E. O'Brien { 650c80476e4SDavid E. O'Brien char *tty = short2str(varval(STRtty)); 651c80476e4SDavid E. O'Brien struct who *wp; 652c80476e4SDavid E. O'Brien char *host = NULL; 653c80476e4SDavid E. O'Brien 654c80476e4SDavid E. O'Brien watch_login(1); 655c80476e4SDavid E. O'Brien 656c80476e4SDavid E. O'Brien for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) { 657c80476e4SDavid E. O'Brien if (strcmp(tty, wp->who_tty) == 0) 658c80476e4SDavid E. O'Brien host = wp->who_host; 659c80476e4SDavid E. O'Brien wp->who_name[0] = '\0'; 660c80476e4SDavid E. O'Brien } 661c80476e4SDavid E. O'Brien resetwatch(); 662c80476e4SDavid E. O'Brien return host; 663c80476e4SDavid E. O'Brien } 6649ccc37e3SMark Peek # endif /* UTHOSTLEN */ 665c80476e4SDavid E. O'Brien 6663b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 6679ccc37e3SMark Peek void 6689ccc37e3SMark Peek add_to_who_list(char *name, char *mach_nm) 669c80476e4SDavid E. O'Brien { 670c80476e4SDavid E. O'Brien 671c80476e4SDavid E. O'Brien struct who *wp, *wpnew; 672c80476e4SDavid E. O'Brien int comp = -1; 673c80476e4SDavid E. O'Brien 674c80476e4SDavid E. O'Brien wp = whohead.who_next; 675c80476e4SDavid E. O'Brien while (wp->who_next && (comp = strncmp(wp->who_tty,mach_nm,UTLINLEN)) < 0) 676c80476e4SDavid E. O'Brien wp = wp->who_next;/* find that tty! */ 677c80476e4SDavid E. O'Brien 678c80476e4SDavid E. O'Brien if (wp->who_next && comp == 0) { /* found the tty... */ 679c80476e4SDavid E. O'Brien 680c80476e4SDavid E. O'Brien if (*name == '\0') { 681c80476e4SDavid E. O'Brien wp->who_time = 0; 682c80476e4SDavid E. O'Brien wp->who_status = OFFLINE; 683c80476e4SDavid E. O'Brien } 684c80476e4SDavid E. O'Brien else if (strncmp(name, wp->who_name, UTNAMLEN) == 0) { 685c80476e4SDavid E. O'Brien /* someone is logged in */ 686c80476e4SDavid E. O'Brien wp->who_time = 0; 687c80476e4SDavid E. O'Brien wp->who_status = 0; /* same guy */ 688c80476e4SDavid E. O'Brien } 689c80476e4SDavid E. O'Brien else { 690c80476e4SDavid E. O'Brien (void) strncpy(wp->who_new, name, UTNAMLEN); 691c80476e4SDavid E. O'Brien wp->who_time = 0; 692c80476e4SDavid E. O'Brien if (wp->who_name[0] == '\0') 693c80476e4SDavid E. O'Brien wp->who_status = ONLINE; 694c80476e4SDavid E. O'Brien else 695c80476e4SDavid E. O'Brien wp->who_status = CHANGED; 696c80476e4SDavid E. O'Brien } 697c80476e4SDavid E. O'Brien } 698c80476e4SDavid E. O'Brien else { 69945e5710bSMark Peek wpnew = xcalloc(1, sizeof *wpnew); 700c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_tty, mach_nm, UTLINLEN); 701c80476e4SDavid E. O'Brien wpnew->who_time = 0; 702c80476e4SDavid E. O'Brien if (*name == '\0') 703c80476e4SDavid E. O'Brien wpnew->who_status = OFFLINE; 704c80476e4SDavid E. O'Brien else { 705c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_new, name, UTNAMLEN); 706c80476e4SDavid E. O'Brien wpnew->who_status = ONLINE; 707c80476e4SDavid E. O'Brien } 708c80476e4SDavid E. O'Brien #ifdef WHODEBUG 709c80476e4SDavid E. O'Brien debugwholist(wpnew, wp); 710c80476e4SDavid E. O'Brien #endif /* WHODEBUG */ 711c80476e4SDavid E. O'Brien 712c80476e4SDavid E. O'Brien wpnew->who_next = wp; /* link in a new 'who' */ 713c80476e4SDavid E. O'Brien wpnew->who_prev = wp->who_prev; 714c80476e4SDavid E. O'Brien wpnew->who_prev->who_next = wpnew; 715c80476e4SDavid E. O'Brien wp->who_prev = wpnew; /* linked in now */ 716c80476e4SDavid E. O'Brien } 717c80476e4SDavid E. O'Brien } 7183b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 719c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */ 720