xref: /freebsd/contrib/tcsh/tc.who.c (revision 2930157267fc56387bb43acf5bb441a84ff6e765)
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