1BSD/s6/watch.c
#
/*
* 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));
}