AUSAM/sys106/ken/sys4.c

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

#
/*
 */

/*
 * Everything in this file is a routine implementing a system call.
 */

#include "../defines.h"
#include "../param.h"
#include "../file.h"
#include "../user.h"
#include "../reg.h"
#include "../inode.h"
#ifdef	AUSAML
#include	"../lnode.h"
#endif	AUSAML
#include "../systm.h"
#include "../proc.h"
#include "../text.h"

getswit()
{

	u.u_ar0[R0] = SW->integ;
}

gtime()
{

	u.u_ar0[R0] = time.hiint;	/* fix000 */
	u.u_ar0[R1] = time.loint;	/* fix000 */
}

stime()
{

	if ( suser() )  {
#ifdef	LRU_INODE
		/*
		 * On altering the time zap last inode reference times.
		 */
		register struct inode *ip;
		for(ip=inode;ip!= &inode[NINODE];ip++) ip->i_lrt=0;
#endif	LRU_INODE
		time.hiint = u.u_ar0[R0];	/* fix000 */
		time.loint = u.u_ar0[R1];	/* fix000 */
#ifndef	NEW_SLEEP
		wakeup( &tout );		/* fix000 */
#endif	NEW_SLEEP
	}
#ifdef	ALARM
#ifndef	MAX_PROC
	for(p = &proc[0]; p < &proc[NPROC]; p++)
#else
	for(p = &proc[0]; p <= max_proc; p++)
#endif	MAX_PROC
		if(p->p_stl)
		{
			spl1();
			diff = p->p_stl - newtime;
			if(newtime > 0)		/* leap fwd */
				if(diff <= 0)
					p->p_stl = 1;
				else
					p->p_stl = diff;
			else			/* leap back */
				if(diff > 0177777)
					p->p_stl = 0177777;
				else
					p->p_stl = diff;
			spl0();
		}
#endif	ALARM
}

setuid()
{
	register uid;

#ifndef	AUSAM16
	uid = u.u_ar0[R0].lobyte;
	if(u.u_ruid == uid.lobyte || suser()) {
		u.u_uid = uid;
		u.u_procp->p_uid = uid;
		u.u_ruid = uid;
	}
#endif	AUSAM16
#ifdef	AUSAM16
	uid = u.u_ar0[R0];
	if( u.u_ruid == uid || suser() )
		u.u_uid = u.u_ruid = u.u_procp->p_uid = uid;
#endif	AUSAM16
}

getuid()
{

#ifndef	AUSAM16
	u.u_ar0[R0].lobyte = u.u_ruid;
	u.u_ar0[R0].hibyte = u.u_uid;
#endif	AUSAM16
#ifdef	AUSAM16
	u.u_ar0[R0] = u.u_uid;
	u.u_ar0[R1] = u.u_ruid;
#endif	AUSAM16
}

#ifndef	AUSAM16
#ifdef	GROUP_ACCESS
setgid()
{
	register gid;

	gid = u.u_ar0[R0].lobyte;
	if(u.u_rgid == gid.lobyte || suser()) {
		u.u_gid = gid;
		u.u_rgid = gid;
	}
}

getgid()
{

	u.u_ar0[R0].lobyte = u.u_rgid;
	u.u_ar0[R0].hibyte = u.u_gid;
}
#endif
#endif	AUSAM16

getpid()
{
	u.u_ar0[R0] = u.u_procp->p_pid;
}

sync()
{

	update();
}

nice()
{
	register n;

	n = u.u_ar0[R0];
	if(n > 20)
		n = 20;
#ifndef	MORE_USER_PRIORITIES
	if(n < 0 && !suser())
#else
	if(n < 0)
	{
	    if( !suser())
#endif	MORE_USER_PRIORITIES
		n = 0;
#ifdef	MORE_USER_PRIORITIES
	}
	else
		n =<< 1;
#endif	MORE_USER_PRIORITIES
	u.u_procp->p_nice = n;
}

/*
 * Unlink system call.
 * Hard to avoid races here, especially		fix025
 * in unlinking directories.			fix025
 */
