AUSAM/source/S/evict.c

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

#
/*
 *	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
	}
}