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