unlink()
{
	register *ip, *pp;
	extern uchar;

	pp = namei(&uchar, 2);
	if(pp == NULL)
		return;
	/*
	 * Check for unlink(".")		fix025
	 * to avoid hanging the iget		fix025
	 */
	if( pp->i_number != u.u_dent.u_ino )		/* fix025 */
		ip = iget(pp->i_dev,u.u_dent.u_ino);	/* fix025 */
	else {						/* fix025 */
		ip = pp;				/* fix025 */
		ip->i_count++;				/* fix025 */
	}						/* fix025 */
	if(ip == NULL)
		goto out1;				/* fix025 */
	if((ip->i_mode&IFMT)==IFDIR && !suser())
		goto out;
	/*
	 * Don't unlink a mounted file.			fix025
	 */
	if( ip->i_dev != pp->i_dev )			/* fix025 */
	{
		u.u_error = EBUSY;			/* fix025 */
		goto out;				/* fix025 */
	}
	if( ip->i_flag & ITEXT && ip->i_nlink == 1 )	/* fix025 */
	{
		u.u_error = ETXTBSY;			/* fix025 */
		goto out;				/* fix025 */
	}

#ifndef	AUSAM16
	if (ip->i_uid != u.u_uid && pp->i_uid != u.u_uid && ! suser())
#else
	if (guid(ip) != u.u_uid && guid(pp) != u.u_uid && ! suser())
#endif
		goto out;				/* fix045 */

	u.u_offset.loint =- DIRSIZ+2; /* fix000 */
	u.u_base = &u.u_dent;
	u.u_count = DIRSIZ+2;
	u.u_dent.u_ino = 0;
	writei(pp);
	ip->i_nlink--;
	ip->i_flag =| IUPD;

out:
	iput(ip);
out1:							/* fix025 */
	iput(pp);
}

chdir()
{
	register *ip;
	extern uchar;

	ip = namei(&uchar, 0);
	if(ip == NULL)
		return;
	if((ip->i_mode&IFMT) != IFDIR) {
		u.u_error = ENOTDIR;
	bad:
		iput(ip);
		return;
	}
	if(access(ip, IEXEC))
		goto bad;
	prele(ip);				/* fix025 */
	plock(u.u_cdir);			/* fix025 */
	iput(u.u_cdir);
	u.u_cdir = ip;
}

chmod()
{
	register *ip;

	if ((ip = owner()) == NULL)
		return;
	ip->i_mode =& ~07777;
	if (u.u_uid)
		u.u_arg[1] =& ~ISVTX;
#	ifdef	LOCKING
	if ( (ip->i_mode&IFMT) == IFDIR )
		u.u_arg[1] =& ~ILPROTOCOL;
#	endif	LOCKING
	ip->i_mode =| u.u_arg[1]&07777;
	ip->i_flag =| IACC;	/* fix029 */
	iput(ip);
}

chown()
{
	register *ip;

	if (!suser() || (ip = owner()) == NULL)
		return;
#ifndef	AUSAM16
	ip->i_uid = u.u_arg[1].lobyte;
	ip->i_gid = u.u_arg[1].hibyte;
#endif	AUSAM16
#ifdef	AUSAM16
	ip->i_uidl = u.u_arg[1].lobyte;
	ip->i_uidh = u.u_arg[1].hibyte;
#endif	AUSAM16
	ip->i_flag =| IACC;	/* fix029 */
	iput(ip);
}

#ifdef	SMDATE
/*
 * Change modified date of file:
 * Super users only may do this
 * time to r0-r1; sys smdate; file
 */

smdate()
{
	register struct inode *ip;
	long tbuf;	/* fix000 */

	if( !suser() ) return;
	if ((ip = owner()) == NULL)
		return;
	ip->i_flag =| IUPD;
	tbuf.loint = u.u_ar0[R1];	/* fix000 */
	tbuf.hiint = u.u_ar0[R0];	/* fix000 */
	iupdat(ip, tbuf);		/* fix000 */
	ip->i_flag =& ~IUPD;
	iput(ip);
}
#endif

ssig()
{
	register unsigned a;		/* fix042 */

	a = u.u_arg[0];
	if(a >= NSIG || a == SIGKIL)	/* fix042 */
	{
		u.u_error = EINVAL;
		return;
	}
	u.u_ar0[R0] = u.u_signal[a];
	u.u_signal[a] = u.u_arg[1];
#ifdef	IGNORE_SIGNALS
	if ( a < 16 )
	{
		register unsigned *p = &u.u_procp->p_ignsig;
		register b = 1<<a;

		if ( u.u_arg[1] & 1 )
			*p =| b;
		else
			*p =& ~b;
	}
#endif
	if(u.u_procp->p_sig == a)
		u.u_procp->p_sig = 0;
}

