xref: /dragonfly/contrib/tcsh-6/tc.who.c (revision d6ab524c)
17d8fb588SMatthias Schmidt /*
27d8fb588SMatthias Schmidt  * tc.who.c: Watch logins and logouts...
37d8fb588SMatthias Schmidt  */
47d8fb588SMatthias Schmidt /*-
57d8fb588SMatthias Schmidt  * Copyright (c) 1980, 1991 The Regents of the University of California.
67d8fb588SMatthias Schmidt  * All rights reserved.
77d8fb588SMatthias Schmidt  *
87d8fb588SMatthias Schmidt  * Redistribution and use in source and binary forms, with or without
97d8fb588SMatthias Schmidt  * modification, are permitted provided that the following conditions
107d8fb588SMatthias Schmidt  * are met:
117d8fb588SMatthias Schmidt  * 1. Redistributions of source code must retain the above copyright
127d8fb588SMatthias Schmidt  *    notice, this list of conditions and the following disclaimer.
137d8fb588SMatthias Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
147d8fb588SMatthias Schmidt  *    notice, this list of conditions and the following disclaimer in the
157d8fb588SMatthias Schmidt  *    documentation and/or other materials provided with the distribution.
167d8fb588SMatthias Schmidt  * 3. Neither the name of the University nor the names of its contributors
177d8fb588SMatthias Schmidt  *    may be used to endorse or promote products derived from this software
187d8fb588SMatthias Schmidt  *    without specific prior written permission.
197d8fb588SMatthias Schmidt  *
207d8fb588SMatthias Schmidt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217d8fb588SMatthias Schmidt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227d8fb588SMatthias Schmidt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237d8fb588SMatthias Schmidt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247d8fb588SMatthias Schmidt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257d8fb588SMatthias Schmidt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267d8fb588SMatthias Schmidt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277d8fb588SMatthias Schmidt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287d8fb588SMatthias Schmidt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297d8fb588SMatthias Schmidt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307d8fb588SMatthias Schmidt  * SUCH DAMAGE.
317d8fb588SMatthias Schmidt  */
327d8fb588SMatthias Schmidt #include "sh.h"
337d8fb588SMatthias Schmidt #include "tc.h"
347d8fb588SMatthias Schmidt 
357d8fb588SMatthias Schmidt #ifndef HAVENOUTMP
367d8fb588SMatthias Schmidt /*
377d8fb588SMatthias Schmidt  * kfk 26 Jan 1984 - for login watch functions.
387d8fb588SMatthias Schmidt  */
397d8fb588SMatthias Schmidt #include <ctype.h>
407d8fb588SMatthias Schmidt 
417d8fb588SMatthias Schmidt #ifdef HAVE_UTMPX_H
427d8fb588SMatthias Schmidt # include <utmpx.h>
4394afa86dSJohn Marino # define UTNAMLEN	sizeof(((struct utmpx *) 0)->ut_name)
4494afa86dSJohn Marino # define UTLINLEN	sizeof(((struct utmpx *) 0)->ut_line)
4594afa86dSJohn Marino # ifdef HAVE_STRUCT_UTMPX_UT_HOST
4694afa86dSJohn Marino #  define UTHOSTLEN	sizeof(((struct utmpx *) 0)->ut_host)
4794afa86dSJohn Marino # endif
487d8fb588SMatthias Schmidt /* I just redefine a few words here.  Changing every occurrence below
497d8fb588SMatthias Schmidt  * seems like too much of work.  All UTMP functions have equivalent
507d8fb588SMatthias Schmidt  * UTMPX counterparts, so they can be added all here when needed.
517d8fb588SMatthias Schmidt  * Kimmo Suominen, Oct 14 1991
527d8fb588SMatthias Schmidt  */
537d8fb588SMatthias Schmidt # if defined(__UTMPX_FILE) && !defined(UTMPX_FILE)
547d8fb588SMatthias Schmidt #  define TCSH_PATH_UTMP __UTMPX_FILE
557d8fb588SMatthias Schmidt # elif defined(_PATH_UTMPX)
567d8fb588SMatthias Schmidt #  define TCSH_PATH_UTMP _PATH_UTMPX
577d8fb588SMatthias Schmidt # elif defined(UTMPX_FILE)
587d8fb588SMatthias Schmidt #  define TCSH_PATH_UTMP UTMPX_FILE
5994afa86dSJohn Marino # elif __FreeBSD_version >= 900000
6094afa86dSJohn Marino #  /* Why isn't this defined somewhere? */
6194afa86dSJohn Marino #  define TCSH_PATH_UTMP "/var/run/utx.active"
6294afa86dSJohn Marino # elif defined(__hpux)
6394afa86dSJohn Marino #  define TCSH_PATH_UTMP "/etc/utmpx"
6460962bbcSJohn Marino # elif defined(IBMAIX) && defined(UTMP_FILE)
6560962bbcSJohn Marino #  define TCSH_PATH_UTMP UTMP_FILE
6694afa86dSJohn Marino # endif
6794afa86dSJohn Marino # if defined(TCSH_PATH_UTMP) || !defined(HAVE_UTMP_H)
687d8fb588SMatthias Schmidt #  define utmp utmpx
6994afa86dSJohn Marino #  define TCSH_USE_UTMPX
7094afa86dSJohn Marino #  if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT)
7194afa86dSJohn Marino #   define getutent getutxent
7294afa86dSJohn Marino #   define setutent setutxent
7394afa86dSJohn Marino #   define endutent endutxent
7494afa86dSJohn Marino #  endif /* HAVE_GETUTENT || HAVE_GETUTXENT */
7594afa86dSJohn Marino #  if defined(HAVE_STRUCT_UTMPX_UT_TV)
7694afa86dSJohn Marino #   define ut_time ut_tv.tv_sec
7794afa86dSJohn Marino #  elif defined(HAVE_STRUCT_UTMPX_UT_XTIME)
7894afa86dSJohn Marino #   define ut_time ut_xtime
7994afa86dSJohn Marino #  endif
8094afa86dSJohn Marino #  if defined(HAVE_STRUCT_UTMPX_UT_USER)
8194afa86dSJohn Marino #   define ut_name ut_user
8294afa86dSJohn Marino #  endif
8394afa86dSJohn Marino # endif /* TCSH_PATH_UTMP || !HAVE_UTMP_H */
8494afa86dSJohn Marino #endif /* HAVE_UTMPX_H */
8594afa86dSJohn Marino 
8694afa86dSJohn Marino #if !defined(TCSH_USE_UTMPX) && defined(HAVE_UTMP_H)
8794afa86dSJohn Marino # include <utmp.h>
887d8fb588SMatthias Schmidt # if defined(HAVE_STRUCT_UTMP_UT_TV)
897d8fb588SMatthias Schmidt #  define ut_time ut_tv.tv_sec
907d8fb588SMatthias Schmidt # elif defined(HAVE_STRUCT_UTMP_UT_XTIME)
917d8fb588SMatthias Schmidt #  define ut_time ut_xtime
927d8fb588SMatthias Schmidt # endif
9394afa86dSJohn Marino # if defined(HAVE_STRUCT_UTMP_UT_USER)
947d8fb588SMatthias Schmidt #  define ut_name ut_user
957d8fb588SMatthias Schmidt # endif
967d8fb588SMatthias Schmidt # ifndef BROKEN_CC
977d8fb588SMatthias Schmidt #  define UTNAMLEN	sizeof(((struct utmp *) 0)->ut_name)
987d8fb588SMatthias Schmidt #  define UTLINLEN	sizeof(((struct utmp *) 0)->ut_line)
997d8fb588SMatthias Schmidt #  ifdef HAVE_STRUCT_UTMP_UT_HOST
1007d8fb588SMatthias Schmidt #   ifdef _SEQUENT_
1017d8fb588SMatthias Schmidt #    define UTHOSTLEN	100
1027d8fb588SMatthias Schmidt #   else
1037d8fb588SMatthias Schmidt #    define UTHOSTLEN	sizeof(((struct utmp *) 0)->ut_host)
1047d8fb588SMatthias Schmidt #   endif
1057d8fb588SMatthias Schmidt #  endif	/* HAVE_STRUCT_UTMP_UT_HOST */
1067d8fb588SMatthias Schmidt # else
1077d8fb588SMatthias Schmidt /* give poor cc a little help if it needs it */
1087d8fb588SMatthias Schmidt struct utmp __ut;
1097d8fb588SMatthias Schmidt #  define UTNAMLEN	sizeof(__ut.ut_name)
1107d8fb588SMatthias Schmidt #  define UTLINLEN	sizeof(__ut.ut_line)
1117d8fb588SMatthias Schmidt #  ifdef HAVE_STRUCT_UTMP_UT_HOST
1127d8fb588SMatthias Schmidt #   ifdef _SEQUENT_
1137d8fb588SMatthias Schmidt #    define UTHOSTLEN	100
1147d8fb588SMatthias Schmidt #   else
1157d8fb588SMatthias Schmidt #    define UTHOSTLEN	sizeof(__ut.ut_host)
1167d8fb588SMatthias Schmidt #   endif
1177d8fb588SMatthias Schmidt #  endif /* HAVE_STRUCT_UTMP_UT_HOST */
1187d8fb588SMatthias Schmidt # endif /* BROKEN_CC */
1197d8fb588SMatthias Schmidt # ifndef TCSH_PATH_UTMP
1207d8fb588SMatthias Schmidt #  ifdef UTMP_FILE
1217d8fb588SMatthias Schmidt #   define TCSH_PATH_UTMP UTMP_FILE
1227d8fb588SMatthias Schmidt #  elif defined(_PATH_UTMP)
1237d8fb588SMatthias Schmidt #   define TCSH_PATH_UTMP _PATH_UTMP
1247d8fb588SMatthias Schmidt #  else
1257d8fb588SMatthias Schmidt #   define TCSH_PATH_UTMP "/etc/utmp"
1267d8fb588SMatthias Schmidt #  endif /* UTMP_FILE */
1277d8fb588SMatthias Schmidt # endif /* TCSH_PATH_UTMP */
12894afa86dSJohn Marino #endif /* !TCSH_USE_UTMPX && HAVE_UTMP_H */
1297d8fb588SMatthias Schmidt 
13094afa86dSJohn Marino #ifndef UTNAMLEN
13194afa86dSJohn Marino #define UTNAMLEN 64
13294afa86dSJohn Marino #endif
13394afa86dSJohn Marino #ifndef UTLINLEN
13494afa86dSJohn Marino #define UTLINLEN 64
13594afa86dSJohn Marino #endif
1367d8fb588SMatthias Schmidt 
1377d8fb588SMatthias Schmidt struct who {
1387d8fb588SMatthias Schmidt     struct who *who_next;
1397d8fb588SMatthias Schmidt     struct who *who_prev;
1407d8fb588SMatthias Schmidt     char    who_name[UTNAMLEN + 1];
1417d8fb588SMatthias Schmidt     char    who_new[UTNAMLEN + 1];
1427d8fb588SMatthias Schmidt     char    who_tty[UTLINLEN + 1];
14394afa86dSJohn Marino #ifdef UTHOSTLEN
1447d8fb588SMatthias Schmidt     char    who_host[UTHOSTLEN + 1];
14594afa86dSJohn Marino #endif /* UTHOSTLEN */
1467d8fb588SMatthias Schmidt     time_t  who_time;
1477d8fb588SMatthias Schmidt     int     who_status;
1487d8fb588SMatthias Schmidt };
1497d8fb588SMatthias Schmidt 
1507d8fb588SMatthias Schmidt static struct who whohead, whotail;
1517d8fb588SMatthias Schmidt static time_t watch_period = 0;
1527d8fb588SMatthias Schmidt static time_t stlast = 0;
1537d8fb588SMatthias Schmidt #ifdef WHODEBUG
1547d8fb588SMatthias Schmidt static	void	debugwholist	(struct who *, struct who *);
1557d8fb588SMatthias Schmidt #endif
1567d8fb588SMatthias Schmidt static	void	print_who	(struct who *);
1577d8fb588SMatthias Schmidt 
1587d8fb588SMatthias Schmidt 
1597d8fb588SMatthias Schmidt #define ONLINE		01
1607d8fb588SMatthias Schmidt #define OFFLINE		02
1617d8fb588SMatthias Schmidt #define CHANGED		04
1627d8fb588SMatthias Schmidt #define STMASK		07
1637d8fb588SMatthias Schmidt #define ANNOUNCE	010
1647d8fb588SMatthias Schmidt #define CLEARED		020
1657d8fb588SMatthias Schmidt 
1667d8fb588SMatthias Schmidt /*
1677d8fb588SMatthias Schmidt  * Karl Kleinpaste, 26 Jan 1984.
1687d8fb588SMatthias Schmidt  * Initialize the dummy tty list for login watch.
1697d8fb588SMatthias Schmidt  * This dummy list eliminates boundary conditions
1707d8fb588SMatthias Schmidt  * when doing pointer-chase searches.
1717d8fb588SMatthias Schmidt  */
1727d8fb588SMatthias Schmidt void
initwatch(void)1737d8fb588SMatthias Schmidt initwatch(void)
1747d8fb588SMatthias Schmidt {
1757d8fb588SMatthias Schmidt     whohead.who_next = &whotail;
1767d8fb588SMatthias Schmidt     whotail.who_prev = &whohead;
1777d8fb588SMatthias Schmidt     stlast = 1;
1787d8fb588SMatthias Schmidt #ifdef WHODEBUG
1797d8fb588SMatthias Schmidt     debugwholist(NULL, NULL);
1807d8fb588SMatthias Schmidt #endif /* WHODEBUG */
1817d8fb588SMatthias Schmidt }
1827d8fb588SMatthias Schmidt 
1837d8fb588SMatthias Schmidt void
resetwatch(void)1847d8fb588SMatthias Schmidt resetwatch(void)
1857d8fb588SMatthias Schmidt {
1867d8fb588SMatthias Schmidt     watch_period = 0;
1877d8fb588SMatthias Schmidt     stlast = 0;
1887d8fb588SMatthias Schmidt }
1897d8fb588SMatthias Schmidt 
1907d8fb588SMatthias Schmidt /*
1917d8fb588SMatthias Schmidt  * Karl Kleinpaste, 26 Jan 1984.
1927d8fb588SMatthias Schmidt  * Watch /etc/utmp for login/logout changes.
1937d8fb588SMatthias Schmidt  */
1947d8fb588SMatthias Schmidt void
watch_login(int force)1957d8fb588SMatthias Schmidt watch_login(int force)
1967d8fb588SMatthias Schmidt {
1977d8fb588SMatthias Schmidt     int     comp = -1, alldone;
1987d8fb588SMatthias Schmidt     int	    firsttime = stlast == 1;
19994afa86dSJohn Marino #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT)
2007d8fb588SMatthias Schmidt     struct utmp *uptr;
2017d8fb588SMatthias Schmidt #else
2027d8fb588SMatthias Schmidt     int utmpfd;
2037d8fb588SMatthias Schmidt #endif
2047d8fb588SMatthias Schmidt     struct utmp utmp;
2057d8fb588SMatthias Schmidt     struct who *wp, *wpnew;
2067d8fb588SMatthias Schmidt     struct varent *v;
2077d8fb588SMatthias Schmidt     Char  **vp = NULL;
2087d8fb588SMatthias Schmidt     time_t  t, interval = MAILINTVL;
2097d8fb588SMatthias Schmidt     struct stat sta;
2107d8fb588SMatthias Schmidt #if defined(HAVE_STRUCT_UTMP_UT_HOST) && defined(_SEQUENT_)
2117d8fb588SMatthias Schmidt     char   *host, *ut_find_host();
2127d8fb588SMatthias Schmidt #endif
2137d8fb588SMatthias Schmidt #ifdef WINNT_NATIVE
2147d8fb588SMatthias Schmidt     USE(utmp);
2157d8fb588SMatthias Schmidt     USE(utmpfd);
2167d8fb588SMatthias Schmidt     USE(sta);
2177d8fb588SMatthias Schmidt     USE(wpnew);
2187d8fb588SMatthias Schmidt #endif /* WINNT_NATIVE */
2197d8fb588SMatthias Schmidt 
2207d8fb588SMatthias Schmidt     /* stop SIGINT, lest our login list get trashed. */
2217d8fb588SMatthias Schmidt     pintr_disabled++;
2227d8fb588SMatthias Schmidt     cleanup_push(&pintr_disabled, disabled_cleanup);
2237d8fb588SMatthias Schmidt 
2247d8fb588SMatthias Schmidt     v = adrof(STRwatch);
2257d8fb588SMatthias Schmidt     if ((v == NULL || v->vec == NULL) && !force) {
2267d8fb588SMatthias Schmidt 	cleanup_until(&pintr_disabled);
2277d8fb588SMatthias Schmidt 	return;			/* no names to watch */
2287d8fb588SMatthias Schmidt     }
2297d8fb588SMatthias Schmidt     if (!force) {
2307d8fb588SMatthias Schmidt 	trim(vp = v->vec);
2317d8fb588SMatthias Schmidt 	if (blklen(vp) % 2)		/* odd # args: 1st == # minutes. */
2327d8fb588SMatthias Schmidt 	    interval = (number(*vp)) ? (getn(*vp++) * 60) : MAILINTVL;
2337d8fb588SMatthias Schmidt     }
2347d8fb588SMatthias Schmidt     else
2357d8fb588SMatthias Schmidt 	interval = 0;
2367d8fb588SMatthias Schmidt 
2377d8fb588SMatthias Schmidt     (void) time(&t);
2387d8fb588SMatthias Schmidt     if (t - watch_period < interval) {
2397d8fb588SMatthias Schmidt 	cleanup_until(&pintr_disabled);
2407d8fb588SMatthias Schmidt 	return;			/* not long enough yet... */
2417d8fb588SMatthias Schmidt     }
2427d8fb588SMatthias Schmidt     watch_period = t;
243653fab9eSSascha Wildner #ifndef WINNT_NATIVE
2447d8fb588SMatthias Schmidt     /*
2457d8fb588SMatthias Schmidt      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
2467d8fb588SMatthias Schmidt      * Don't open utmp all the time, stat it first...
2477d8fb588SMatthias Schmidt      */
2487d8fb588SMatthias Schmidt     if (stat(TCSH_PATH_UTMP, &sta)) {
2497d8fb588SMatthias Schmidt 	if (!force)
2507d8fb588SMatthias Schmidt 	    xprintf(CGETS(26, 1,
2517d8fb588SMatthias Schmidt 			  "cannot stat %s.  Please \"unset watch\".\n"),
2527d8fb588SMatthias Schmidt 		    TCSH_PATH_UTMP);
2537d8fb588SMatthias Schmidt 	cleanup_until(&pintr_disabled);
2547d8fb588SMatthias Schmidt 	return;
2557d8fb588SMatthias Schmidt     }
2567d8fb588SMatthias Schmidt     if (stlast == sta.st_mtime) {
2577d8fb588SMatthias Schmidt 	cleanup_until(&pintr_disabled);
2587d8fb588SMatthias Schmidt 	return;
2597d8fb588SMatthias Schmidt     }
2607d8fb588SMatthias Schmidt     stlast = sta.st_mtime;
26194afa86dSJohn Marino #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT)
2627d8fb588SMatthias Schmidt     setutent();
2637d8fb588SMatthias Schmidt #else
2647d8fb588SMatthias Schmidt     if ((utmpfd = xopen(TCSH_PATH_UTMP, O_RDONLY|O_LARGEFILE)) < 0) {
2657d8fb588SMatthias Schmidt 	if (!force)
2667d8fb588SMatthias Schmidt 	    xprintf(CGETS(26, 2,
2677d8fb588SMatthias Schmidt 			  "%s cannot be opened.  Please \"unset watch\".\n"),
2687d8fb588SMatthias Schmidt 		    TCSH_PATH_UTMP);
2697d8fb588SMatthias Schmidt 	cleanup_until(&pintr_disabled);
2707d8fb588SMatthias Schmidt 	return;
2717d8fb588SMatthias Schmidt     }
2727d8fb588SMatthias Schmidt     cleanup_push(&utmpfd, open_cleanup);
2737d8fb588SMatthias Schmidt #endif
2747d8fb588SMatthias Schmidt 
2757d8fb588SMatthias Schmidt     /*
2767d8fb588SMatthias Schmidt      * xterm clears the entire utmp entry - mark everyone on the status list
2777d8fb588SMatthias Schmidt      * OFFLINE or we won't notice X "logouts"
2787d8fb588SMatthias Schmidt      */
2797d8fb588SMatthias Schmidt     for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next)
2807d8fb588SMatthias Schmidt 	wp->who_status = OFFLINE | CLEARED;
2817d8fb588SMatthias Schmidt 
2827d8fb588SMatthias Schmidt     /*
2837d8fb588SMatthias Schmidt      * Read in the utmp file, sort the entries, and update existing entries or
2847d8fb588SMatthias Schmidt      * add new entries to the status list.
2857d8fb588SMatthias Schmidt      */
28694afa86dSJohn Marino #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT)
2877d8fb588SMatthias Schmidt     while ((uptr = getutent()) != NULL) {
2887d8fb588SMatthias Schmidt         memcpy(&utmp, uptr, sizeof (utmp));
2897d8fb588SMatthias Schmidt #else
2907d8fb588SMatthias Schmidt     while (xread(utmpfd, &utmp, sizeof utmp) == sizeof utmp) {
2917d8fb588SMatthias Schmidt #endif
2927d8fb588SMatthias Schmidt 
2937d8fb588SMatthias Schmidt # ifdef DEAD_PROCESS
2947d8fb588SMatthias Schmidt #  ifndef IRIS4D
2957d8fb588SMatthias Schmidt 	if (utmp.ut_type != USER_PROCESS)
2967d8fb588SMatthias Schmidt 	    continue;
2977d8fb588SMatthias Schmidt #  else
2987d8fb588SMatthias Schmidt 	/* Why is that? Cause the utmp file is always corrupted??? */
2997d8fb588SMatthias Schmidt 	if (utmp.ut_type != USER_PROCESS && utmp.ut_type != DEAD_PROCESS)
3007d8fb588SMatthias Schmidt 	    continue;
3017d8fb588SMatthias Schmidt #  endif /* IRIS4D */
3027d8fb588SMatthias Schmidt # endif /* DEAD_PROCESS */
3037d8fb588SMatthias Schmidt 
3047d8fb588SMatthias Schmidt 	if (utmp.ut_name[0] == '\0' && utmp.ut_line[0] == '\0')
3057d8fb588SMatthias Schmidt 	    continue;	/* completely void entry */
3067d8fb588SMatthias Schmidt # ifdef DEAD_PROCESS
3077d8fb588SMatthias Schmidt 	if (utmp.ut_type == DEAD_PROCESS && utmp.ut_line[0] == '\0')
3087d8fb588SMatthias Schmidt 	    continue;
3097d8fb588SMatthias Schmidt # endif /* DEAD_PROCESS */
3107d8fb588SMatthias Schmidt 	wp = whohead.who_next;
3117d8fb588SMatthias Schmidt 	while (wp->who_next && (comp = strncmp(wp->who_tty, utmp.ut_line, UTLINLEN)) < 0)
3127d8fb588SMatthias Schmidt 	    wp = wp->who_next;/* find that tty! */
3137d8fb588SMatthias Schmidt 
3147d8fb588SMatthias Schmidt 	if (wp->who_next && comp == 0) {	/* found the tty... */
3157d8fb588SMatthias Schmidt 	    if (utmp.ut_time < wp->who_time)
3167d8fb588SMatthias Schmidt 	        continue;
3177d8fb588SMatthias Schmidt # ifdef DEAD_PROCESS
3187d8fb588SMatthias Schmidt 	    if (utmp.ut_type == DEAD_PROCESS) {
3197d8fb588SMatthias Schmidt 		wp->who_time = utmp.ut_time;
3207d8fb588SMatthias Schmidt 		wp->who_status = OFFLINE;
3217d8fb588SMatthias Schmidt 	    }
3227d8fb588SMatthias Schmidt 	    else
3237d8fb588SMatthias Schmidt # endif /* DEAD_PROCESS */
3247d8fb588SMatthias Schmidt 	    if (utmp.ut_name[0] == '\0') {
3257d8fb588SMatthias Schmidt 		wp->who_time = utmp.ut_time;
3267d8fb588SMatthias Schmidt 		wp->who_status = OFFLINE;
3277d8fb588SMatthias Schmidt 	    }
3287d8fb588SMatthias Schmidt 	    else if (strncmp(utmp.ut_name, wp->who_name, UTNAMLEN) == 0) {
3297d8fb588SMatthias Schmidt 		/* someone is logged in */
3307d8fb588SMatthias Schmidt 		wp->who_time = utmp.ut_time;
3317d8fb588SMatthias Schmidt 		wp->who_status = ONLINE | ANNOUNCE;	/* same guy */
3327d8fb588SMatthias Schmidt 	    }
3337d8fb588SMatthias Schmidt 	    else {
3347d8fb588SMatthias Schmidt 		(void) strncpy(wp->who_new, utmp.ut_name, UTNAMLEN);
33594afa86dSJohn Marino # ifdef UTHOSTLEN
3367d8fb588SMatthias Schmidt #  ifdef _SEQUENT_
3377d8fb588SMatthias Schmidt 		host = ut_find_host(wp->who_tty);
3387d8fb588SMatthias Schmidt 		if (host)
3397d8fb588SMatthias Schmidt 		    (void) strncpy(wp->who_host, host, UTHOSTLEN);
3407d8fb588SMatthias Schmidt 		else
3417d8fb588SMatthias Schmidt 		    wp->who_host[0] = 0;
3427d8fb588SMatthias Schmidt #  else
3437d8fb588SMatthias Schmidt 		(void) strncpy(wp->who_host, utmp.ut_host, UTHOSTLEN);
3447d8fb588SMatthias Schmidt #  endif
34594afa86dSJohn Marino # endif /* UTHOSTLEN */
3467d8fb588SMatthias Schmidt 		wp->who_time = utmp.ut_time;
3477d8fb588SMatthias Schmidt 		if (wp->who_name[0] == '\0')
3487d8fb588SMatthias Schmidt 		    wp->who_status = ONLINE;
3497d8fb588SMatthias Schmidt 		else
3507d8fb588SMatthias Schmidt 		    wp->who_status = CHANGED;
3517d8fb588SMatthias Schmidt 	    }
3527d8fb588SMatthias Schmidt 	}
3537d8fb588SMatthias Schmidt 	else {		/* new tty in utmp */
3547d8fb588SMatthias Schmidt 	    wpnew = xcalloc(1, sizeof *wpnew);
3557d8fb588SMatthias Schmidt 	    (void) strncpy(wpnew->who_tty, utmp.ut_line, UTLINLEN);
35694afa86dSJohn Marino # ifdef UTHOSTLEN
3577d8fb588SMatthias Schmidt #  ifdef _SEQUENT_
3587d8fb588SMatthias Schmidt 	    host = ut_find_host(wpnew->who_tty);
3597d8fb588SMatthias Schmidt 	    if (host)
3607d8fb588SMatthias Schmidt 		(void) strncpy(wpnew->who_host, host, UTHOSTLEN);
3617d8fb588SMatthias Schmidt 	    else
3627d8fb588SMatthias Schmidt 		wpnew->who_host[0] = 0;
3637d8fb588SMatthias Schmidt #  else
3647d8fb588SMatthias Schmidt 	    (void) strncpy(wpnew->who_host, utmp.ut_host, UTHOSTLEN);
3657d8fb588SMatthias Schmidt #  endif
36694afa86dSJohn Marino # endif /* UTHOSTLEN */
3677d8fb588SMatthias Schmidt 	    wpnew->who_time = utmp.ut_time;
3687d8fb588SMatthias Schmidt # ifdef DEAD_PROCESS
3697d8fb588SMatthias Schmidt 	    if (utmp.ut_type == DEAD_PROCESS)
3707d8fb588SMatthias Schmidt 		wpnew->who_status = OFFLINE;
3717d8fb588SMatthias Schmidt 	    else
3727d8fb588SMatthias Schmidt # endif /* DEAD_PROCESS */
3737d8fb588SMatthias Schmidt 	    if (utmp.ut_name[0] == '\0')
3747d8fb588SMatthias Schmidt 		wpnew->who_status = OFFLINE;
3757d8fb588SMatthias Schmidt 	    else {
3767d8fb588SMatthias Schmidt 		(void) strncpy(wpnew->who_new, utmp.ut_name, UTNAMLEN);
3777d8fb588SMatthias Schmidt 		wpnew->who_status = ONLINE;
3787d8fb588SMatthias Schmidt 	    }
3797d8fb588SMatthias Schmidt # ifdef WHODEBUG
3807d8fb588SMatthias Schmidt 	    debugwholist(wpnew, wp);
3817d8fb588SMatthias Schmidt # endif /* WHODEBUG */
3827d8fb588SMatthias Schmidt 
3837d8fb588SMatthias Schmidt 	    wpnew->who_next = wp;	/* link in a new 'who' */
3847d8fb588SMatthias Schmidt 	    wpnew->who_prev = wp->who_prev;
3857d8fb588SMatthias Schmidt 	    wpnew->who_prev->who_next = wpnew;
3867d8fb588SMatthias Schmidt 	    wp->who_prev = wpnew;	/* linked in now */
3877d8fb588SMatthias Schmidt 	}
3887d8fb588SMatthias Schmidt     }
38994afa86dSJohn Marino #if defined(HAVE_GETUTENT) || defined(HAVE_GETUTXENT)
3907d8fb588SMatthias Schmidt     endutent();
3917d8fb588SMatthias Schmidt #else
3927d8fb588SMatthias Schmidt     cleanup_until(&utmpfd);
3937d8fb588SMatthias Schmidt #endif
3947d8fb588SMatthias Schmidt #endif /* !WINNT_NATIVE */
3957d8fb588SMatthias Schmidt 
3967d8fb588SMatthias Schmidt     if (force || vp == NULL) {
3977d8fb588SMatthias Schmidt 	cleanup_until(&pintr_disabled);
3987d8fb588SMatthias Schmidt 	return;
3997d8fb588SMatthias Schmidt     }
4007d8fb588SMatthias Schmidt 
4017d8fb588SMatthias Schmidt     /*
4027d8fb588SMatthias Schmidt      * The state of all logins is now known, so we can search the user's list
4037d8fb588SMatthias Schmidt      * of watchables to print the interesting ones.
4047d8fb588SMatthias Schmidt      */
4057d8fb588SMatthias Schmidt     for (alldone = 0; !alldone && *vp != NULL && **vp != '\0' &&
4067d8fb588SMatthias Schmidt 	 *(vp + 1) != NULL && **(vp + 1) != '\0';
4077d8fb588SMatthias Schmidt 	 vp += 2) {		/* args used in pairs... */
4087d8fb588SMatthias Schmidt 
4097d8fb588SMatthias Schmidt 	if (eq(*vp, STRany) && eq(*(vp + 1), STRany))
4107d8fb588SMatthias Schmidt 	    alldone = 1;
4117d8fb588SMatthias Schmidt 
4127d8fb588SMatthias Schmidt 	for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
4137d8fb588SMatthias Schmidt 	    if (wp->who_status & ANNOUNCE ||
4147d8fb588SMatthias Schmidt 		(!eq(STRany, vp[0]) &&
4157d8fb588SMatthias Schmidt 		 !Gmatch(str2short(wp->who_name), vp[0]) &&
4167d8fb588SMatthias Schmidt 		 !Gmatch(str2short(wp->who_new),  vp[0])) ||
4177d8fb588SMatthias Schmidt 		(!Gmatch(str2short(wp->who_tty),  vp[1]) &&
4187d8fb588SMatthias Schmidt 		 !eq(STRany, vp[1])))
4197d8fb588SMatthias Schmidt 		continue;	/* entry doesn't qualify */
4207d8fb588SMatthias Schmidt 	    /* already printed or not right one to print */
4217d8fb588SMatthias Schmidt 
4227d8fb588SMatthias Schmidt 
4237d8fb588SMatthias Schmidt 	    if (wp->who_status & CLEARED) {/* utmp entry was cleared */
4247d8fb588SMatthias Schmidt 		wp->who_time = watch_period;
4257d8fb588SMatthias Schmidt 		wp->who_status &= ~CLEARED;
4267d8fb588SMatthias Schmidt 	    }
4277d8fb588SMatthias Schmidt 
4287d8fb588SMatthias Schmidt 	    if ((wp->who_status & OFFLINE) &&
4297d8fb588SMatthias Schmidt 		(wp->who_name[0] != '\0')) {
4307d8fb588SMatthias Schmidt 		if (!firsttime)
4317d8fb588SMatthias Schmidt 		    print_who(wp);
4327d8fb588SMatthias Schmidt 		wp->who_name[0] = '\0';
4337d8fb588SMatthias Schmidt 		wp->who_status |= ANNOUNCE;
4347d8fb588SMatthias Schmidt 		continue;
4357d8fb588SMatthias Schmidt 	    }
4367d8fb588SMatthias Schmidt 	    if (wp->who_status & ONLINE) {
4377d8fb588SMatthias Schmidt 		if (!firsttime)
4387d8fb588SMatthias Schmidt 		    print_who(wp);
4397d8fb588SMatthias Schmidt 		(void) strcpy(wp->who_name, wp->who_new);
4407d8fb588SMatthias Schmidt 		wp->who_status |= ANNOUNCE;
4417d8fb588SMatthias Schmidt 		continue;
4427d8fb588SMatthias Schmidt 	    }
4437d8fb588SMatthias Schmidt 	    if (wp->who_status & CHANGED) {
4447d8fb588SMatthias Schmidt 		if (!firsttime)
4457d8fb588SMatthias Schmidt 		    print_who(wp);
4467d8fb588SMatthias Schmidt 		(void) strcpy(wp->who_name, wp->who_new);
4477d8fb588SMatthias Schmidt 		wp->who_status |= ANNOUNCE;
4487d8fb588SMatthias Schmidt 		continue;
4497d8fb588SMatthias Schmidt 	    }
4507d8fb588SMatthias Schmidt 	}
4517d8fb588SMatthias Schmidt     }
4527d8fb588SMatthias Schmidt     cleanup_until(&pintr_disabled);
4537d8fb588SMatthias Schmidt }
4547d8fb588SMatthias Schmidt 
4557d8fb588SMatthias Schmidt #ifdef WHODEBUG
4567d8fb588SMatthias Schmidt static void
4577d8fb588SMatthias Schmidt debugwholist(struct who *new, struct who *wp)
4587d8fb588SMatthias Schmidt {
4597d8fb588SMatthias Schmidt     struct who *a;
4607d8fb588SMatthias Schmidt 
4617d8fb588SMatthias Schmidt     a = whohead.who_next;
4627d8fb588SMatthias Schmidt     while (a->who_next != NULL) {
4637d8fb588SMatthias Schmidt 	xprintf("%s/%s -> ", a->who_name, a->who_tty);
4647d8fb588SMatthias Schmidt 	a = a->who_next;
4657d8fb588SMatthias Schmidt     }
4667d8fb588SMatthias Schmidt     xprintf("TAIL\n");
4677d8fb588SMatthias Schmidt     if (a != &whotail) {
4687d8fb588SMatthias Schmidt 	xprintf(CGETS(26, 3, "BUG! last element is not whotail!\n"));
4697d8fb588SMatthias Schmidt 	abort();
4707d8fb588SMatthias Schmidt     }
4717d8fb588SMatthias Schmidt     a = whotail.who_prev;
4727d8fb588SMatthias Schmidt     xprintf(CGETS(26, 4, "backward: "));
4737d8fb588SMatthias Schmidt     while (a->who_prev != NULL) {
4747d8fb588SMatthias Schmidt 	xprintf("%s/%s -> ", a->who_name, a->who_tty);
4757d8fb588SMatthias Schmidt 	a = a->who_prev;
4767d8fb588SMatthias Schmidt     }
4777d8fb588SMatthias Schmidt     xprintf("HEAD\n");
4787d8fb588SMatthias Schmidt     if (a != &whohead) {
4797d8fb588SMatthias Schmidt 	xprintf(CGETS(26, 5, "BUG! first element is not whohead!\n"));
4807d8fb588SMatthias Schmidt 	abort();
4817d8fb588SMatthias Schmidt     }
4827d8fb588SMatthias Schmidt     if (new)
4837d8fb588SMatthias Schmidt 	xprintf(CGETS(26, 6, "new: %s/%s\n"), new->who_name, new->who_tty);
4847d8fb588SMatthias Schmidt     if (wp)
4857d8fb588SMatthias Schmidt 	xprintf("wp: %s/%s\n", wp->who_name, wp->who_tty);
4867d8fb588SMatthias Schmidt }
4877d8fb588SMatthias Schmidt #endif /* WHODEBUG */
4887d8fb588SMatthias Schmidt 
4897d8fb588SMatthias Schmidt 
4907d8fb588SMatthias Schmidt static void
4917d8fb588SMatthias Schmidt print_who(struct who *wp)
4927d8fb588SMatthias Schmidt {
49394afa86dSJohn Marino #ifdef UTHOSTLEN
4947d8fb588SMatthias Schmidt     Char   *cp = str2short(CGETS(26, 7, "%n has %a %l from %m."));
4957d8fb588SMatthias Schmidt #else
4967d8fb588SMatthias Schmidt     Char   *cp = str2short(CGETS(26, 8, "%n has %a %l."));
49794afa86dSJohn Marino #endif /* UTHOSTLEN */
4987d8fb588SMatthias Schmidt     struct varent *vp = adrof(STRwho);
4997d8fb588SMatthias Schmidt     Char *str;
5007d8fb588SMatthias Schmidt 
5017d8fb588SMatthias Schmidt     if (vp && vp->vec && vp->vec[0])
5027d8fb588SMatthias Schmidt 	cp = vp->vec[0];
5037d8fb588SMatthias Schmidt 
5047d8fb588SMatthias Schmidt     str = tprintf(FMT_WHO, cp, NULL, wp->who_time, wp);
5057d8fb588SMatthias Schmidt     cleanup_push(str, xfree);
5067d8fb588SMatthias Schmidt     for (cp = str; *cp;)
5077d8fb588SMatthias Schmidt 	xputwchar(*cp++);
5087d8fb588SMatthias Schmidt     cleanup_until(str);
5097d8fb588SMatthias Schmidt     xputchar('\n');
5107d8fb588SMatthias Schmidt } /* end print_who */
5117d8fb588SMatthias Schmidt 
5127d8fb588SMatthias Schmidt 
5137d8fb588SMatthias Schmidt char *
5147d8fb588SMatthias Schmidt who_info(ptr_t ptr, int c)
5157d8fb588SMatthias Schmidt {
5167d8fb588SMatthias Schmidt     struct who *wp = ptr;
5177d8fb588SMatthias Schmidt     char *wbuf;
51894afa86dSJohn Marino #ifdef UTHOSTLEN
5197d8fb588SMatthias Schmidt     char *wb;
5207d8fb588SMatthias Schmidt     int flg;
5217d8fb588SMatthias Schmidt     char *pb;
52294afa86dSJohn Marino #endif /* UTHOSTLEN */
5237d8fb588SMatthias Schmidt 
5247d8fb588SMatthias Schmidt     switch (c) {
5257d8fb588SMatthias Schmidt     case 'n':		/* user name */
5267d8fb588SMatthias Schmidt 	switch (wp->who_status & STMASK) {
5277d8fb588SMatthias Schmidt 	case ONLINE:
5287d8fb588SMatthias Schmidt 	case CHANGED:
5297d8fb588SMatthias Schmidt 	    return strsave(wp->who_new);
5307d8fb588SMatthias Schmidt 	case OFFLINE:
5317d8fb588SMatthias Schmidt 	    return strsave(wp->who_name);
5327d8fb588SMatthias Schmidt 	default:
5337d8fb588SMatthias Schmidt 	    break;
5347d8fb588SMatthias Schmidt 	}
5357d8fb588SMatthias Schmidt 	break;
5367d8fb588SMatthias Schmidt 
5377d8fb588SMatthias Schmidt     case 'a':
5387d8fb588SMatthias Schmidt 	switch (wp->who_status & STMASK) {
5397d8fb588SMatthias Schmidt 	case ONLINE:
5407d8fb588SMatthias Schmidt 	    return strsave(CGETS(26, 9, "logged on"));
5417d8fb588SMatthias Schmidt 	case OFFLINE:
5427d8fb588SMatthias Schmidt 	    return strsave(CGETS(26, 10, "logged off"));
5437d8fb588SMatthias Schmidt 	case CHANGED:
5447d8fb588SMatthias Schmidt 	    return xasprintf(CGETS(26, 11, "replaced %s on"), wp->who_name);
5457d8fb588SMatthias Schmidt 	default:
5467d8fb588SMatthias Schmidt 	    break;
5477d8fb588SMatthias Schmidt 	}
5487d8fb588SMatthias Schmidt 	break;
5497d8fb588SMatthias Schmidt 
55094afa86dSJohn Marino #ifdef UTHOSTLEN
5517d8fb588SMatthias Schmidt     case 'm':
5527d8fb588SMatthias Schmidt 	if (wp->who_host[0] == '\0')
5537d8fb588SMatthias Schmidt 	    return strsave(CGETS(26, 12, "local"));
5547d8fb588SMatthias Schmidt 	else {
5557d8fb588SMatthias Schmidt 	    pb = wp->who_host;
5567d8fb588SMatthias Schmidt 	    wbuf = xmalloc(strlen(pb) + 1);
5577d8fb588SMatthias Schmidt 	    wb = wbuf;
5587d8fb588SMatthias Schmidt 	    /* the ':' stuff is for <host>:<display>.<screen> */
5597d8fb588SMatthias Schmidt 	    for (flg = isdigit((unsigned char)*pb) ? '\0' : '.';
5607d8fb588SMatthias Schmidt 		 *pb != '\0' && (*pb != flg || ((pb = strchr(pb, ':')) != 0));
5617d8fb588SMatthias Schmidt 		 pb++) {
5627d8fb588SMatthias Schmidt 		if (*pb == ':')
5637d8fb588SMatthias Schmidt 		    flg = '\0';
5647d8fb588SMatthias Schmidt 		*wb++ = isupper((unsigned char)*pb) ?
5657d8fb588SMatthias Schmidt 		    tolower((unsigned char)*pb) : *pb;
5667d8fb588SMatthias Schmidt 	    }
5677d8fb588SMatthias Schmidt 	    *wb = '\0';
5687d8fb588SMatthias Schmidt 	    return wbuf;
5697d8fb588SMatthias Schmidt 	}
5707d8fb588SMatthias Schmidt 
5717d8fb588SMatthias Schmidt     case 'M':
5727d8fb588SMatthias Schmidt 	if (wp->who_host[0] == '\0')
5737d8fb588SMatthias Schmidt 	    return strsave(CGETS(26, 12, "local"));
5747d8fb588SMatthias Schmidt 	else {
5757d8fb588SMatthias Schmidt 	    pb = wp->who_host;
5767d8fb588SMatthias Schmidt 	    wbuf = xmalloc(strlen(pb) + 1);
5777d8fb588SMatthias Schmidt 	    wb = wbuf;
5787d8fb588SMatthias Schmidt 	    for (; *pb != '\0'; pb++)
5797d8fb588SMatthias Schmidt 		*wb++ = isupper((unsigned char)*pb) ?
5807d8fb588SMatthias Schmidt 		    tolower((unsigned char)*pb) : *pb;
5817d8fb588SMatthias Schmidt 	    *wb = '\0';
5827d8fb588SMatthias Schmidt 	    return wbuf;
5837d8fb588SMatthias Schmidt 	}
58494afa86dSJohn Marino #endif /* UTHOSTLEN */
5857d8fb588SMatthias Schmidt 
5867d8fb588SMatthias Schmidt     case 'l':
5877d8fb588SMatthias Schmidt 	return strsave(wp->who_tty);
5887d8fb588SMatthias Schmidt 
5897d8fb588SMatthias Schmidt     default:
5907d8fb588SMatthias Schmidt 	wbuf = xmalloc(3);
5917d8fb588SMatthias Schmidt 	wbuf[0] = '%';
5927d8fb588SMatthias Schmidt 	wbuf[1] = (char) c;
5937d8fb588SMatthias Schmidt 	wbuf[2] = '\0';
5947d8fb588SMatthias Schmidt 	return wbuf;
5957d8fb588SMatthias Schmidt     }
5967d8fb588SMatthias Schmidt     return NULL;
5977d8fb588SMatthias Schmidt }
5987d8fb588SMatthias Schmidt 
5997d8fb588SMatthias Schmidt void
6007d8fb588SMatthias Schmidt /*ARGSUSED*/
6017d8fb588SMatthias Schmidt dolog(Char **v, struct command *c)
6027d8fb588SMatthias Schmidt {
6037d8fb588SMatthias Schmidt     struct who *wp;
6047d8fb588SMatthias Schmidt     struct varent *vp;
6057d8fb588SMatthias Schmidt 
6067d8fb588SMatthias Schmidt     USE(v);
6077d8fb588SMatthias Schmidt     USE(c);
6087d8fb588SMatthias Schmidt     vp = adrof(STRwatch);	/* lint insists vp isn't used unless we */
6097d8fb588SMatthias Schmidt     if (vp == NULL)		/* unless we assign it outside the if */
6107d8fb588SMatthias Schmidt 	stderror(ERR_NOWATCH);
6117d8fb588SMatthias Schmidt     resetwatch();
6127d8fb588SMatthias Schmidt     wp = whohead.who_next;
6137d8fb588SMatthias Schmidt     while (wp->who_next != NULL) {
6147d8fb588SMatthias Schmidt 	wp->who_name[0] = '\0';
6157d8fb588SMatthias Schmidt 	wp = wp->who_next;
6167d8fb588SMatthias Schmidt     }
6177d8fb588SMatthias Schmidt }
6187d8fb588SMatthias Schmidt 
61994afa86dSJohn Marino # ifdef UTHOSTLEN
6207d8fb588SMatthias Schmidt size_t
6217d8fb588SMatthias Schmidt utmphostsize(void)
6227d8fb588SMatthias Schmidt {
6237d8fb588SMatthias Schmidt     return UTHOSTLEN;
6247d8fb588SMatthias Schmidt }
6257d8fb588SMatthias Schmidt 
6267d8fb588SMatthias Schmidt char *
6277d8fb588SMatthias Schmidt utmphost(void)
6287d8fb588SMatthias Schmidt {
6297d8fb588SMatthias Schmidt     char *tty = short2str(varval(STRtty));
6307d8fb588SMatthias Schmidt     struct who *wp;
6317d8fb588SMatthias Schmidt     char *host = NULL;
6327d8fb588SMatthias Schmidt 
6337d8fb588SMatthias Schmidt     watch_login(1);
6347d8fb588SMatthias Schmidt 
6357d8fb588SMatthias Schmidt     for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
6367d8fb588SMatthias Schmidt 	if (strcmp(tty, wp->who_tty) == 0)
6377d8fb588SMatthias Schmidt 	    host = wp->who_host;
6387d8fb588SMatthias Schmidt 	wp->who_name[0] = '\0';
6397d8fb588SMatthias Schmidt     }
6407d8fb588SMatthias Schmidt     resetwatch();
6417d8fb588SMatthias Schmidt     return host;
6427d8fb588SMatthias Schmidt }
64394afa86dSJohn Marino # endif /* UTHOSTLEN */
6447d8fb588SMatthias Schmidt 
6457d8fb588SMatthias Schmidt #endif /* HAVENOUTMP */
646