AUSAM/source/S/evict.c
#
/*
* This program is used to remove ungracefully a group of persons
* from the system .
* Used by TERMBOOK . Can also be used directly .
* Syntax:
* evict ttys [ wait [ lname ] ]
*
* 'ttys' is a string of chars, 'ab...' meaning ttya,ttyb...
* 'wait' the number of seconds between warning and death.
* 'lname' is the person (or class) who has the right to remain.
*
* Modified on the 29 june 1979 to give a log of eviction
* information. Defined as EVICTMONITOR in local-system.
* Graham S.
*/
#include <param.h>
#include <proc.h>
#include <local-system>
#include <class.h>
#include <tty.h>
char partab[1];
#include <passwd.h>
#include <lnode.h>
#include <stat.h>
#include <utmp.h>
#define NVIC 70
#define NASTY -40
#define DIETIME 5
char m0[] "\nThis terminal is booked for ";
char m1[] "\nYou have minutes to log off or your account\nwill be removed from the system.\nRemain off for at least 5 minutes.\n\tBe warned.\n";
char *min &m1[12]; /* where to put number of minutes */
char m2[] "account ";
char m3[] "members of class(es) ";
char ttyn[] "tty?";
#define ttyx ttyn[3]
struct pwent pe; /* the pwent of he who may stay */
struct proc *hiproc;
int nvic; /* number of terminals evicted */
struct victim
{
int v_uid;
struct tty *v_dev;
struct lnode *v_lnp;
}
victims[NVIC]; /* one entry for every 1..nvic */
int uids[256]; /* one uid per tty char */
int class; /* set when a class eviction in progress */
int wte; /* time allowed to log off in peace */
int kmfd,utfd; /* kmem, utmp file desciptors */
int trycnt; /* A KLUDGE SO THAT EVICT DOES NOT STAY AROUND TO LONG */
#ifdef EVICTMONITOR
#include <uid.h>
extern fout; /* A buffer for writing on the monitor file */
extern long time();
int thispid;
#endif EVICTMONITOR
main(argc, argv)
int argc;
char **argv;
{
register char *s;
register int warned;
nice(NASTY);
#ifdef EVICTMONITOR
thispid = getpid();
if((fout = open(EVICTLOG,2)) == -1)
err("Can't open : %s\n",EVICTLOG);
seek(fout,0,2); /* Put it at the end of the file */
printf("%ld %d ",time(),thispid);
{
unsigned r;
printf("Uid : %d",r = REALUID());
if(argc > 1)
printf(" Ttys : %s",argv[1]);
if(argc > 2)
printf(" Wait : %s",argv[2]);
if(argc > 3)
printf(" Lname : %s",argv[3]);
printf("\n");
}
flush();
#endif EVICTMONITOR
if(argc > 4 || argc < 2)
err("Usage : evict ttys [ wait [ lname] ]\n");
if(argc == 4)
{
pe.pw_strings[LNAME] = argv[3];
if(getpwuid(&pe, 0, 0) < 0)
err("Who ?\n");
if(pe.pw_flags & CLASSACC)
class++;
}
else
{
pe.pw_flags = 0; /* just to be safe */
pe.pw_uid = 0;
}
if(argc >= 3)
wte = atoi(argv[2]);
warned = wte/60;
do
{
*--min = warned%10+'0';
warned =/ 10;
}
while(warned);
if(chdir("/dev") == -1)
err("chdir /dev failed\n");
if((kmfd = open("kmem", 0)) == -1)
err("Can't open /dev/kmem\n");
if((utfd = open("/etc/utmp", 0)) == -1)
err("Can't open /etc/utmp\n");
do
{
warned = 0;
hiproc = &proc[gprocs(proc)];
for(s = argv[1]; *s != 0; s++)
{
switch(whosat(*s))
{
case 0:
continue;
case 1: /* to be warned */
if(wte)
{
warn(*s, argc == 4 ? argv[3] : 0);
warned++;
break;
}
case -1:
zap(*s);
break;
}
}
/* The Kludge so that evict will go away */
if (trycnt++ == 3) break;
if(warned)
sleep(wte);
}
while(warned);
/*
* get the processes which did not submit to a SIGTERMINATE
*/
if(nvic)
finalzap();
else
prints(2, "No evictions performed\n");
return 0;
}
err(string)
char *string;
{
prints(2, string);
exit(1);
}
warn(c, name)
int c;
char *name;
{
register int f;
#ifdef EVICTMONITOR
seek(fout,0,2);
printf("%ld %d Warn tty%c, %s\n",time(),thispid,c,name);
flush();
#endif EVICTMONITOR
ttyx = c;
if((f = open(ttyn, 1)) >= 0)
{
if(class)
{
register int i;
prints(f, &m0);
prints(f, &m3);
for(i = 0; i < (sizeof classes/sizeof classes[0]); i++)
{
if(pe.pw_cmask[classes[i].c_word]&classes[i].c_mask)
{
prints(f, classes[i].c_name);
prints(f, " ");
}
}
}
else
{
if(name != 0)
{
prints(f, m0);
prints(f, &m2);
prints(f, name);
}
}
prints(f, &m1);
close(f);
}
}
zap(c)
int c;
{
register struct proc *p;
register struct tty *dev 0;
register struct lnode *lnp;
struct statb sb;
int ttydev;
ttyx = c;
stat(ttyn, &sb);
if((sb.i_mode&IFMT) != IFCHR)
{
prints(2, ttyn);
prints(2, ": not a character device.\n");
return;
}
for(p = proc; p < hiproc; p++)
{
if(p->p_stat && p->p_stat != SZOMB && uids[c] == p->p_uid)
{
/*
* Look for ttyp and lnode.
*/
seek(kmfd, &(p->p_ttyp->t_dev), 0);
read(kmfd, &ttydev, 2);
if(ttydev == sb.i_addr[0])
{
dev = p->p_ttyp;
lnp = p->p_lnode;
victims[nvic].v_uid = uids[c];
victims[nvic].v_dev = dev;
victims[nvic].v_lnp = lnp;
#ifdef EVICTMONITOR
seek(fout,0,2);
printf("%ld %d tty%c, Lnode : 0%o\n",
time(),thispid,c,lnp);
flush();
#endif EVICTMONITOR
nvic++;
break;
}
}
}
if(dev)
{
for(p = proc; p < hiproc; p++)
{
if(p->p_stat
&& p->p_stat != SZOMB
&& p->p_ttyp == dev
&& p->p_lnode == lnp)
{
#ifdef EVICTMONITOR
seek(fout,0,2);
printf("%ld %d SIGTERMINATE Lnode : 0%o, Pid : %d\n",
time(),thispid,lnp,p->p_pid);
flush();
#endif EVICTMONITOR
kill(p->p_pid, SIGTERMINATE);
}
}
}
else
{
prints(2, ttyx);
prints(2, ": No procs found\n");
}
}
whosat(c)
register c;
{
struct utmp utmpst;
struct pwent ze;
register int n;
n = c;
if(n >= '0' && n <= '9')
n =- '0';
else if(n >= 'a' && n <= 'z')
n =+ 10-'a';
else
n =+ 36-'A';
seek(utfd, UTMPSIZ*n, 0);
read(utfd, &utmpst, UTMPSIZ);
if(utmpst.u_ttyid == 0 || utmpst.u_u_id == 0 || pe.pw_uid == utmpst.u_u_id)
{
uids[c] = 0;
return 0;
}
if(uids[c] == utmpst.u_u_id)
{
return -1;
}
ze.pw_uid = utmpst.u_u_id;
getpwlog(&ze, 0, 0);
if(ze.pw_flags & NOEVICT)
{
uids[c] = 0;
return 0;
}
if(class)
{
register i;
for(i = 0; i < CMASKSIZE; i++)
{
if(pe.pw_cmask[i] & ze.pw_cmask[i])
{
uids[c] = 0;
return 0;
}
}
}
uids[c] = utmpst.u_u_id;
return 1;
}
finalzap()
{
register struct proc *p;
register struct victim *v;
struct pwent ze;
char names[SSIZ];
sleep(DIETIME);
hiproc = &proc[gprocs(proc)];
for(v = victims; v < victims+nvic; v++)
{
for(p = proc; p < hiproc; p++)
{
if(p->p_stat
&& p->p_stat != SZOMB
&& p->p_lnode == v->v_lnp
&& p->p_ttyp == v->v_dev)
{
#ifdef EVICTMONITOR
seek(fout,0,2);
printf("%ld %d SIGKIL Lnode : 0%o, Pid : %d\n",
time(),thispid,v->v_lnp,p->p_pid);
flush();
#endif EVICTMONITOR
kill(p->p_pid, SIGKIL);
}
}
ze.pw_uid = v->v_uid;
#ifdef EVICTMONITOR
if(getpwlog(&ze, names, sizeof names) == -1)
{
seek(fout,0,2);
printf("%ld %d GETPWLOG FAILED\n",time(),thispid);
flush();
}
#else
getpwlog(&ze, names, sizeof names);
#endif EVICTMONITOR
ze.pw_tmask = 0;
ze.pw_cmask[CMASKSIZE-1] =| 01; /* set EVICTED flag */
chmod(ze.pw_strings[DIRPATH], 0);
#ifdef EVICTMONITOR
printf("%ld %d Chmod %s\n",time(),thispid,ze.pw_strings[DIRPATH]);
seek(fout,0,2);
printf("%ld %d EVICTED Uid : %d\n",time(),thispid,ze.pw_uid);
flush();
#endif EVICTMONITOR
#ifdef EVICTMONITOR
if(updtpwent(&ze) <= 0)
{
seek(fout,0,2);
printf("%ld %d UPDTPWENT FAILED\n",time(),thispid);
}
#else
updtpwent(&ze);
#endif EVICTMONITOR
}
}