kill()
{
	register struct proc *p, *q;
	register a;
	int f;

	f = 0;
	a = u.u_ar0[R0];
	q = u.u_procp;
#ifndef	MAX_PROC
	for(p = &proc[0]; p < &proc[NPROC]; p++) {
#endif	MAX_PROC
#ifdef	MAX_PROC
	for(p = &proc[0]; p <= max_proc; p++) {
#endif	MAX_PROC
		if(p == q)
			continue;
		if(a != 0 && p->p_pid != a)
			continue;
#ifdef	ZOMBIE
		if( p->p_stat == SZOMB )
			continue;
#endif
		if(a == 0 && (p->p_ttyp != q->p_ttyp || p <= &proc[1]))
			continue;
		if(u.u_uid != 0 && u.u_uid != p->p_uid)
			continue;
		f++;
		psignal(p, u.u_arg[0]);
	}
	if(f == 0)
		u.u_error = ESRCH;
}

times()
{
	register *p;

	for(p = &u.u_utime; p  < &u.u_utime+4;) {	/* fix000 */
		suword(u.u_arg[0], *p++);
		u.u_arg[0] =+ 2;
	}
}

profil()
{

	u.u_prof[0] = u.u_arg[0] & ~1;	/* base of sample buf */
	u.u_prof[1] = u.u_arg[1];	/* size of same */
	u.u_prof[2] = u.u_arg[2];	/* pc offset */
	u.u_prof[3] = (u.u_arg[3]>>1) & 077777; /* pc scale */
}

#ifdef	SHARED_DATA
/*	.... and now for something completely different        */


enqueue()
{
	int register x,n;

	n = u.u_ar0[R0];
	while((x = fuword(n)) <= 0 && u.u_error == 0)	/* fix037 */
	{
		sleep(n|1, PPV);
	}
	suword(n, x-1);
}

dequeue()
{
	int register x,n;

	n = u.u_ar0[R0];
	x = fuword(n);
	if(u.u_error == 0)	/* fix037 */
	{
		suword(n, x+1);
		if(x == 0)
			wakeup(n|1);
	}
}
#endif

#ifdef	SETPSW
/*
 *	Return with ps set to supplied value
 *	old ps is pushed on stack.
 *	Only the super user may set certain bits
 */
setpsw()
{
	register m, s;

	m = 0140340;
	if(u.u_uid)
		m = 0177740;
	s = u.u_ar0[RPS];
	u.u_ar0[RPS] = (s&m) | (u.u_arg[0]&~m);
	grow(u.u_ar0[R6] =- 2);
	suword(u.u_ar0[R6], s);
}
#endif

#ifdef	TIME_LIMITS
tlimit()	/* cpu time limit */
{
	register t;

	spl6();
	u.u_tix = HZ;
	t = u.u_cpusec;
	u.u_cpusec = u.u_ar0[R0];
	spl0();
	u.u_ar0[R0] = t;	/* return remaining time */
}

clktim()	/* real time limit */
{
	register unsigned  x;

	spl1();
	x = u.u_procp->p_rtl;
	u.u_procp->p_rtl = u.u_ar0[R0].unsignd;
	spl0();
	u.u_ar0[R0].unsignd = x;
}
#endif

#ifdef	U_LOCK
slockon()	/* lock process in core */
{
	if ( suser() )
		u.u_procp->p_flag =| SLOCK;
}

slockoff()
{
	u.u_procp->p_flag =& ~SLOCK;
}
#endif

#ifdef	U_DELAY
sdelay()	/* user delay function */
{
  u.u_ar0[R0] = delay( u.u_ar0[R0] );
}
#endif

#ifdef	AUSAML
/*
 *	limits system call
 *
 *	sys limits; addr; function
 *
 *	limits( addr , function )
 *	struct lnode *addr;
 *	int function;
 *
 *	function = 0
 *		return own limit structure	(r0==1)
 *		ENOLIM => no limit structure
 *
 *	function = 1
 *		return limit structure associated with l_uid	(r0==1)
 *		ENOLIM => no limit structure
 *
 *	function = 2
 *		return all 'active' limit structures
 *		return r0 == number of active limit structures
 *
 *	function = 3
 *		super-users only
 *		initialize limit structure for l_uid
 *		no limit structure for super-users
 *		ETOOMANYU => no limit structures remaining for allocation.
 *
 *	function = OTHER
 *		EINVAL => illegal argument
 *
 */

limits()
{
	register i;
	register unsigned x;
	register struct lnode *l;
	struct lnode *addr;

	if( u.u_arg[0] & 1 ) {
		u.u_error = EINVAL;
		return;
	}
	addr = u.u_arg[0];	/* lnode buffer address */

	switch( u.u_arg[1] ) {	/* switch on desired function */
	default:
		u.u_error = EINVAL;
		return;
	case 0:
		l = u.u_procp->p_lnode;
		goto singo;
	case 1:
		x = fuword( & addr->l_uid );	/* get desired useruid */
		if( u.u_error )			/* fix037 */
			return;			/* fix037 */
		l = 0;
		for( i=0 ; i<MAXUSERS ; i++ )
			if( (lnode[i].l_refcount) && (lnode[i].l_uid==x) ) {
				l = &lnode[i];
				break;
			}
	singo:
		if( l == 0 ) {
			u.u_error = ENOLIM;
			return;
		}
#ifdef	_1170 | _1145
		copyout( l , addr , sizeof lnode[0] , SEG_USD );
#endif
#ifndef	_1170 | _1145
		copyout( l , addr , sizeof lnode[0] );
#endif
		u.u_ar0[R0] = 1;
		return;
	case 2:
		for( i=x=0 ; i<MAXUSERS ; i++ )
			if( lnode[i].l_refcount ) {
#ifdef	_1170 | _1145
				copyout( &lnode[i] , addr , sizeof lnode[0] , SEG_USD );
#endif
#ifndef	_1170 | _1145
				copyout( &lnode[i] , addr , sizeof lnode[0] );
#endif
				addr++;	/* step to next lnode */
				x++;	/* count how many */
			}
		u.u_ar0[R0] = x;
		return;
	case 3:
		if( !suser() ) return;	/* keep things reasonable */
		if( u.u_procp->p_lnode ) {
			u.u_error = ELIMEXIST;
			return;
		}
		x = fuword( & addr->l_uid );	/* get desired useruid */
		if( u.u_error )			/* fix037 */
			return;			/* fix037 */
		if( x == 0 ) {
			u.u_error = ENOROOTLIM;
			return;
		}
		l = 0;
		for( i=0 ; i<MAXUSERS ; i++ )
			if( lnode[i].l_refcount == 0 ) {
				if ( l == 0 ) l = &lnode[i];
			} else if( lnode[i].l_uid == x ) {
					l = &lnode[i];
					if( ++l->l_refcount >= l->l_plimit ) {
						--l->l_refcount;
						u.u_error = EPROCLIM;
						return;
					}
					goto found;
				}
		if( l == 0 ) {
			u.u_error = ETOOMANYU;
			return;
		}
#ifdef	_1170 | _1145
		copyin( addr , l , sizeof lnode[0] , SEG_USD );
#endif	_1170 | _1145
#ifndef	_1170 | _1145
		copyin( addr , l , sizeof lnode[0] );
#endif	_1170 | _1145
		l->l_refcount = 1;
	found:
		u.u_procp->p_lnode = l;
		u.u_ar0[R0] = 0;
		return;
	}
}
#endif	AUSAML

#ifdef	GETTAB

struct	tabdescr {
	char			*tb_base;	/* base of region */
	unsigned int		tb_size;	/* size of region */
	unsigned int		tb_items;	/* no. of elements in region */
	} tabdescr[] {
		{	proc,	sizeof proc,	NPROC	},
		{	text,	sizeof text,	NTEXT	},
		{	inode,	sizeof inode,	NINODE	},
		{	file,	sizeof file,	NFILE	},
	};

/*
 * Copy various system tables into user buffers
 */
gettable()
{
	register struct	tabdescr	*tbp;
	register char			*p;

	if (u.u_ar0[R0] >= (sizeof tabdescr / sizeof tabdescr[0]))
		goto bad;
	tbp = &tabdescr[u.u_ar0[R0]];
	p = u.u_arg[0];
	if (p != NULL) {
		if (p&01 || p>=(p + u.u_arg[1]) || u.u_arg[1]<tbp->tb_size)
			goto bad;
		if (copyout(tbp->tb_base, p, tbp->tb_size) < 0)
			goto bad;
	}
	u.u_ar0[R0] = tbp->tb_items;
	u.u_ar0[R1] = tbp->tb_base;
	return;

bad:
	u.u_error = EFAULT;
}
#endif	GETTAB