1BSD/s6/watch.c

Compare this file to the similar file:
Show the results in this format:

#
/*
 * watch - watch for logins/logouts of specified users
 *
 * Author: Howard Katseff UCB July, 1977
 *
 * Watch watches the specified users and reports their logins
 * and logouts.  If no people are specified, watch execl's its
 * companion routine, syswatch, which watches over the whole system.
 */

#define NUSERS 20
#define LATENCY 15
#define ROOTSYS ((5<<8) | 8)
#define NULLDEV ((8<<8) | 2)

int lastuser,valid;
char *who_file "/etc/utmp";
char *syswatch "/usr/pascal/syswatch";
char *nil 0177777;

struct {
	char name[10];
	struct t_entry *tlink;
} users[NUSERS];

struct	t_entry	*checkout(), *talloc();
struct t_entry {
	char tty;
	int time[2];
	struct t_entry *flink;
	struct t_entry *blink;
	int valid;
};

struct	utmp {
	char	Xname[10];
	char	Xtty;
	char	pad1;
	int	ltime[2];
	int	pad2;
};

main(ct,av)
	char **av;
{
	register i;
	register char *cp,*cp2;
	int *p,pid,count;
	signal(2,1);
	signal(3,1);
	if (ct < 2)
	{
		execl(syswatch, "- ", 0);
		perror(syswatch);
		exit(1);
	}
	p = -2;
	if (pid=fork())
	{
		printf("%d\n",pid);
		exit(0);
	}
	i = 0;
	while (--ct)
	{
		cp = users[i].name;
		cp2 = *++av;
		copy(cp2,cp);
		users[i++].tlink = nil;
	}
	lastuser = --i;
	*p = -1;
	for (;;)
	{
		++count;
		count =& 037;
		if (!count) if (fork()) exit(0);
		execute();
		sleep(LATENCY);
	}
}

execute()
{
	struct utmp line;
	struct t_entry *t;
	register fd,i;
	int buf[18];
	if (fstat(1,buf)) exit(0);
	if (buf[0] == ROOTSYS && buf[6] == NULLDEV) exit(0);
	if (*buf == ctoi(2,8)) exit(0);
	fd = open(who_file,0);
	if (fd < 0)
	{
		perror(who_file);
		sleep(90);
		return;
	}
	++valid;
	while (getuser(fd,&line))
	{
		i = 0;
		while (i <= lastuser)
		{
			if (equal(line.Xname, users[i].name))
			{
				if (t=cdrondown(users[i].tlink,&line))
					users[i].tlink = t;
				break;
			}
			++i;
		}
	}
	for (i=0;i<=lastuser;++i)
		if (t=checkout(users[i].name,users[i].tlink)) users[i].tlink=t;
	close(fd);
}

cdrondown(tlist,wholine)
	struct t_entry *tlist;
	struct utmp *wholine;
{
	struct t_entry *t,*save;
	save = tlist;
	while (tlist != nil)
	{
		if (dcmp(tlist->time,wholine->ltime))
		{
			tlist->valid = valid;
			return(0);
		}
		tlist = tlist->flink;
	}
/* this tty not on the user's tty list, so it's a new entry */
	t = talloc();
	t->time[0] = wholine->ltime[0];
	t->time[1] = wholine->ltime[1];
	t->tty = wholine->Xtty;
	t->valid = valid;
	t->flink = save;
	if (save != nil) save->blink = t;
	t->blink = nil;
	message(wholine->Xname,t->tty,t->time);
	return(t);
}

struct t_entry *checkout(user,tlist)
	struct t_entry *tlist;
	char *user;
{
	struct t_entry *t,*rvalue;
	rvalue = 0;
	while (tlist != nil)
	{
		if (tlist->valid != valid)
		{
			t = tlist;
			printf("%s on tty%c logged out.\n",user,t->tty);
			if (t->blink == nil) rvalue = t->flink;
			else (t->blink)->flink = t->flink;
			if (t->flink != nil) (t->flink)->blink = t->blink;
			tlist = t->flink;
			free(t);
		} else tlist=tlist->flink;
	}
	return(rvalue);
}

struct t_entry *talloc()
{
	struct t_entry sam;
	return(alloc(sizeof sam));
}

getuser(f,w)
	struct utmp *w;
{
	register c;
	char buf[16];
	c = read(f,buf,16);
	if (c != 16) return(0);
	for (c=0;c<8;++c) w->Xname[c] = (buf[c] == 040 ? 0 : buf[c]);
	w->Xname[8] = 0;
	w->Xtty = buf[8];
	w->ltime[0] = ctoi(buf[11],buf[10]);
	w->ltime[1] = ctoi(buf[13],buf[12]);
	return(16);
}

dcmp(a,b)
	int a[],b[];
{
	return(a[0]==b[0] && a[1]==b[1]);
}

message(nm,tty,tim)
	char *nm,tty;
	int tim[];
{
	char *cvtime;
	cvtime = ctime(tim);
	cvtime[16]=0;
	cvtime =+ 4;
	printf("%s tty%c %s\n",nm,tty,cvtime);
}

copy(c1,c2)
	char *c1,*c2;
{
	while (*c2++ = *c1++);
}

equal(left,right)
	char *left,*right;
{
	while (*left && *right)
	{
		if (*left != *right) return(0);
		++left;
		++right;
	}
	return(*left == *right);
}

ctoi(a,b)
	char a,b;
{
	return(((a & 0377) << 8) | (b & 0377));
}