summaryrefslogtreecommitdiffstats
path: root/contrib/tcsh/tc.who.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2000-04-15 04:41:27 +0000
committerobrien <obrien@FreeBSD.org>2000-04-15 04:41:27 +0000
commit4ad28cefef28ce6bdb44a0532cfe20a2076bc694 (patch)
tree7679c440a91912ee9586cee3ebab24596c0fe1c4 /contrib/tcsh/tc.who.c
downloadFreeBSD-src-4ad28cefef28ce6bdb44a0532cfe20a2076bc694.zip
FreeBSD-src-4ad28cefef28ce6bdb44a0532cfe20a2076bc694.tar.gz
Import the latest version of the 44BSD C-shell -- tcsh-6.09.
Diffstat (limited to 'contrib/tcsh/tc.who.c')
-rw-r--r--contrib/tcsh/tc.who.c679
1 files changed, 679 insertions, 0 deletions
diff --git a/contrib/tcsh/tc.who.c b/contrib/tcsh/tc.who.c
new file mode 100644
index 0000000..fe80702
--- /dev/null
+++ b/contrib/tcsh/tc.who.c
@@ -0,0 +1,679 @@
+/* $Header: /src/pub/tcsh/tc.who.c,v 3.28 1998/04/08 13:59:13 christos Exp $ */
+/*
+ * tc.who.c: Watch logins and logouts...
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.who.c,v 3.28 1998/04/08 13:59:13 christos Exp $")
+
+#include "tc.h"
+
+#ifndef HAVENOUTMP
+/*
+ * kfk 26 Jan 1984 - for login watch functions.
+ */
+#include <ctype.h>
+
+#ifdef HAVEUTMPX
+# include <utmpx.h>
+/* I just redefine a few words here. Changing every occurrence below
+ * seems like too much of work. All UTMP functions have equivalent
+ * UTMPX counterparts, so they can be added all here when needed.
+ * Kimmo Suominen, Oct 14 1991
+ */
+# ifndef _PATH_UTMP
+# define _PATH_UTMP UTMPX_FILE
+# endif /* _PATH_UTMP */
+# define utmp utmpx
+# define ut_time ut_xtime
+#else /* !HAVEUTMPX */
+# ifndef WINNT
+# include <utmp.h>
+# endif /* WINNT */
+#endif /* HAVEUTMPX */
+
+#ifndef BROKEN_CC
+# define UTNAMLEN sizeof(((struct utmp *) 0)->ut_name)
+# define UTLINLEN sizeof(((struct utmp *) 0)->ut_line)
+# ifdef UTHOST
+# ifdef _SEQUENT_
+# define UTHOSTLEN 100
+# else
+# define UTHOSTLEN sizeof(((struct utmp *) 0)->ut_host)
+# endif
+# endif /* UTHOST */
+#else
+/* give poor cc a little help if it needs it */
+struct utmp __ut;
+
+# define UTNAMLEN sizeof(__ut.ut_name)
+# define UTLINLEN sizeof(__ut.ut_line)
+# ifdef UTHOST
+# ifdef _SEQUENT_
+# define UTHOSTLEN 100
+# else
+# define UTHOSTLEN sizeof(__ut.ut_host)
+# endif
+# endif /* UTHOST */
+#endif /* BROKEN_CC */
+
+#ifndef _PATH_UTMP
+# ifdef UTMP_FILE
+# define _PATH_UTMP UTMP_FILE
+# else
+# define _PATH_UTMP "/etc/utmp"
+# endif /* UTMP_FILE */
+#endif /* _PATH_UTMP */
+
+
+struct who {
+ struct who *who_next;
+ struct who *who_prev;
+ char who_name[UTNAMLEN + 1];
+ char who_new[UTNAMLEN + 1];
+ char who_tty[UTLINLEN + 1];
+#ifdef UTHOST
+ char who_host[UTHOSTLEN + 1];
+#endif /* UTHOST */
+ time_t who_time;
+ int who_status;
+};
+
+static struct who whohead, whotail;
+static time_t watch_period = 0;
+static time_t stlast = 0;
+#ifdef WHODEBUG
+static void debugwholist __P((struct who *, struct who *));
+#endif
+static void print_who __P((struct who *));
+
+
+#define ONLINE 01
+#define OFFLINE 02
+#define CHANGED 04
+#define STMASK 07
+#define ANNOUNCE 010
+
+/*
+ * Karl Kleinpaste, 26 Jan 1984.
+ * Initialize the dummy tty list for login watch.
+ * This dummy list eliminates boundary conditions
+ * when doing pointer-chase searches.
+ */
+void
+initwatch()
+{
+ whohead.who_next = &whotail;
+ whotail.who_prev = &whohead;
+ stlast = 1;
+#ifdef WHODEBUG
+ debugwholist(NULL, NULL);
+#endif /* WHODEBUG */
+}
+
+void
+resetwatch()
+{
+ watch_period = 0;
+ stlast = 0;
+}
+
+/*
+ * Karl Kleinpaste, 26 Jan 1984.
+ * Watch /etc/utmp for login/logout changes.
+ */
+void
+watch_login(force)
+ int force;
+{
+ int utmpfd, comp = -1, alldone;
+ int firsttime = stlast == 1;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+ struct utmp utmp;
+ struct who *wp, *wpnew;
+ struct varent *v;
+ Char **vp = NULL;
+ time_t t, interval = MAILINTVL;
+ struct stat sta;
+#if defined(UTHOST) && defined(_SEQUENT_)
+ char *host, *ut_find_host();
+#endif
+#ifdef WINNT
+ static int ncbs_posted = 0;
+ USE(utmp);
+ USE(utmpfd);
+ USE(sta);
+ USE(wpnew);
+#endif /* WINNT */
+
+ /* stop SIGINT, lest our login list get trashed. */
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGINT));
+#else
+ (void) sighold(SIGINT);
+#endif
+
+ v = adrof(STRwatch);
+ if (v == NULL && !force) {
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ return; /* no names to watch */
+ }
+ if (!force) {
+ trim(vp = v->vec);
+ if (blklen(vp) % 2) /* odd # args: 1st == # minutes. */
+ interval = (number(*vp)) ? (getn(*vp++) * 60) : MAILINTVL;
+ }
+ else
+ interval = 0;
+
+ (void) time(&t);
+#ifdef WINNT
+ /*
+ * Since NCB_ASTATs take time, start em async at least 90 secs
+ * before we are due -amol 6/5/97
+ */
+ if (!ncbs_posted) {
+ unsigned long tdiff = t - watch_period;
+ if (!watch_period || ((tdiff > 0) && (tdiff > (interval - 90)))) {
+ start_ncbs(vp);
+ ncbs_posted = 1;
+ }
+ }
+#endif /* WINNT */
+ if (t - watch_period < interval) {
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ return; /* not long enough yet... */
+ }
+ watch_period = t;
+#ifdef WINNT
+ ncbs_posted = 0;
+#else /* !WINNT */
+
+ /*
+ * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
+ * Don't open utmp all the time, stat it first...
+ */
+ if (stat(_PATH_UTMP, &sta)) {
+ xprintf(CGETS(26, 1, "cannot stat %s. Please \"unset watch\".\n"),
+ _PATH_UTMP);
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif
+ return;
+ }
+ if (stlast == sta.st_mtime) {
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif
+ return;
+ }
+ stlast = sta.st_mtime;
+ if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) {
+ xprintf(CGETS(26, 2, "%s cannot be opened. Please \"unset watch\".\n"),
+ _PATH_UTMP);
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif
+ return;
+ }
+
+ /*
+ * xterm clears the entire utmp entry - mark everyone on the status list
+ * OFFLINE or we won't notice X "logouts"
+ */
+ for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
+ wp->who_status = OFFLINE;
+ wp->who_time = 0;
+ }
+
+ /*
+ * Read in the utmp file, sort the entries, and update existing entries or
+ * add new entries to the status list.
+ */
+ while (read(utmpfd, (char *) &utmp, sizeof utmp) == sizeof utmp) {
+
+# ifdef DEAD_PROCESS
+# ifndef IRIS4D
+ if (utmp.ut_type != USER_PROCESS)
+ continue;
+# else
+ /* Why is that? Cause the utmp file is always corrupted??? */
+ if (utmp.ut_type != USER_PROCESS && utmp.ut_type != DEAD_PROCESS)
+ continue;
+# endif /* IRIS4D */
+# endif /* DEAD_PROCESS */
+
+ if (utmp.ut_name[0] == '\0' && utmp.ut_line[0] == '\0')
+ continue; /* completely void entry */
+# ifdef DEAD_PROCESS
+ if (utmp.ut_type == DEAD_PROCESS && utmp.ut_line[0] == '\0')
+ continue;
+# endif /* DEAD_PROCESS */
+ wp = whohead.who_next;
+ while (wp->who_next && (comp = strncmp(wp->who_tty, utmp.ut_line, UTLINLEN)) < 0)
+ wp = wp->who_next;/* find that tty! */
+
+ if (wp->who_next && comp == 0) { /* found the tty... */
+# ifdef DEAD_PROCESS
+ if (utmp.ut_type == DEAD_PROCESS) {
+ wp->who_time = utmp.ut_time;
+ wp->who_status = OFFLINE;
+ }
+ else
+# endif /* DEAD_PROCESS */
+ if (utmp.ut_name[0] == '\0') {
+ wp->who_time = utmp.ut_time;
+ wp->who_status = OFFLINE;
+ }
+ else if (strncmp(utmp.ut_name, wp->who_name, UTNAMLEN) == 0) {
+ /* someone is logged in */
+ wp->who_time = utmp.ut_time;
+ wp->who_status = 0; /* same guy */
+ }
+ else {
+ (void) strncpy(wp->who_new, utmp.ut_name, UTNAMLEN);
+# ifdef UTHOST
+# ifdef _SEQUENT_
+ host = ut_find_host(wp->who_tty);
+ if (host)
+ (void) strncpy(wp->who_host, host, UTHOSTLEN);
+ else
+ wp->who_host[0] = 0;
+# else
+ (void) strncpy(wp->who_host, utmp.ut_host, UTHOSTLEN);
+# endif
+# endif /* UTHOST */
+ wp->who_time = utmp.ut_time;
+ if (wp->who_name[0] == '\0')
+ wp->who_status = ONLINE;
+ else
+ wp->who_status = CHANGED;
+ }
+ }
+ else { /* new tty in utmp */
+ wpnew = (struct who *) xcalloc(1, sizeof *wpnew);
+ (void) strncpy(wpnew->who_tty, utmp.ut_line, UTLINLEN);
+# ifdef UTHOST
+# ifdef _SEQUENT_
+ host = ut_find_host(wpnew->who_tty);
+ if (host)
+ (void) strncpy(wpnew->who_host, host, UTHOSTLEN);
+ else
+ wpnew->who_host[0] = 0;
+# else
+ (void) strncpy(wpnew->who_host, utmp.ut_host, UTHOSTLEN);
+# endif
+# endif /* UTHOST */
+ wpnew->who_time = utmp.ut_time;
+# ifdef DEAD_PROCESS
+ if (utmp.ut_type == DEAD_PROCESS)
+ wpnew->who_status = OFFLINE;
+ else
+# endif /* DEAD_PROCESS */
+ if (utmp.ut_name[0] == '\0')
+ wpnew->who_status = OFFLINE;
+ else {
+ (void) strncpy(wpnew->who_new, utmp.ut_name, UTNAMLEN);
+ wpnew->who_status = ONLINE;
+ }
+# ifdef WHODEBUG
+ debugwholist(wpnew, wp);
+# endif /* WHODEBUG */
+
+ wpnew->who_next = wp; /* link in a new 'who' */
+ wpnew->who_prev = wp->who_prev;
+ wpnew->who_prev->who_next = wpnew;
+ wp->who_prev = wpnew; /* linked in now */
+ }
+ }
+ (void) close(utmpfd);
+# if defined(UTHOST) && defined(_SEQUENT_)
+ endutent();
+# endif
+#endif /* !WINNT */
+
+ if (force || vp == NULL)
+ return;
+
+ /*
+ * The state of all logins is now known, so we can search the user's list
+ * of watchables to print the interesting ones.
+ */
+ for (alldone = 0; !alldone && *vp != NULL && **vp != '\0' &&
+ *(vp + 1) != NULL && **(vp + 1) != '\0';
+ vp += 2) { /* args used in pairs... */
+
+ if (eq(*vp, STRany) && eq(*(vp + 1), STRany))
+ alldone = 1;
+
+ for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
+ if (wp->who_status & ANNOUNCE ||
+ (!eq(STRany, vp[0]) &&
+ !Gmatch(str2short(wp->who_name), vp[0]) &&
+ !Gmatch(str2short(wp->who_new), vp[0])) ||
+ (!Gmatch(str2short(wp->who_tty), vp[1]) &&
+ !eq(STRany, vp[1])))
+ continue; /* entry doesn't qualify */
+ /* already printed or not right one to print */
+
+
+ if (wp->who_time == 0)/* utmp entry was cleared */
+ wp->who_time = watch_period;
+
+ if ((wp->who_status & OFFLINE) &&
+ (wp->who_name[0] != '\0')) {
+ if (!firsttime)
+ print_who(wp);
+ wp->who_name[0] = '\0';
+ wp->who_status |= ANNOUNCE;
+ continue;
+ }
+ if (wp->who_status & ONLINE) {
+ if (!firsttime)
+ print_who(wp);
+ (void) strcpy(wp->who_name, wp->who_new);
+ wp->who_status |= ANNOUNCE;
+ continue;
+ }
+ if (wp->who_status & CHANGED) {
+ if (!firsttime)
+ print_who(wp);
+ (void) strcpy(wp->who_name, wp->who_new);
+ wp->who_status |= ANNOUNCE;
+ continue;
+ }
+ }
+ }
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+}
+
+#ifdef WHODEBUG
+static void
+debugwholist(new, wp)
+ register struct who *new, *wp;
+{
+ register struct who *a;
+
+ a = whohead.who_next;
+ while (a->who_next != NULL) {
+ xprintf("%s/%s -> ", a->who_name, a->who_tty);
+ a = a->who_next;
+ }
+ xprintf("TAIL\n");
+ if (a != &whotail) {
+ xprintf(CGETS(26, 3, "BUG! last element is not whotail!\n"));
+ abort();
+ }
+ a = whotail.who_prev;
+ xprintf(CGETS(26, 4, "backward: "));
+ while (a->who_prev != NULL) {
+ xprintf("%s/%s -> ", a->who_name, a->who_tty);
+ a = a->who_prev;
+ }
+ xprintf("HEAD\n");
+ if (a != &whohead) {
+ xprintf(CGETS(26, 5, "BUG! first element is not whohead!\n"));
+ abort();
+ }
+ if (new)
+ xprintf(CGETS(26, 6, "new: %s/%s\n"), new->who_name, new->who_tty);
+ if (wp)
+ xprintf("wp: %s/%s\n", wp->who_name, wp->who_tty);
+}
+#endif /* WHODEBUG */
+
+
+static void
+print_who(wp)
+ struct who *wp;
+{
+#ifdef UTHOST
+ Char *cp = str2short(CGETS(26, 7, "%n has %a %l from %m."));
+#else
+ Char *cp = str2short(CGETS(26, 8, "%n has %a %l."));
+#endif /* UTHOST */
+ struct varent *vp = adrof(STRwho);
+ Char buf[BUFSIZE];
+
+ if (vp && vp->vec[0])
+ cp = vp->vec[0];
+
+ tprintf(FMT_WHO, buf, cp, BUFSIZE, NULL, wp->who_time, (ptr_t) wp);
+ for (cp = buf; *cp;)
+ xputchar(*cp++);
+ xputchar('\n');
+} /* end print_who */
+
+
+const char *
+who_info(ptr, c, wbuf, wbufsiz)
+ ptr_t ptr;
+ int c;
+ char *wbuf;
+ size_t wbufsiz;
+{
+ struct who *wp = (struct who *) ptr;
+#ifdef UTHOST
+ char *wb = wbuf;
+ int flg;
+ char *pb;
+#endif /* UTHOST */
+
+ switch (c) {
+ case 'n': /* user name */
+ switch (wp->who_status & STMASK) {
+ case ONLINE:
+ case CHANGED:
+ return wp->who_new;
+ case OFFLINE:
+ return wp->who_name;
+ default:
+ break;
+ }
+ break;
+
+ case 'a':
+ switch (wp->who_status & STMASK) {
+ case ONLINE:
+ return CGETS(26, 9, "logged on");
+ case OFFLINE:
+ return CGETS(26, 10, "logged off");
+ case CHANGED:
+ xsnprintf(wbuf, wbufsiz, CGETS(26, 11, "replaced %s on"),
+ wp->who_name);
+ return wbuf;
+ default:
+ break;
+ }
+ break;
+
+#ifdef UTHOST
+ case 'm':
+ if (wp->who_host[0] == '\0')
+ return CGETS(26, 12, "local");
+ else {
+ /* the ':' stuff is for <host>:<display>.<screen> */
+ for (pb = wp->who_host, flg = Isdigit(*pb) ? '\0' : '.';
+ *pb != '\0' &&
+ (*pb != flg || ((pb = strchr(pb, ':')) != 0));
+ pb++) {
+ if (*pb == ':')
+ flg = '\0';
+ *wb++ = Isupper(*pb) ? Tolower(*pb) : *pb;
+ }
+ *wb = '\0';
+ return wbuf;
+ }
+
+ case 'M':
+ if (wp->who_host[0] == '\0')
+ return CGETS(26, 12, "local");
+ else {
+ for (pb = wp->who_host; *pb != '\0'; pb++)
+ *wb++ = Isupper(*pb) ? Tolower(*pb) : *pb;
+ *wb = '\0';
+ return wbuf;
+ }
+#endif /* UTHOST */
+
+ case 'l':
+ return wp->who_tty;
+
+ default:
+ wbuf[0] = '%';
+ wbuf[1] = (char) c;
+ wbuf[2] = '\0';
+ return wbuf;
+ }
+ return NULL;
+}
+
+void
+/*ARGSUSED*/
+dolog(v, c)
+Char **v;
+struct command *c;
+{
+ struct who *wp;
+ struct varent *vp;
+
+ USE(v);
+ USE(c);
+ vp = adrof(STRwatch); /* lint insists vp isn't used unless we */
+ if (vp == NULL) /* unless we assign it outside the if */
+ stderror(ERR_NOWATCH);
+ resetwatch();
+ wp = whohead.who_next;
+ while (wp->who_next != NULL) {
+ wp->who_name[0] = '\0';
+ wp = wp->who_next;
+ }
+}
+
+# ifdef UTHOST
+char *
+utmphost()
+{
+ char *tty = short2str(varval(STRtty));
+ struct who *wp;
+ char *host = NULL;
+
+ watch_login(1);
+
+ for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
+ if (strcmp(tty, wp->who_tty) == 0)
+ host = wp->who_host;
+ wp->who_name[0] = '\0';
+ }
+ resetwatch();
+ return host;
+}
+# endif /* UTHOST */
+
+#ifdef WINNT
+void add_to_who_list(name, mach_nm)
+ char *name;
+ char *mach_nm;
+{
+
+ struct who *wp, *wpnew;
+ int comp = -1;
+
+ wp = whohead.who_next;
+ while (wp->who_next && (comp = strncmp(wp->who_tty,mach_nm,UTLINLEN)) < 0)
+ wp = wp->who_next;/* find that tty! */
+
+ if (wp->who_next && comp == 0) { /* found the tty... */
+
+ if (*name == '\0') {
+ wp->who_time = 0;
+ wp->who_status = OFFLINE;
+ }
+ else if (strncmp(name, wp->who_name, UTNAMLEN) == 0) {
+ /* someone is logged in */
+ wp->who_time = 0;
+ wp->who_status = 0; /* same guy */
+ }
+ else {
+ (void) strncpy(wp->who_new, name, UTNAMLEN);
+ wp->who_time = 0;
+ if (wp->who_name[0] == '\0')
+ wp->who_status = ONLINE;
+ else
+ wp->who_status = CHANGED;
+ }
+ }
+ else {
+ wpnew = (struct who *) xcalloc(1, sizeof *wpnew);
+ (void) strncpy(wpnew->who_tty, mach_nm, UTLINLEN);
+ wpnew->who_time = 0;
+ if (*name == '\0')
+ wpnew->who_status = OFFLINE;
+ else {
+ (void) strncpy(wpnew->who_new, name, UTNAMLEN);
+ wpnew->who_status = ONLINE;
+ }
+#ifdef WHODEBUG
+ debugwholist(wpnew, wp);
+#endif /* WHODEBUG */
+
+ wpnew->who_next = wp; /* link in a new 'who' */
+ wpnew->who_prev = wp->who_prev;
+ wpnew->who_prev->who_next = wpnew;
+ wp->who_prev = wpnew; /* linked in now */
+ }
+}
+#endif /* WINNT */
+#endif /* HAVENOUTMP */
OpenPOWER on IntegriCloud