[net.sources] Rcheck - tell when users log in and out

klemets@ttds.UUCP (Anders Klemets) (05/06/85)

This program tells you when users log in or out from your machine
and from other machines connected to a local network. It can be told
to only watch for some users, ttys and hosts in any combination you
like.
The program was written on a VAX 11/750 with 4.2 BSD and will only
work on a 4.2 BSD system in its original form. If you don't have
4.2 BSD you will have to change a little in the makefile, and then
it might work. If it does it will ignore a local network, if there's any.

-------------------------(Cut here)--------------------------------------------

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
echo 'Extracting Makefile'
sed 's/^X//' > Makefile << '+ END-OF-FILE Makefile'
XFILES = rcheck.o net.o
XCFLAGS = -O -DBSD
X# If your system doesn't use 4.2BSD remove the two previous lines
X# and remove the "#" at the beginning of the following two lines.
X# FILES = rcheck.o
X# CFLAGS = -O -UBSD
X
XNAME = rcheck
XDESTDIR = /usr/local
X
Xrcheck : ${FILES} rcheck.h
X	cc ${CFLAGS} -o ${NAME} ${FILES}
X
Xrcheck.h : ${FILES}
X
Xinstall :
X	mv ${NAME} ${DESTDIR}
X	mv rcheck.1 /usr/man/manl
+ END-OF-FILE Makefile
chmod 'u=rw,g=r,o=r' 'Makefile'
echo '	-rw-r--r--  1 klemets       392 May  5 22:07 Makefile        (as sent)'
echo -n '	'
/bin/ls -l Makefile
echo 'Extracting net.c'
sed 's/^X//' > net.c << '+ END-OF-FILE net.c'
X#include "rcheck.h"
X#include "/usr/src/etc/rwhod/rwhod.h"
X/* The location of the above file may differ. */
Xint rsize = 1024 / sizeof (struct whoent);
Xstruct whod rold[MAXHOSTS], rnew[MAXHOSTS];
Xrload (mode)
X{
X    	DIR *dirp;
X    	struct direct *dp;
X	int fd, x, nr=0;
X	dirp = opendir (".");
X	while (dp = readdir (dirp)) {
X 		if (dp->d_ino == 0)
X		    continue;
X	    	if (strncmp (dp->d_name, "whod.", 5))
X		    continue;
X		if (strcmp (dp->d_name+5, hostname) == 0)
X		    continue;
X	    	fd = open (dp->d_name, 0);
X		for (x=0;  x<rsize;  ++x) {
X		    if (mode)
X		    strcpy (rnew[nr].wd_we[x].we_utmp.out_line, "\0");
X		    else strcpy (rold[nr].wd_we[x].we_utmp.out_line, "\0");
X		}
X		if (mode)
X		    read (fd, &rnew[nr], sizeof (struct whod));
X		else read (fd, &rold[nr], sizeof (struct whod));
X		close (fd);
X		++nr;
X	}
X	closedir (dirp);
X}
X
Xrscan ()
X{
X	int x, u;
X	for (x=0; x<MAXHOSTS; ++x)
X		for (u = 0; strlen (rold[x].wd_we[u].we_utmp.out_line) && 
X			u < rsize;  ++u)
X			if (find (&rold[x].wd_we[u].we_utmp, &rnew[x]))
X	printout(rold[x].wd_we[u].we_utmp.out_name, rold[x].wd_we[u].we_utmp.out_line,
X	rold[x].wd_hostname, "\0", 0);
X	for (x=0; x <MAXHOSTS; ++x)
X		for (u = 0; strlen (rnew[x].wd_we[u].we_utmp.out_line) &&
X			u < rsize;  ++u)
X			if (find (&rnew[x].wd_we[u].we_utmp, &rold[x]))
X	printout(rnew[x].wd_we[u].we_utmp.out_name, rnew[x].wd_we[u].we_utmp.out_line,
X	rnew[x].wd_hostname, "\0", 1);
X	for (x=0;  x<MAXHOSTS;  ++x)
X	    for (u = 0;  u < rsize;  ++u) {
X		strcpy (rold[x].wd_we[u].we_utmp.out_name, 
X			rnew[x].wd_we[u].we_utmp.out_name);
X		strcpy (rold[x].wd_we[u].we_utmp.out_line, 
X			rnew[x].wd_we[u].we_utmp.out_line);
X	    }
X}
Xfind (a, b)
Xstruct outmp *a;
Xstruct whod *b;
X{
X	int x;
X	char cname[NAMELEN+1];
X	strncpy (cname, a->out_name, NAMELEN);
X	cname[NAMELEN] = '\0';
X	for (x = 0; x < rsize; ++x)
X		if (strcmp(a->out_line, b->wd_we[x].we_utmp.out_line) == 0
X		&& strncmp(cname, b->wd_we[x].we_utmp.out_name, NAMELEN)==0)
X			return (0);
X	return (1);
X}
+ END-OF-FILE net.c
chmod 'u=rw,g=r,o=r' 'net.c'
echo '	-rw-r--r--  1 klemets      1979 May  5 22:15 net.c        (as sent)'
echo -n '	'
/bin/ls -l net.c
echo 'Extracting rcheck.1'
sed 's/^X//' > rcheck.1 << '+ END-OF-FILE rcheck.1'
X.TH RCHECK 1 "18 Mars 1985"
X.UC 4
X.SH NAME
Xrcheck \- check for users logging in and out from systems on the local network
X.SH SYNOPSIS
X.B rcheck
X[
X.B username ...
X] [
X.B \-t tty ...
X] [
X.B \-h host ...
X]
X.SH DESCRIPTION
X.I Rcheck
Xruns in the background and checks for
Xusers logging in and out from machines
Xconnected to the local network.
XEvery time
X.I rcheck
Xfinds out that somebody has logged in
Xor out, it will print a message on the
Xterminal screen,
Xtelling the time,
Xthe users login-name,
Xthe host he is on,
Xthe affected tty,
Xand the real name of the user, if it is
Xpossible to find it in the local machines
X/etc/passwd -file.
X.PP
XIt can be very annoying receiving messages
Xall the time on the terminal screen, specially
Xwhen editing files... But if you specify one or
Xmore
X.B usernames
Xon the command line,
X.I rcheck
Xwill only tell you when the specified users log
Xin and out.
X.br
XThe other flags works in a similar way.
XThe
X.B \-t
Xflag takes arguments of tty-names and then it
Xwill only tell you when any of the specified
Xttys is affected.
XThe
X.B \-h
Xflag accepts arguments which are names of remote
Xhosts connected to a local network. As with the
Xprevious flags,
X.I rcheck
Xwill only print messages concearning the specified
Xhosts.
X.PP
X.I Rcheck
Xscans the local machine with an
X30 second intervall, and the
Xremote hosts every
X60 seconds.
X.I Rcheck
Xterminates it self when the calling process is
Xterminated.
X.SH FILES
X.ta 1i
X/etc/utmp
X.br
X/usr/spool/rwho/whod.*
X.br
X/etc/passwd
X.SH "SEE ALSO"
Xsysline(1)
X.SH AUTHOR
XAnders Klemets
X (klemets@ttds.UUCP)
X.SH BUGS
XIf there are two different users with the same
X.B username
Xon the hosts in the local network, and one of
Xthem has an account on the local machine,
X.I rcheck
Xwill tell you the name of this user even when
Xthe other user logs in on "his" machine.
XThis, however, is not specially common.
X
+ END-OF-FILE rcheck.1
chmod 'u=rw,g=r,o=r' 'rcheck.1'
echo '	-rw-r--r--  1 klemets      1851 May  5 18:17 rcheck.1        (as sent)'
echo -n '	'
/bin/ls -l rcheck.1
echo 'Extracting rcheck.c'
sed 's/^X//' > rcheck.c << '+ END-OF-FILE rcheck.c'
X/*
X * CHECK for users logging in or out on the local and Remote machines.
X * Idea stolen from jr by bs
X * Idea stolen from bs by klemets@ttds.UUCP
X * It should be started with "rcheck &".
X * The program is written for 4.2 BSD UNIX. If you don't use 4.2 BSD
X * you must change a little in the makefile and then it will work,
X * I hope... (It will then ignore the local network.)
X */
X
X#include "rcheck.h"
Xint users, fid;
Xstruct utmp old[MAXUSERS], new[MAXUSERS];
X
Xmain(argc, argv)
Xchar *argv[];
X{
X	int x, h=0, p=0, m=0, t=0;
X	for (x=1; x<argc; ++x)
X		if (strcmp ("-h", argv[x]) == 0)
X			m = 1;
X		else if (strcmp ("-t", argv[x]) == 0)
X			m = 2;
X		else {
X			if (m == 0) {
X				if (p == MAXUSERS) {
X					fprintf (stderr, "Too many users specified.\n");
X					exit (1);
X				}
X				strcpy (allperson[p++], argv[x]);
X			}
X			else if (m == 1) {
X				if (h == MAXHOSTS) {
X					fprintf (stderr, "Too many hosts specified.\n");
X					exit (1);
X				}
X				strcpy (allhost[h++], argv[x]);
X			}
X			else {
X				if (t == MAXUSERS) {
X					fprintf (stderr, "Too many ttys specified.\n");
X					exit (1);
X				}
X				strcpy (alltty[t++], argv[x]);
X			}
X	}
X#ifdef BSD
X	chdir ("/usr/spool/rwho");
X#endif BSD
X	gethostname (hostname, sizeof hostname);
X	if ((fid = open("/etc/utmp", 0)) == NULL) {
X		fprintf (stderr, "Can't open /etc/utmp\n");
X		exit (-1);
X	}
X	load(old);
X#ifdef BSD
X	rload (0);/* rold */
X#endif BSD
X	while (getppid() > 1) {
X	    sleep(30);
X	    load(new);
X	    localscan ();
X	    sleep (30);
X	    load (new);
X	    localscan ();
X#ifdef BSD
X	    rload (1);
X	    rscan ();
X#endif BSD
X	}
X}
X
Xlocalscan ()
X{
X	    for (users--; users>=0; users--)
X		if (strcmp(old[users].ut_name,new[users].ut_name))
X		    if (new[users].ut_name[0]=='\0') {
X			printout (old[users].ut_name, old[users].ut_line, hostname, old[users].ut_host, 0);
X			old[users].ut_name[0]='\0';
X		    }
X		    else {
X			printout (new[users].ut_name, new[users].ut_line, hostname, new[users].ut_host, 1);
X			strcpy(old[users].ut_name,new[users].ut_name);
X			strcpy (old[users].ut_line, new[users].ut_line);
X			strcpy (old[users].ut_host, new[users].ut_host);
X		    }
X}
Xprintout (name, tty, host, remote, mode)
Xchar *name, *tty, *host, *remote;
X{
X	char *givename(), rtime[10], cname[NAMELEN+1];
X	long time (), tim;
X	int x=0;
X	strncpy (cname, name, NAMELEN);
X	cname[NAMELEN] = '\0';
X	if (strlen (allperson[0])) {
X		while (x < MAXUSERS)
X			if (strncmp (allperson[x], cname, NAMELEN) == 0)
X				break;
X			else ++x;
X		if (x == MAXUSERS)
X			return (0);
X	}
X	x = 0;
X	if (strlen (allhost[0])) {
X		while (x < MAXHOSTS)
X			if (strcmp (allhost[x], host) == 0)
X				break;
X			else ++x;
X		if (x == MAXHOSTS)
X			return (0);
X	}
X	x = 0;
X	if (strlen (alltty[0])) {
X		while (x < MAXUSERS)
X			if (strcmp (alltty[x], tty) == 0)
X				break;
X			else ++x;
X		if (x == MAXUSERS)
X			return (0);
X	}
X	tim = time (0);
X	strncpy (rtime, ctime (&tim)+11, 5);
X	rtime[5] = '\0';
X	printf ("\r\n*** %s %s@%s%s logged %s %s%s%s ***\7\r\n", rtime, cname,
X		host, givename (cname), (mode) ? "in on" : "out from", tty,
X		(strlen (remote)) ? " via " : "\0", (strlen (remote)) ? remote : "\0");
X	return (1);
X}
X	    
Xchar *givename (s)
Xchar *s;
X{
X	struct passwd *getpwname (), *psw;
X	char *namefix (), *r;
X	static char str[100];
X	if (psw = getpwnam (s))
X		if (strlen (r = namefix (psw->pw_gecos, s))) {
X			strcpy (str, " (");
X			strcat (str, r);
X			strcat (str, ")");
X			return (str);
X		}
X	return ("");
X}
Xload(f)
Xstruct utmp f[MAXUSERS];
X{
X	int i;
X	users = 0;
X	lseek (fid, 0, 0);
X	while (read (fid, (char *) &f[users], sizeof (struct utmp)) > 0)
X	    ++users;
X}
Xchar *namefix (s, name)
Xchar s[], name[];
X{   
X    int x, i;
X    char tmp[200];
X    for (x=i=0; x<strlen (s); ++x, ++i) {
X	if (s[x] == ',') {
X	    tmp[i] = '\0';
X	    return (tmp);
X	}
X	if (s[x] == '&') {
X	    strcpy (&tmp[i], name);
X	    if (tmp[i] < 'A' || tmp[i] > 'Z')
X		tmp[i] -= ' ';
X	    i += strlen (name)-1;
X	}
X	else tmp[i] = s[x];
X    }
X    tmp[i] = '\0';
X    return (tmp);
X}
+ END-OF-FILE rcheck.c
chmod 'u=rw,g=r,o=r' 'rcheck.c'
echo '	-rw-r--r--  1 klemets      3937 May  5 22:12 rcheck.c        (as sent)'
echo -n '	'
/bin/ls -l rcheck.c
echo 'Extracting rcheck.h'
sed 's/^X//' > rcheck.h << '+ END-OF-FILE rcheck.h'
X#include <stdio.h>
X#include <pwd.h>
X#include <utmp.h>
X#include <sys/types.h>
X#include <sys/dir.h>
X#define MAXUSERS 64
X#define MAXHOSTS 20
X#define NAMELEN 8
Xchar hostname [32], allperson[MAXUSERS][10], allhost[MAXHOSTS][32],
X	alltty[MAXUSERS][10];
+ END-OF-FILE rcheck.h
chmod 'u=rw,g=r,o=r' 'rcheck.h'
echo '	-rw-r--r--  1 klemets       247 May  5 20:15 rcheck.h        (as sent)'
echo -n '	'
/bin/ls -l rcheck.h
exit 0