129301572SMark Peek /* $Header: /src/pub/tcsh/tc.who.c,v 3.35 2002/07/01 21:12:04 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 3529301572SMark Peek RCSID("$Id: tc.who.c,v 3.35 2002/07/01 21:12:04 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 45c80476e4SDavid E. O'Brien #ifdef HAVEUTMPX 46c80476e4SDavid E. O'Brien # include <utmpx.h> 47c80476e4SDavid E. O'Brien /* I just redefine a few words here. Changing every occurrence below 48c80476e4SDavid E. O'Brien * seems like too much of work. All UTMP functions have equivalent 49c80476e4SDavid E. O'Brien * UTMPX counterparts, so they can be added all here when needed. 50c80476e4SDavid E. O'Brien * Kimmo Suominen, Oct 14 1991 51c80476e4SDavid E. O'Brien */ 52c80476e4SDavid E. O'Brien # ifndef _PATH_UTMP 533b6eaa7bSAndrey A. Chernov # if defined(__UTMPX_FILE) && !defined(UTMPX_FILE) 543b6eaa7bSAndrey A. Chernov # define _PATH_UTMP __UTMPX_FILE 553b6eaa7bSAndrey A. Chernov # else 56c80476e4SDavid E. O'Brien # define _PATH_UTMP UTMPX_FILE 573b6eaa7bSAndrey A. Chernov # endif /* __UTMPX_FILE && !UTMPX_FILE */ 58c80476e4SDavid E. O'Brien # endif /* _PATH_UTMP */ 59c80476e4SDavid E. O'Brien # define utmp utmpx 603b6eaa7bSAndrey A. Chernov # ifdef __MVS__ 613b6eaa7bSAndrey A. Chernov # define ut_time ut_tv.tv_sec 623b6eaa7bSAndrey A. Chernov # define ut_name ut_user 633b6eaa7bSAndrey A. Chernov # else 64c80476e4SDavid E. O'Brien # define ut_time ut_xtime 653b6eaa7bSAndrey A. Chernov # endif /* __MVS__ */ 66c80476e4SDavid E. O'Brien #else /* !HAVEUTMPX */ 673b6eaa7bSAndrey A. Chernov # ifndef WINNT_NATIVE 68c80476e4SDavid E. O'Brien # include <utmp.h> 693b6eaa7bSAndrey A. Chernov # endif /* WINNT_NATIVE */ 70c80476e4SDavid E. O'Brien #endif /* HAVEUTMPX */ 71c80476e4SDavid E. O'Brien 72c80476e4SDavid E. O'Brien #ifndef BROKEN_CC 73c80476e4SDavid E. O'Brien # define UTNAMLEN sizeof(((struct utmp *) 0)->ut_name) 74c80476e4SDavid E. O'Brien # define UTLINLEN sizeof(((struct utmp *) 0)->ut_line) 75c80476e4SDavid E. O'Brien # ifdef UTHOST 76c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 77c80476e4SDavid E. O'Brien # define UTHOSTLEN 100 78c80476e4SDavid E. O'Brien # else 79c80476e4SDavid E. O'Brien # define UTHOSTLEN sizeof(((struct utmp *) 0)->ut_host) 80c80476e4SDavid E. O'Brien # endif 81c80476e4SDavid E. O'Brien # endif /* UTHOST */ 82c80476e4SDavid E. O'Brien #else 83c80476e4SDavid E. O'Brien /* give poor cc a little help if it needs it */ 84c80476e4SDavid E. O'Brien struct utmp __ut; 85c80476e4SDavid E. O'Brien 86c80476e4SDavid E. O'Brien # define UTNAMLEN sizeof(__ut.ut_name) 87c80476e4SDavid E. O'Brien # define UTLINLEN sizeof(__ut.ut_line) 88c80476e4SDavid E. O'Brien # ifdef UTHOST 89c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 90c80476e4SDavid E. O'Brien # define UTHOSTLEN 100 91c80476e4SDavid E. O'Brien # else 92c80476e4SDavid E. O'Brien # define UTHOSTLEN sizeof(__ut.ut_host) 93c80476e4SDavid E. O'Brien # endif 94c80476e4SDavid E. O'Brien # endif /* UTHOST */ 95c80476e4SDavid E. O'Brien #endif /* BROKEN_CC */ 96c80476e4SDavid E. O'Brien 97c80476e4SDavid E. O'Brien #ifndef _PATH_UTMP 98c80476e4SDavid E. O'Brien # ifdef UTMP_FILE 99c80476e4SDavid E. O'Brien # define _PATH_UTMP UTMP_FILE 100c80476e4SDavid E. O'Brien # else 101c80476e4SDavid E. O'Brien # define _PATH_UTMP "/etc/utmp" 102c80476e4SDavid E. O'Brien # endif /* UTMP_FILE */ 103c80476e4SDavid E. O'Brien #endif /* _PATH_UTMP */ 104c80476e4SDavid E. O'Brien 105c80476e4SDavid E. O'Brien 106c80476e4SDavid E. O'Brien struct who { 107c80476e4SDavid E. O'Brien struct who *who_next; 108c80476e4SDavid E. O'Brien struct who *who_prev; 109c80476e4SDavid E. O'Brien char who_name[UTNAMLEN + 1]; 110c80476e4SDavid E. O'Brien char who_new[UTNAMLEN + 1]; 111c80476e4SDavid E. O'Brien char who_tty[UTLINLEN + 1]; 112c80476e4SDavid E. O'Brien #ifdef UTHOST 113c80476e4SDavid E. O'Brien char who_host[UTHOSTLEN + 1]; 114c80476e4SDavid E. O'Brien #endif /* UTHOST */ 115c80476e4SDavid E. O'Brien time_t who_time; 116c80476e4SDavid E. O'Brien int who_status; 117c80476e4SDavid E. O'Brien }; 118c80476e4SDavid E. O'Brien 119c80476e4SDavid E. O'Brien static struct who whohead, whotail; 120c80476e4SDavid E. O'Brien static time_t watch_period = 0; 121c80476e4SDavid E. O'Brien static time_t stlast = 0; 122c80476e4SDavid E. O'Brien #ifdef WHODEBUG 123c80476e4SDavid E. O'Brien static void debugwholist __P((struct who *, struct who *)); 124c80476e4SDavid E. O'Brien #endif 125c80476e4SDavid E. O'Brien static void print_who __P((struct who *)); 126c80476e4SDavid E. O'Brien 127c80476e4SDavid E. O'Brien 128c80476e4SDavid E. O'Brien #define ONLINE 01 129c80476e4SDavid E. O'Brien #define OFFLINE 02 130c80476e4SDavid E. O'Brien #define CHANGED 04 131c80476e4SDavid E. O'Brien #define STMASK 07 132c80476e4SDavid E. O'Brien #define ANNOUNCE 010 133c80476e4SDavid E. O'Brien 134c80476e4SDavid E. O'Brien /* 135c80476e4SDavid E. O'Brien * Karl Kleinpaste, 26 Jan 1984. 136c80476e4SDavid E. O'Brien * Initialize the dummy tty list for login watch. 137c80476e4SDavid E. O'Brien * This dummy list eliminates boundary conditions 138c80476e4SDavid E. O'Brien * when doing pointer-chase searches. 139c80476e4SDavid E. O'Brien */ 140c80476e4SDavid E. O'Brien void 141c80476e4SDavid E. O'Brien initwatch() 142c80476e4SDavid E. O'Brien { 143c80476e4SDavid E. O'Brien whohead.who_next = &whotail; 144c80476e4SDavid E. O'Brien whotail.who_prev = &whohead; 145c80476e4SDavid E. O'Brien stlast = 1; 146c80476e4SDavid E. O'Brien #ifdef WHODEBUG 147c80476e4SDavid E. O'Brien debugwholist(NULL, NULL); 148c80476e4SDavid E. O'Brien #endif /* WHODEBUG */ 149c80476e4SDavid E. O'Brien } 150c80476e4SDavid E. O'Brien 151c80476e4SDavid E. O'Brien void 152c80476e4SDavid E. O'Brien resetwatch() 153c80476e4SDavid E. O'Brien { 154c80476e4SDavid E. O'Brien watch_period = 0; 155c80476e4SDavid E. O'Brien stlast = 0; 156c80476e4SDavid E. O'Brien } 157c80476e4SDavid E. O'Brien 158c80476e4SDavid E. O'Brien /* 159c80476e4SDavid E. O'Brien * Karl Kleinpaste, 26 Jan 1984. 160c80476e4SDavid E. O'Brien * Watch /etc/utmp for login/logout changes. 161c80476e4SDavid E. O'Brien */ 162c80476e4SDavid E. O'Brien void 163c80476e4SDavid E. O'Brien watch_login(force) 164c80476e4SDavid E. O'Brien int force; 165c80476e4SDavid E. O'Brien { 166c80476e4SDavid E. O'Brien int utmpfd, comp = -1, alldone; 167c80476e4SDavid E. O'Brien int firsttime = stlast == 1; 168c80476e4SDavid E. O'Brien #ifdef BSDSIGS 169c80476e4SDavid E. O'Brien sigmask_t omask; 170c80476e4SDavid E. O'Brien #endif /* BSDSIGS */ 171c80476e4SDavid E. O'Brien struct utmp utmp; 172c80476e4SDavid E. O'Brien struct who *wp, *wpnew; 173c80476e4SDavid E. O'Brien struct varent *v; 174c80476e4SDavid E. O'Brien Char **vp = NULL; 175c80476e4SDavid E. O'Brien time_t t, interval = MAILINTVL; 176c80476e4SDavid E. O'Brien struct stat sta; 177c80476e4SDavid E. O'Brien #if defined(UTHOST) && defined(_SEQUENT_) 178c80476e4SDavid E. O'Brien char *host, *ut_find_host(); 179c80476e4SDavid E. O'Brien #endif 1803b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 181c80476e4SDavid E. O'Brien static int ncbs_posted = 0; 182c80476e4SDavid E. O'Brien USE(utmp); 183c80476e4SDavid E. O'Brien USE(utmpfd); 184c80476e4SDavid E. O'Brien USE(sta); 185c80476e4SDavid E. O'Brien USE(wpnew); 1863b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 187c80476e4SDavid E. O'Brien 188c80476e4SDavid E. O'Brien /* stop SIGINT, lest our login list get trashed. */ 189c80476e4SDavid E. O'Brien #ifdef BSDSIGS 190c80476e4SDavid E. O'Brien omask = sigblock(sigmask(SIGINT)); 191c80476e4SDavid E. O'Brien #else 192c80476e4SDavid E. O'Brien (void) sighold(SIGINT); 193c80476e4SDavid E. O'Brien #endif 194c80476e4SDavid E. O'Brien 195c80476e4SDavid E. O'Brien v = adrof(STRwatch); 19629301572SMark Peek if ((v == NULL || v->vec == NULL) && !force) { 197c80476e4SDavid E. O'Brien #ifdef BSDSIGS 198c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 199c80476e4SDavid E. O'Brien #else 200c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 201c80476e4SDavid E. O'Brien #endif 202c80476e4SDavid E. O'Brien return; /* no names to watch */ 203c80476e4SDavid E. O'Brien } 204c80476e4SDavid E. O'Brien if (!force) { 205c80476e4SDavid E. O'Brien trim(vp = v->vec); 206c80476e4SDavid E. O'Brien if (blklen(vp) % 2) /* odd # args: 1st == # minutes. */ 207c80476e4SDavid E. O'Brien interval = (number(*vp)) ? (getn(*vp++) * 60) : MAILINTVL; 208c80476e4SDavid E. O'Brien } 209c80476e4SDavid E. O'Brien else 210c80476e4SDavid E. O'Brien interval = 0; 211c80476e4SDavid E. O'Brien 212c80476e4SDavid E. O'Brien (void) time(&t); 2133b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 214c80476e4SDavid E. O'Brien /* 215c80476e4SDavid E. O'Brien * Since NCB_ASTATs take time, start em async at least 90 secs 216c80476e4SDavid E. O'Brien * before we are due -amol 6/5/97 217c80476e4SDavid E. O'Brien */ 218c80476e4SDavid E. O'Brien if (!ncbs_posted) { 219c80476e4SDavid E. O'Brien unsigned long tdiff = t - watch_period; 220c80476e4SDavid E. O'Brien if (!watch_period || ((tdiff > 0) && (tdiff > (interval - 90)))) { 221c80476e4SDavid E. O'Brien start_ncbs(vp); 222c80476e4SDavid E. O'Brien ncbs_posted = 1; 223c80476e4SDavid E. O'Brien } 224c80476e4SDavid E. O'Brien } 2253b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 226c80476e4SDavid E. O'Brien if (t - watch_period < interval) { 227c80476e4SDavid E. O'Brien #ifdef BSDSIGS 228c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 229c80476e4SDavid E. O'Brien #else 230c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 231c80476e4SDavid E. O'Brien #endif 232c80476e4SDavid E. O'Brien return; /* not long enough yet... */ 233c80476e4SDavid E. O'Brien } 234c80476e4SDavid E. O'Brien watch_period = t; 2353b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 236c80476e4SDavid E. O'Brien ncbs_posted = 0; 2373b6eaa7bSAndrey A. Chernov #else /* !WINNT_NATIVE */ 238c80476e4SDavid E. O'Brien 239c80476e4SDavid E. O'Brien /* 240c80476e4SDavid E. O'Brien * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 241c80476e4SDavid E. O'Brien * Don't open utmp all the time, stat it first... 242c80476e4SDavid E. O'Brien */ 243c80476e4SDavid E. O'Brien if (stat(_PATH_UTMP, &sta)) { 244dc86a98eSDavid E. O'Brien if (!force) 245dc86a98eSDavid E. O'Brien xprintf(CGETS(26, 1, 246dc86a98eSDavid E. O'Brien "cannot stat %s. Please \"unset watch\".\n"), 247c80476e4SDavid E. O'Brien _PATH_UTMP); 248c80476e4SDavid E. O'Brien # ifdef BSDSIGS 249c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 250c80476e4SDavid E. O'Brien # else 251c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 252c80476e4SDavid E. O'Brien # endif 253c80476e4SDavid E. O'Brien return; 254c80476e4SDavid E. O'Brien } 255c80476e4SDavid E. O'Brien if (stlast == sta.st_mtime) { 256c80476e4SDavid E. O'Brien # ifdef BSDSIGS 257c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 258c80476e4SDavid E. O'Brien # else 259c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 260c80476e4SDavid E. O'Brien # endif 261c80476e4SDavid E. O'Brien return; 262c80476e4SDavid E. O'Brien } 263c80476e4SDavid E. O'Brien stlast = sta.st_mtime; 264c80476e4SDavid E. O'Brien if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) { 265dc86a98eSDavid E. O'Brien if (!force) 266dc86a98eSDavid E. O'Brien xprintf(CGETS(26, 2, 267dc86a98eSDavid E. O'Brien "%s cannot be opened. Please \"unset watch\".\n"), 268c80476e4SDavid E. O'Brien _PATH_UTMP); 269c80476e4SDavid E. O'Brien # ifdef BSDSIGS 270c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 271c80476e4SDavid E. O'Brien # else 272c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 273c80476e4SDavid E. O'Brien # endif 274c80476e4SDavid E. O'Brien return; 275c80476e4SDavid E. O'Brien } 276c80476e4SDavid E. O'Brien 277c80476e4SDavid E. O'Brien /* 278c80476e4SDavid E. O'Brien * xterm clears the entire utmp entry - mark everyone on the status list 279c80476e4SDavid E. O'Brien * OFFLINE or we won't notice X "logouts" 280c80476e4SDavid E. O'Brien */ 281c80476e4SDavid E. O'Brien for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) { 282c80476e4SDavid E. O'Brien wp->who_status = OFFLINE; 283c80476e4SDavid E. O'Brien wp->who_time = 0; 284c80476e4SDavid E. O'Brien } 285c80476e4SDavid E. O'Brien 286c80476e4SDavid E. O'Brien /* 287c80476e4SDavid E. O'Brien * Read in the utmp file, sort the entries, and update existing entries or 288c80476e4SDavid E. O'Brien * add new entries to the status list. 289c80476e4SDavid E. O'Brien */ 290c80476e4SDavid E. O'Brien while (read(utmpfd, (char *) &utmp, sizeof utmp) == sizeof utmp) { 291c80476e4SDavid E. O'Brien 292c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 293c80476e4SDavid E. O'Brien # ifndef IRIS4D 294c80476e4SDavid E. O'Brien if (utmp.ut_type != USER_PROCESS) 295c80476e4SDavid E. O'Brien continue; 296c80476e4SDavid E. O'Brien # else 297c80476e4SDavid E. O'Brien /* Why is that? Cause the utmp file is always corrupted??? */ 298c80476e4SDavid E. O'Brien if (utmp.ut_type != USER_PROCESS && utmp.ut_type != DEAD_PROCESS) 299c80476e4SDavid E. O'Brien continue; 300c80476e4SDavid E. O'Brien # endif /* IRIS4D */ 301c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 302c80476e4SDavid E. O'Brien 303c80476e4SDavid E. O'Brien if (utmp.ut_name[0] == '\0' && utmp.ut_line[0] == '\0') 304c80476e4SDavid E. O'Brien continue; /* completely void entry */ 305c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 306c80476e4SDavid E. O'Brien if (utmp.ut_type == DEAD_PROCESS && utmp.ut_line[0] == '\0') 307c80476e4SDavid E. O'Brien continue; 308c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 309c80476e4SDavid E. O'Brien wp = whohead.who_next; 310c80476e4SDavid E. O'Brien while (wp->who_next && (comp = strncmp(wp->who_tty, utmp.ut_line, UTLINLEN)) < 0) 311c80476e4SDavid E. O'Brien wp = wp->who_next;/* find that tty! */ 312c80476e4SDavid E. O'Brien 313c80476e4SDavid E. O'Brien if (wp->who_next && comp == 0) { /* found the tty... */ 314c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 315c80476e4SDavid E. O'Brien if (utmp.ut_type == DEAD_PROCESS) { 316c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 317c80476e4SDavid E. O'Brien wp->who_status = OFFLINE; 318c80476e4SDavid E. O'Brien } 319c80476e4SDavid E. O'Brien else 320c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 321c80476e4SDavid E. O'Brien if (utmp.ut_name[0] == '\0') { 322c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 323c80476e4SDavid E. O'Brien wp->who_status = OFFLINE; 324c80476e4SDavid E. O'Brien } 325c80476e4SDavid E. O'Brien else if (strncmp(utmp.ut_name, wp->who_name, UTNAMLEN) == 0) { 326c80476e4SDavid E. O'Brien /* someone is logged in */ 327c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 328c80476e4SDavid E. O'Brien wp->who_status = 0; /* same guy */ 329c80476e4SDavid E. O'Brien } 330c80476e4SDavid E. O'Brien else { 331c80476e4SDavid E. O'Brien (void) strncpy(wp->who_new, utmp.ut_name, UTNAMLEN); 332c80476e4SDavid E. O'Brien # ifdef UTHOST 333c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 334c80476e4SDavid E. O'Brien host = ut_find_host(wp->who_tty); 335c80476e4SDavid E. O'Brien if (host) 336c80476e4SDavid E. O'Brien (void) strncpy(wp->who_host, host, UTHOSTLEN); 337c80476e4SDavid E. O'Brien else 338c80476e4SDavid E. O'Brien wp->who_host[0] = 0; 339c80476e4SDavid E. O'Brien # else 340c80476e4SDavid E. O'Brien (void) strncpy(wp->who_host, utmp.ut_host, UTHOSTLEN); 341c80476e4SDavid E. O'Brien # endif 342c80476e4SDavid E. O'Brien # endif /* UTHOST */ 343c80476e4SDavid E. O'Brien wp->who_time = utmp.ut_time; 344c80476e4SDavid E. O'Brien if (wp->who_name[0] == '\0') 345c80476e4SDavid E. O'Brien wp->who_status = ONLINE; 346c80476e4SDavid E. O'Brien else 347c80476e4SDavid E. O'Brien wp->who_status = CHANGED; 348c80476e4SDavid E. O'Brien } 349c80476e4SDavid E. O'Brien } 350c80476e4SDavid E. O'Brien else { /* new tty in utmp */ 351c80476e4SDavid E. O'Brien wpnew = (struct who *) xcalloc(1, sizeof *wpnew); 352c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_tty, utmp.ut_line, UTLINLEN); 353c80476e4SDavid E. O'Brien # ifdef UTHOST 354c80476e4SDavid E. O'Brien # ifdef _SEQUENT_ 355c80476e4SDavid E. O'Brien host = ut_find_host(wpnew->who_tty); 356c80476e4SDavid E. O'Brien if (host) 357c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_host, host, UTHOSTLEN); 358c80476e4SDavid E. O'Brien else 359c80476e4SDavid E. O'Brien wpnew->who_host[0] = 0; 360c80476e4SDavid E. O'Brien # else 361c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_host, utmp.ut_host, UTHOSTLEN); 362c80476e4SDavid E. O'Brien # endif 363c80476e4SDavid E. O'Brien # endif /* UTHOST */ 364c80476e4SDavid E. O'Brien wpnew->who_time = utmp.ut_time; 365c80476e4SDavid E. O'Brien # ifdef DEAD_PROCESS 366c80476e4SDavid E. O'Brien if (utmp.ut_type == DEAD_PROCESS) 367c80476e4SDavid E. O'Brien wpnew->who_status = OFFLINE; 368c80476e4SDavid E. O'Brien else 369c80476e4SDavid E. O'Brien # endif /* DEAD_PROCESS */ 370c80476e4SDavid E. O'Brien if (utmp.ut_name[0] == '\0') 371c80476e4SDavid E. O'Brien wpnew->who_status = OFFLINE; 372c80476e4SDavid E. O'Brien else { 373c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_new, utmp.ut_name, UTNAMLEN); 374c80476e4SDavid E. O'Brien wpnew->who_status = ONLINE; 375c80476e4SDavid E. O'Brien } 376c80476e4SDavid E. O'Brien # ifdef WHODEBUG 377c80476e4SDavid E. O'Brien debugwholist(wpnew, wp); 378c80476e4SDavid E. O'Brien # endif /* WHODEBUG */ 379c80476e4SDavid E. O'Brien 380c80476e4SDavid E. O'Brien wpnew->who_next = wp; /* link in a new 'who' */ 381c80476e4SDavid E. O'Brien wpnew->who_prev = wp->who_prev; 382c80476e4SDavid E. O'Brien wpnew->who_prev->who_next = wpnew; 383c80476e4SDavid E. O'Brien wp->who_prev = wpnew; /* linked in now */ 384c80476e4SDavid E. O'Brien } 385c80476e4SDavid E. O'Brien } 386c80476e4SDavid E. O'Brien (void) close(utmpfd); 387c80476e4SDavid E. O'Brien # if defined(UTHOST) && defined(_SEQUENT_) 388c80476e4SDavid E. O'Brien endutent(); 389c80476e4SDavid E. O'Brien # endif 3903b6eaa7bSAndrey A. Chernov #endif /* !WINNT_NATIVE */ 391c80476e4SDavid E. O'Brien 392c80476e4SDavid E. O'Brien if (force || vp == NULL) 393c80476e4SDavid E. O'Brien return; 394c80476e4SDavid E. O'Brien 395c80476e4SDavid E. O'Brien /* 396c80476e4SDavid E. O'Brien * The state of all logins is now known, so we can search the user's list 397c80476e4SDavid E. O'Brien * of watchables to print the interesting ones. 398c80476e4SDavid E. O'Brien */ 399c80476e4SDavid E. O'Brien for (alldone = 0; !alldone && *vp != NULL && **vp != '\0' && 400c80476e4SDavid E. O'Brien *(vp + 1) != NULL && **(vp + 1) != '\0'; 401c80476e4SDavid E. O'Brien vp += 2) { /* args used in pairs... */ 402c80476e4SDavid E. O'Brien 403c80476e4SDavid E. O'Brien if (eq(*vp, STRany) && eq(*(vp + 1), STRany)) 404c80476e4SDavid E. O'Brien alldone = 1; 405c80476e4SDavid E. O'Brien 406c80476e4SDavid E. O'Brien for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) { 407c80476e4SDavid E. O'Brien if (wp->who_status & ANNOUNCE || 408c80476e4SDavid E. O'Brien (!eq(STRany, vp[0]) && 409c80476e4SDavid E. O'Brien !Gmatch(str2short(wp->who_name), vp[0]) && 410c80476e4SDavid E. O'Brien !Gmatch(str2short(wp->who_new), vp[0])) || 411c80476e4SDavid E. O'Brien (!Gmatch(str2short(wp->who_tty), vp[1]) && 412c80476e4SDavid E. O'Brien !eq(STRany, vp[1]))) 413c80476e4SDavid E. O'Brien continue; /* entry doesn't qualify */ 414c80476e4SDavid E. O'Brien /* already printed or not right one to print */ 415c80476e4SDavid E. O'Brien 416c80476e4SDavid E. O'Brien 417c80476e4SDavid E. O'Brien if (wp->who_time == 0)/* utmp entry was cleared */ 418c80476e4SDavid E. O'Brien wp->who_time = watch_period; 419c80476e4SDavid E. O'Brien 420c80476e4SDavid E. O'Brien if ((wp->who_status & OFFLINE) && 421c80476e4SDavid E. O'Brien (wp->who_name[0] != '\0')) { 422c80476e4SDavid E. O'Brien if (!firsttime) 423c80476e4SDavid E. O'Brien print_who(wp); 424c80476e4SDavid E. O'Brien wp->who_name[0] = '\0'; 425c80476e4SDavid E. O'Brien wp->who_status |= ANNOUNCE; 426c80476e4SDavid E. O'Brien continue; 427c80476e4SDavid E. O'Brien } 428c80476e4SDavid E. O'Brien if (wp->who_status & ONLINE) { 429c80476e4SDavid E. O'Brien if (!firsttime) 430c80476e4SDavid E. O'Brien print_who(wp); 431c80476e4SDavid E. O'Brien (void) strcpy(wp->who_name, wp->who_new); 432c80476e4SDavid E. O'Brien wp->who_status |= ANNOUNCE; 433c80476e4SDavid E. O'Brien continue; 434c80476e4SDavid E. O'Brien } 435c80476e4SDavid E. O'Brien if (wp->who_status & CHANGED) { 436c80476e4SDavid E. O'Brien if (!firsttime) 437c80476e4SDavid E. O'Brien print_who(wp); 438c80476e4SDavid E. O'Brien (void) strcpy(wp->who_name, wp->who_new); 439c80476e4SDavid E. O'Brien wp->who_status |= ANNOUNCE; 440c80476e4SDavid E. O'Brien continue; 441c80476e4SDavid E. O'Brien } 442c80476e4SDavid E. O'Brien } 443c80476e4SDavid E. O'Brien } 444c80476e4SDavid E. O'Brien #ifdef BSDSIGS 445c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 446c80476e4SDavid E. O'Brien #else 447c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 448c80476e4SDavid E. O'Brien #endif 449c80476e4SDavid E. O'Brien } 450c80476e4SDavid E. O'Brien 451c80476e4SDavid E. O'Brien #ifdef WHODEBUG 452c80476e4SDavid E. O'Brien static void 453c80476e4SDavid E. O'Brien debugwholist(new, wp) 454c80476e4SDavid E. O'Brien register struct who *new, *wp; 455c80476e4SDavid E. O'Brien { 456c80476e4SDavid E. O'Brien register struct who *a; 457c80476e4SDavid E. O'Brien 458c80476e4SDavid E. O'Brien a = whohead.who_next; 459c80476e4SDavid E. O'Brien while (a->who_next != NULL) { 460c80476e4SDavid E. O'Brien xprintf("%s/%s -> ", a->who_name, a->who_tty); 461c80476e4SDavid E. O'Brien a = a->who_next; 462c80476e4SDavid E. O'Brien } 463c80476e4SDavid E. O'Brien xprintf("TAIL\n"); 464c80476e4SDavid E. O'Brien if (a != &whotail) { 465c80476e4SDavid E. O'Brien xprintf(CGETS(26, 3, "BUG! last element is not whotail!\n")); 466c80476e4SDavid E. O'Brien abort(); 467c80476e4SDavid E. O'Brien } 468c80476e4SDavid E. O'Brien a = whotail.who_prev; 469c80476e4SDavid E. O'Brien xprintf(CGETS(26, 4, "backward: ")); 470c80476e4SDavid E. O'Brien while (a->who_prev != NULL) { 471c80476e4SDavid E. O'Brien xprintf("%s/%s -> ", a->who_name, a->who_tty); 472c80476e4SDavid E. O'Brien a = a->who_prev; 473c80476e4SDavid E. O'Brien } 474c80476e4SDavid E. O'Brien xprintf("HEAD\n"); 475c80476e4SDavid E. O'Brien if (a != &whohead) { 476c80476e4SDavid E. O'Brien xprintf(CGETS(26, 5, "BUG! first element is not whohead!\n")); 477c80476e4SDavid E. O'Brien abort(); 478c80476e4SDavid E. O'Brien } 479c80476e4SDavid E. O'Brien if (new) 480c80476e4SDavid E. O'Brien xprintf(CGETS(26, 6, "new: %s/%s\n"), new->who_name, new->who_tty); 481c80476e4SDavid E. O'Brien if (wp) 482c80476e4SDavid E. O'Brien xprintf("wp: %s/%s\n", wp->who_name, wp->who_tty); 483c80476e4SDavid E. O'Brien } 484c80476e4SDavid E. O'Brien #endif /* WHODEBUG */ 485c80476e4SDavid E. O'Brien 486c80476e4SDavid E. O'Brien 487c80476e4SDavid E. O'Brien static void 488c80476e4SDavid E. O'Brien print_who(wp) 489c80476e4SDavid E. O'Brien struct who *wp; 490c80476e4SDavid E. O'Brien { 491c80476e4SDavid E. O'Brien #ifdef UTHOST 492c80476e4SDavid E. O'Brien Char *cp = str2short(CGETS(26, 7, "%n has %a %l from %m.")); 493c80476e4SDavid E. O'Brien #else 494c80476e4SDavid E. O'Brien Char *cp = str2short(CGETS(26, 8, "%n has %a %l.")); 495c80476e4SDavid E. O'Brien #endif /* UTHOST */ 496c80476e4SDavid E. O'Brien struct varent *vp = adrof(STRwho); 497c80476e4SDavid E. O'Brien Char buf[BUFSIZE]; 498c80476e4SDavid E. O'Brien 49929301572SMark Peek if (vp && vp->vec && vp->vec[0]) 500c80476e4SDavid E. O'Brien cp = vp->vec[0]; 501c80476e4SDavid E. O'Brien 502c80476e4SDavid E. O'Brien tprintf(FMT_WHO, buf, cp, BUFSIZE, NULL, wp->who_time, (ptr_t) wp); 503c80476e4SDavid E. O'Brien for (cp = buf; *cp;) 504c80476e4SDavid E. O'Brien xputchar(*cp++); 505c80476e4SDavid E. O'Brien xputchar('\n'); 506c80476e4SDavid E. O'Brien } /* end print_who */ 507c80476e4SDavid E. O'Brien 508c80476e4SDavid E. O'Brien 509c80476e4SDavid E. O'Brien const char * 510c80476e4SDavid E. O'Brien who_info(ptr, c, wbuf, wbufsiz) 511c80476e4SDavid E. O'Brien ptr_t ptr; 512c80476e4SDavid E. O'Brien int c; 513c80476e4SDavid E. O'Brien char *wbuf; 514c80476e4SDavid E. O'Brien size_t wbufsiz; 515c80476e4SDavid E. O'Brien { 516c80476e4SDavid E. O'Brien struct who *wp = (struct who *) ptr; 517c80476e4SDavid E. O'Brien #ifdef UTHOST 518c80476e4SDavid E. O'Brien char *wb = wbuf; 519c80476e4SDavid E. O'Brien int flg; 520c80476e4SDavid E. O'Brien char *pb; 521c80476e4SDavid E. O'Brien #endif /* UTHOST */ 522c80476e4SDavid E. O'Brien 523c80476e4SDavid E. O'Brien switch (c) { 524c80476e4SDavid E. O'Brien case 'n': /* user name */ 525c80476e4SDavid E. O'Brien switch (wp->who_status & STMASK) { 526c80476e4SDavid E. O'Brien case ONLINE: 527c80476e4SDavid E. O'Brien case CHANGED: 528c80476e4SDavid E. O'Brien return wp->who_new; 529c80476e4SDavid E. O'Brien case OFFLINE: 530c80476e4SDavid E. O'Brien return wp->who_name; 531c80476e4SDavid E. O'Brien default: 532c80476e4SDavid E. O'Brien break; 533c80476e4SDavid E. O'Brien } 534c80476e4SDavid E. O'Brien break; 535c80476e4SDavid E. O'Brien 536c80476e4SDavid E. O'Brien case 'a': 537c80476e4SDavid E. O'Brien switch (wp->who_status & STMASK) { 538c80476e4SDavid E. O'Brien case ONLINE: 539c80476e4SDavid E. O'Brien return CGETS(26, 9, "logged on"); 540c80476e4SDavid E. O'Brien case OFFLINE: 541c80476e4SDavid E. O'Brien return CGETS(26, 10, "logged off"); 542c80476e4SDavid E. O'Brien case CHANGED: 543c80476e4SDavid E. O'Brien xsnprintf(wbuf, wbufsiz, CGETS(26, 11, "replaced %s on"), 544c80476e4SDavid E. O'Brien wp->who_name); 545c80476e4SDavid E. O'Brien return wbuf; 546c80476e4SDavid E. O'Brien default: 547c80476e4SDavid E. O'Brien break; 548c80476e4SDavid E. O'Brien } 549c80476e4SDavid E. O'Brien break; 550c80476e4SDavid E. O'Brien 551c80476e4SDavid E. O'Brien #ifdef UTHOST 552c80476e4SDavid E. O'Brien case 'm': 553c80476e4SDavid E. O'Brien if (wp->who_host[0] == '\0') 554c80476e4SDavid E. O'Brien return CGETS(26, 12, "local"); 555c80476e4SDavid E. O'Brien else { 556c80476e4SDavid E. O'Brien /* the ':' stuff is for <host>:<display>.<screen> */ 557c80476e4SDavid E. O'Brien for (pb = wp->who_host, flg = Isdigit(*pb) ? '\0' : '.'; 558c80476e4SDavid E. O'Brien *pb != '\0' && 559c80476e4SDavid E. O'Brien (*pb != flg || ((pb = strchr(pb, ':')) != 0)); 560c80476e4SDavid E. O'Brien pb++) { 561c80476e4SDavid E. O'Brien if (*pb == ':') 562c80476e4SDavid E. O'Brien flg = '\0'; 563c80476e4SDavid E. O'Brien *wb++ = Isupper(*pb) ? Tolower(*pb) : *pb; 564c80476e4SDavid E. O'Brien } 565c80476e4SDavid E. O'Brien *wb = '\0'; 566c80476e4SDavid E. O'Brien return wbuf; 567c80476e4SDavid E. O'Brien } 568c80476e4SDavid E. O'Brien 569c80476e4SDavid E. O'Brien case 'M': 570c80476e4SDavid E. O'Brien if (wp->who_host[0] == '\0') 571c80476e4SDavid E. O'Brien return CGETS(26, 12, "local"); 572c80476e4SDavid E. O'Brien else { 573c80476e4SDavid E. O'Brien for (pb = wp->who_host; *pb != '\0'; pb++) 574c80476e4SDavid E. O'Brien *wb++ = Isupper(*pb) ? Tolower(*pb) : *pb; 575c80476e4SDavid E. O'Brien *wb = '\0'; 576c80476e4SDavid E. O'Brien return wbuf; 577c80476e4SDavid E. O'Brien } 578c80476e4SDavid E. O'Brien #endif /* UTHOST */ 579c80476e4SDavid E. O'Brien 580c80476e4SDavid E. O'Brien case 'l': 581c80476e4SDavid E. O'Brien return wp->who_tty; 582c80476e4SDavid E. O'Brien 583c80476e4SDavid E. O'Brien default: 584c80476e4SDavid E. O'Brien wbuf[0] = '%'; 585c80476e4SDavid E. O'Brien wbuf[1] = (char) c; 586c80476e4SDavid E. O'Brien wbuf[2] = '\0'; 587c80476e4SDavid E. O'Brien return wbuf; 588c80476e4SDavid E. O'Brien } 589c80476e4SDavid E. O'Brien return NULL; 590c80476e4SDavid E. O'Brien } 591c80476e4SDavid E. O'Brien 592c80476e4SDavid E. O'Brien void 593c80476e4SDavid E. O'Brien /*ARGSUSED*/ 594c80476e4SDavid E. O'Brien dolog(v, c) 595c80476e4SDavid E. O'Brien Char **v; 596c80476e4SDavid E. O'Brien struct command *c; 597c80476e4SDavid E. O'Brien { 598c80476e4SDavid E. O'Brien struct who *wp; 599c80476e4SDavid E. O'Brien struct varent *vp; 600c80476e4SDavid E. O'Brien 601c80476e4SDavid E. O'Brien USE(v); 602c80476e4SDavid E. O'Brien USE(c); 603c80476e4SDavid E. O'Brien vp = adrof(STRwatch); /* lint insists vp isn't used unless we */ 604c80476e4SDavid E. O'Brien if (vp == NULL) /* unless we assign it outside the if */ 605c80476e4SDavid E. O'Brien stderror(ERR_NOWATCH); 606c80476e4SDavid E. O'Brien resetwatch(); 607c80476e4SDavid E. O'Brien wp = whohead.who_next; 608c80476e4SDavid E. O'Brien while (wp->who_next != NULL) { 609c80476e4SDavid E. O'Brien wp->who_name[0] = '\0'; 610c80476e4SDavid E. O'Brien wp = wp->who_next; 611c80476e4SDavid E. O'Brien } 612c80476e4SDavid E. O'Brien } 613c80476e4SDavid E. O'Brien 614c80476e4SDavid E. O'Brien # ifdef UTHOST 6153b6eaa7bSAndrey A. Chernov size_t 6163b6eaa7bSAndrey A. Chernov utmphostsize() 6173b6eaa7bSAndrey A. Chernov { 6183b6eaa7bSAndrey A. Chernov return UTHOSTLEN; 6193b6eaa7bSAndrey A. Chernov } 6203b6eaa7bSAndrey A. Chernov 621c80476e4SDavid E. O'Brien char * 622c80476e4SDavid E. O'Brien utmphost() 623c80476e4SDavid E. O'Brien { 624c80476e4SDavid E. O'Brien char *tty = short2str(varval(STRtty)); 625c80476e4SDavid E. O'Brien struct who *wp; 626c80476e4SDavid E. O'Brien char *host = NULL; 627c80476e4SDavid E. O'Brien 628c80476e4SDavid E. O'Brien watch_login(1); 629c80476e4SDavid E. O'Brien 630c80476e4SDavid E. O'Brien for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) { 631c80476e4SDavid E. O'Brien if (strcmp(tty, wp->who_tty) == 0) 632c80476e4SDavid E. O'Brien host = wp->who_host; 633c80476e4SDavid E. O'Brien wp->who_name[0] = '\0'; 634c80476e4SDavid E. O'Brien } 635c80476e4SDavid E. O'Brien resetwatch(); 636c80476e4SDavid E. O'Brien return host; 637c80476e4SDavid E. O'Brien } 638c80476e4SDavid E. O'Brien # endif /* UTHOST */ 639c80476e4SDavid E. O'Brien 6403b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 641c80476e4SDavid E. O'Brien void add_to_who_list(name, mach_nm) 642c80476e4SDavid E. O'Brien char *name; 643c80476e4SDavid E. O'Brien char *mach_nm; 644c80476e4SDavid E. O'Brien { 645c80476e4SDavid E. O'Brien 646c80476e4SDavid E. O'Brien struct who *wp, *wpnew; 647c80476e4SDavid E. O'Brien int comp = -1; 648c80476e4SDavid E. O'Brien 649c80476e4SDavid E. O'Brien wp = whohead.who_next; 650c80476e4SDavid E. O'Brien while (wp->who_next && (comp = strncmp(wp->who_tty,mach_nm,UTLINLEN)) < 0) 651c80476e4SDavid E. O'Brien wp = wp->who_next;/* find that tty! */ 652c80476e4SDavid E. O'Brien 653c80476e4SDavid E. O'Brien if (wp->who_next && comp == 0) { /* found the tty... */ 654c80476e4SDavid E. O'Brien 655c80476e4SDavid E. O'Brien if (*name == '\0') { 656c80476e4SDavid E. O'Brien wp->who_time = 0; 657c80476e4SDavid E. O'Brien wp->who_status = OFFLINE; 658c80476e4SDavid E. O'Brien } 659c80476e4SDavid E. O'Brien else if (strncmp(name, wp->who_name, UTNAMLEN) == 0) { 660c80476e4SDavid E. O'Brien /* someone is logged in */ 661c80476e4SDavid E. O'Brien wp->who_time = 0; 662c80476e4SDavid E. O'Brien wp->who_status = 0; /* same guy */ 663c80476e4SDavid E. O'Brien } 664c80476e4SDavid E. O'Brien else { 665c80476e4SDavid E. O'Brien (void) strncpy(wp->who_new, name, UTNAMLEN); 666c80476e4SDavid E. O'Brien wp->who_time = 0; 667c80476e4SDavid E. O'Brien if (wp->who_name[0] == '\0') 668c80476e4SDavid E. O'Brien wp->who_status = ONLINE; 669c80476e4SDavid E. O'Brien else 670c80476e4SDavid E. O'Brien wp->who_status = CHANGED; 671c80476e4SDavid E. O'Brien } 672c80476e4SDavid E. O'Brien } 673c80476e4SDavid E. O'Brien else { 674c80476e4SDavid E. O'Brien wpnew = (struct who *) xcalloc(1, sizeof *wpnew); 675c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_tty, mach_nm, UTLINLEN); 676c80476e4SDavid E. O'Brien wpnew->who_time = 0; 677c80476e4SDavid E. O'Brien if (*name == '\0') 678c80476e4SDavid E. O'Brien wpnew->who_status = OFFLINE; 679c80476e4SDavid E. O'Brien else { 680c80476e4SDavid E. O'Brien (void) strncpy(wpnew->who_new, name, UTNAMLEN); 681c80476e4SDavid E. O'Brien wpnew->who_status = ONLINE; 682c80476e4SDavid E. O'Brien } 683c80476e4SDavid E. O'Brien #ifdef WHODEBUG 684c80476e4SDavid E. O'Brien debugwholist(wpnew, wp); 685c80476e4SDavid E. O'Brien #endif /* WHODEBUG */ 686c80476e4SDavid E. O'Brien 687c80476e4SDavid E. O'Brien wpnew->who_next = wp; /* link in a new 'who' */ 688c80476e4SDavid E. O'Brien wpnew->who_prev = wp->who_prev; 689c80476e4SDavid E. O'Brien wpnew->who_prev->who_next = wpnew; 690c80476e4SDavid E. O'Brien wp->who_prev = wpnew; /* linked in now */ 691c80476e4SDavid E. O'Brien } 692c80476e4SDavid E. O'Brien } 6933b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 694c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */ 695