Ausam/sys/ken/sys1.c
#
/*
*/
#include "../defines.h"
#include "../param.h"
#ifdef AUSAML
#include "../lnode.h"
#endif AUSAML
#include "../systm.h"
#include "../file.h"
#include "../user.h"
#include "../proc.h"
#include "../buf.h"
#include "../reg.h"
#include "../inode.h"
#ifdef ZOMBIE
#include "../pzomb.h"
#endif ZOMBIE
#ifdef SHARED_DATA
#include "../text.h"
#endif SHARED_DATA
/*
* exec system call.
* Because of the fact that an I/O buffer is used
* to store the caller's arguments during exec,
* and more buffers are needed to read in the text file,
* deadly embraces waiting for free buffers are possible.
* Therefore the number of processes simultaneously
* running in exec has to be limited to NEXEC.
*/
#define EXPRI -1
exec()
{
int ap, na, nc, *bp;
int ts, ds, sep;
register c, *ip;
register char *cp;
extern uchar;
/*
* pick up file names
* and check various modes
* for execute permission
*/
ip = namei(&uchar, 0);
if(ip == NULL)
return;
while(execnt >= NEXEC)
sleep(&execnt, EXPRI);
execnt++;
bp = getblk(NODEV);
if(access(ip, IEXEC) || (ip->i_mode&IFMT)!=0)
goto bad;
/*
* pack up arguments into
* allocated disk buffer
*/
#ifndef MAPPED_BUFFERS
cp = bp->b_addr;
#else MAPPED_BUFFERS
cp = &b;
bswtch( bp );
#endif MAPPED_BUFFERS
na = 0;
nc = 0;
for(;;)
{
if((ap = fuword(u.u_arg[1])) == 0)
break;
if(u.u_error) /* fix037 */
goto bad;
na++;
u.u_arg[1] =+ 2;
for(;;) {
c = fubyte(ap++);
if(c == -1)
goto bad;
*cp++ = c;
nc++;
if(nc > 510) {
u.u_error = E2BIG;
goto bad;
}
if(c == 0)
break;
}
}
if((nc&1) != 0) {
*cp++ = 0;
nc++;
}
/*
* read in first 8 bytes
* of file for segment
* sizes:
* w0 = 407/410/411 (410 implies RO text) (411 implies sep ID)
#ifdef SHARED_DATA
* (412 implies shared data)
#endif
* w1 = text size
* w2 = data size
* w3 = bss size
#ifdef EP_ADDRESS
* w5 = entry point location
#endif
#ifdef SHARED_DATA
* w6 = special id for shared data
#endif
*/
u.u_base = &u.u_arg[0];
#ifndef EP_ADDRESS | SHARED_DATA
u.u_count = 8;
#endif
#ifdef EP_ADDRESS | SHARED_DATA
u.u_count = 16;
#endif
u.u_offset = 0; /* fix000 */
u.u_segflg = SEG_KER;
readi(ip);
#ifdef SHARED_DATA
/*
* must check permission to link to the shared data segment.
* Being super user is NOT a good criterion here, in fact
* this is one of the more important things to guard.
* GGR Sep 79.
*/
if(u.u_arg[0] == 0412) /* it is shared */
{
struct text *xp;
int *spid = u.u_arg[6]; /* MUST be int-> for no sensible reason */
/* search for this 'data' segment existing */
for(xp = text; xp < &text[NTEXT]; xp++)
if(xp->x_iptr != NULL && xp->x_spid == spid)
{
sep = (ip->i_mode & ISUID) != 0;
#ifdef AUSAM16
if ((sep == 0 && guid(xp->x_iptr) == u.u_uid)
|| (sep && (guid(ip) == guid(xp->x_iptr))))
#else AUSAM16
if ((sep == 0 && xp->x_iptr->i_uid == u.u_uid)
|| (sep && (ip->i_uid == xp->x_iptr->i_uid)))
#endif AUSAM16
break;
/* 'data' seg exists, and he can't touch it */
u.u_error = EPERM;
goto bad;
}
}
u.u_flags =& ~USHRDATA;
#endif
u.u_segflg = SEG_USD;
if(u.u_error)
goto bad;
sep = 0;
if(u.u_arg[0] == 0407) {
u.u_arg[2] =+ u.u_arg[1];
u.u_arg[1] = 0;
} else
if(u.u_arg[0] == 0411)
sep++; else
#ifdef SHARED_DATA
if(u.u_arg[0] != 0412)
#endif
if(u.u_arg[0] != 0410) {
u.u_error = ENOEXEC;
goto bad;
}
if(u.u_arg[1]!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
u.u_error = ETXTBSY;
goto bad;
}
/*
* find text and data sizes
* try them out for possible
* exceed of max sizes
*/
ts = ((u.u_arg[1]+63)>>6) & 01777;
ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777;
if(estabur(ts, ds, SSIZE, sep))
goto bad;
/*
* allocate and clear core
* at this point, committed
* to the new image
*/
#ifdef SHARED_DATA
if ( u.u_arg[0] == 0412 )
u.u_flags =| USHRDATA;
#endif SHARED_DATA
u.u_prof[3] = 0;
xfree();
expand(USIZE);
#ifndef SHARED_DATA
xalloc(ip);
#endif
#ifdef SHARED_DATA
if (u.u_flags&USHRDATA)
xalloc(ip , u.u_arg[6]);
else
xalloc(ip , ip);
#endif
c = USIZE+ds+SSIZE;
expand(c);
while(--c >= USIZE)
clearseg(u.u_procp->p_addr+c);
/*
* read in data segment
*/
estabur(0, ds, 0, 0);
u.u_base = 0;
u.u_offset.loint = 020+u.u_arg[1]; /* fix000 */
u.u_count = u.u_arg[2];
readi(ip);
/*
* initialize stack segment
*/
u.u_tsize = ts;
u.u_dsize = ds;
u.u_ssize = SSIZE;
u.u_sep = sep;
estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep);
#ifndef MAPPED_BUFFERS
cp = bp->b_addr;
#else MAPPED_BUFFERS
cp = &b;
bswtch( bp );
#endif MAPPED_BUFFERS
ap = -nc - na*2 - 4;
u.u_ar0[R6] = ap;
suword(ap, na);
c = -nc;
while(na--) {
suword(ap=+2, c);
do
subyte(c++, *cp);
while(*cp++);
}
suword(ap+2, -1);
/*
* turn off tracing, if you don't own the new process fix043
* set SUID/SGID protections, if no tracing
*/
#ifdef AUSAM16
if (u.u_uid && guid(ip) != u.u_uid) /* fix043 */
#else
if (u.u_uid && ip->i_uid != u.u_uid) /* fix043 */
#endif
u.u_procp->p_flag =& ~STRC; /* fix043 */
if ((u.u_procp->p_flag&STRC)==0) {
if(ip->i_mode&ISUID)
if(u.u_uid != 0) {
#ifndef AUSAM16
u.u_uid = ip->i_uid;
u.u_procp->p_uid = ip->i_uid;
#endif AUSAM16
#ifdef AUSAM16
u.u_uid = u.u_procp->p_uid = guid(ip);
#endif AUSAM16
}
#ifdef GROUP_ACCESS & !LOCKING
if(ip->i_mode&ISGID)
u.u_gid = ip->i_gid;
#endif
}
/*
* clear sigs, regs and return
*/
c = ip;
for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++)
if((*ip & 1) == 0)
*ip = 0;
#ifdef IGNORE_SIGNALS
u.u_procp->p_ignsig = 0;
#endif IGNORE_SIGNALS
for(cp = ®loc[0]; cp < ®loc[6];)
u.u_ar0[*cp++] = 0;
#ifndef EP_ADDRESS
u.u_ar0[R7] = 0;
#endif
#ifdef EP_ADDRESS
u.u_ar0[R7] = u.u_arg[5] & 0177776;
#endif
#ifdef FPU
for(ip = &u.u_fsav[0]; ip < &u.u_fsav[25];)
*ip++ = 0;
#endif
ip = c;
bad:
iput(ip);
brelse(bp);
if(execnt >= NEXEC)
wakeup(&execnt);
execnt--;
}
/*
* exit system call:
* pass back caller's r0
*/
rexit()
{
u.u_arg[0] = u.u_ar0[R0] << 8;
exit();
}
/*
* Release resources.
* Save u. area for parent to look at.
* Enter zombie state.
* Wake up parent and init processes,
* and dispose of children.
*/
exit()
{
register int *q, a;
register struct proc *p;
#ifdef BETTER_EXIT
expand(USIZE);
#endif BETTER_EXIT
#ifdef TIME_LIMITS
u.u_procp->p_rtl = 0; /* disable any clock time interval left */
u.u_cpusec = 0;
#endif TIME_LIMITS
u.u_procp->p_flag =& ~STRC;
for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];)
*q++ = 1;
for(q = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++)
if(a = *q) {
*q = NULL;
closef(a);
}
plock(u.u_cdir); /* fix025 */
iput(u.u_cdir);
xfree();
#ifndef ZOMBIE
a = malloc(swapmap, 1);
if(a == NULL)
panic("out of swap");
p = getblk(swapdev, a);
bcopy(&u, p->b_addr, 256);
bwrite(p);
#endif
q = u.u_procp;
mfree(coremap, q->p_size, q->p_addr);
#ifndef ZOMBIE
q->p_addr = a;
#endif
q->p_stat = SZOMB;
#ifdef ZOMBIE
q->pz_ur0 = u.u_arg[0];
q->pz_utime = u.u_utime + u.u_cutime;
q->pz_stime = u.u_stime + u.u_cstime;
#endif
#ifndef INIT_FIX
loop:
#ifndef MAX_PROC
for(p = &proc[0]; p < &proc[NPROC]; p++)
#else
for(p = &proc[0]; p <= max_proc; p++)
#endif MAX_PROC
if(q->p_ppid == p->p_pid) {
wakeup(&proc[1]);
wakeup(p);
#ifndef MAX_PROC
for(p = &proc[0]; p < &proc[NPROC]; p++)
#else
for(p = &proc[0]; p <= max_proc; p++)
#endif MAX_PROC
if(q->p_pid == p->p_ppid) {
p->p_ppid = 1;
if (p->p_stat == SSTOP)
setrun(p);
}
swtch();
/* no return */
}
q->p_ppid = 1;
goto loop;
#endif
#ifdef INIT_FIX
#define ORPHAN 0100000
a = ORPHAN;
#ifndef MAX_PROC
for(p = &proc[0]; p < &proc[NPROC]; p++)
#else
for(p = &proc[0]; p <= max_proc; p++)
#endif MAX_PROC
{
if(q->p_pid == p->p_ppid) /* child */
{
p->p_ppid = 1;
if(p->p_stat == SZOMB)
a++;
else if(p->p_stat == SSTOP)
setrun(p);
}
else if(q->p_ppid == p->p_pid) /* parent */
{
#ifdef PROCESS_QUEUES
if( p->p_stat == SSLEEP && p->p_wchan == p.integ )
#else
if( p->p_stat == SWAIT && p->p_wchan == p.integ )
#endif PROCESS_QUEUES
setrun(p); /* don't need wakeup */
a =& ~ORPHAN;
}
}
if(a)
{
if(a & ORPHAN)
q->p_ppid = 1;
p = &proc[1];
#ifdef PROCESS_QUEUES
if( p->p_stat == SSLEEP && p->p_wchan == p.integ )
#else
if( p->p_stat == SWAIT && p->p_wchan == p.integ )
#endif PROCESS_QUEUES
setrun(p);
}
swtch();
#endif
}
/*
* Wait system call.
* Search for a terminated (zombie) child,
* finally lay it to rest, and collect its status.
* Look also for stopped (traced) children,
* and pass back status from them.
*/
wait()
{
register f;
#ifndef ZOMBIE
register *bp;
#endif
register struct proc *p;
#ifdef ZOMBIE
register pid;
pid = u.u_procp->p_pid;
#endif
f = 0;
loop:
#ifndef MAX_PROC
for(p = &proc[0]; p < &proc[NPROC]; p++)
#else
for(p = &proc[0]; p <= max_proc; p++)
#endif MAX_PROC
#ifdef ZOMBIE
if ( p->p_ppid == pid ) {
#endif
#ifndef ZOMBIE
if(p->p_ppid == u.u_procp->p_pid) {
#endif
f++;
if(p->p_stat == SZOMB) {
#ifdef AUSAML
if( u.u_procp->p_pid == 1)
{
#ifdef _1170 | _1145
copyout(p, u.u_ar0[R0], sizeof proc[0], SEG_USD);
if( p->p_lnode )
copyout( p->p_lnode , u.u_ar0[R0] + sizeof proc[0] , sizeof lnode[0] , SEG_USD );
#endif _1170 | _1145
#ifndef _1170 | _1145
copyout(p, u.u_ar0[R0], sizeof proc[0]);
if( p->p_lnode )
copyout( p->p_lnode , u.u_ar0[R0] + sizeof proc[0] , sizeof lnode[0] );
#endif _1170 | _1145
}
if( p->p_lnode ) p->p_lnode->l_refcount--; /* one less user proc */
#endif AUSAML
u.u_ar0[R0] = p->p_pid;
#ifndef ZOMBIE
bp = bread(swapdev, f=p->p_addr);
mfree(swapmap, 1, f);
#endif
p->p_stat = NULL;
p->p_pid = 0;
p->p_ppid = 0;
p->p_sig = 0;
p->p_ttyp = 0;
p->p_flag = 0;
#ifdef MAX_PROC
if( p >= max_proc ) {
max_proc = p;
while( (--max_proc)->p_stat == NULL );
}
#endif MAX_PROC
#ifndef ZOMBIE
p = bp->b_addr;
u.u_cstime =+ p->u_cstime + p->u_stime ; /* fix000 */
u.u_cutime =+ p->u_cutime + p->u_utime ; /* fix000 */
u.u_ar0[R1] = p->u_arg[0];
brelse(bp);
#endif
#ifdef ZOMBIE
u.u_cstime =+ p->pz_stime;
u.u_cutime =+ p->pz_utime;
u.u_ar0[R1] = p->pz_ur0;
#endif
p->p_wchan = 0; /* fix025 */
return;
}
if(p->p_stat == SSTOP) {
if((p->p_flag&SWTED) == 0) {
p->p_flag =| SWTED;
u.u_ar0[R0] = p->p_pid;
u.u_ar0[R1] = (p->p_sig<<8) | 0177;
return;
}
p->p_flag =& ~(STRC|SWTED);
setrun(p);
}
}
if(f) {
sleep(u.u_procp, PWAIT);
goto loop;
}
u.u_error = ECHILD;
}
/*
* fork system call.
*/
fork()
{
#ifdef LARGE_FILE_REFERENCES
{
register i;
register struct file *fp;
register count;
for(i=0 ; i<NOFILE ; i++) {
if ((fp = u.u_ofile[i]) != NULL) {
count = fp->f_count&0377;
if ( count > (0377-NOFILE) ) {
u.u_error = ENREF;
goto out;
}
}
}
}
#endif LARGE_FILE_REFERENCES
#ifdef SWAP_CHECK
{
register char *a;
register largest = maxmem >> 3;
if ( a = malloc( swapmap, largest ) )
mfree( swapmap, largest, a );
else
{
uprints("\nswap device full\n");
u.u_error = EAGAIN;
goto out;
}
}
#endif SWAP_CHECK
{
register struct proc *p1, *p2;
p1 = u.u_procp;
for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++)
if(p2->p_stat == NULL)
goto found;
u.u_error = EAGAIN;
goto out;
found:
#ifdef AUSAML
{
register struct lnode *l;
if( l = u.u_procp->p_lnode ) {
/* limit structure exists */
if( l->l_refcount >= l->l_plimit ) {
/* too many processes */
u.u_error = EPROCLIM;
goto out;
}
l->l_refcount++;
}
}
#endif AUSAML
if(newproc()) {
u.u_ar0[R0] = p1->p_pid;
u.u_cstime = 0; /* fix000 */
u.u_stime = 0; /* fix000 */
u.u_cutime = 0; /* fix000 */
u.u_utime = 0; /* fix000 */
#ifdef LOCKING
/* ensure that children never inherit a lock on a file */
u.u_locki = NULL;
#endif
return;
}
u.u_ar0[R0] = p2->p_pid;
}
out:
u.u_ar0[R7] =+ 2;
}
/*
* break system call.
* -- bad planning: "break" is a dirty word in C.
*/
sbreak()
{
register a, n, d;
int i;
/*
* set n to new data size
* set d to new-old
* set n to new total size
*/
n = (((u.u_arg[0]+63)>>6) & 01777);
if(!u.u_sep)
n =- nseg(u.u_tsize) * 128;
if(n < 0)
n = 0;
d = n - u.u_dsize;
n =+ USIZE+u.u_ssize;
if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep))
return;
u.u_dsize =+ d;
if(d > 0)
goto bigger;
a = u.u_procp->p_addr + n - u.u_ssize;
i = n;
n = u.u_ssize;
while(n--) {
copyseg(a-d, a);
a++;
}
expand(i);
return;
bigger:
# ifdef SWAP_CHECK
i = maxmem >> 3;
if ( a = malloc( swapmap, i ) )
mfree( swapmap, i, a );
else
{
u.u_error = ENOMEM;
u.u_dsize =- d;
return;
}
# endif SWAP_CHECK
expand(n);
a = u.u_procp->p_addr + n;
n = u.u_ssize;
while(n--) {
a--;
copyseg(a-d, a);
}
while(d--)
clearseg(--a);
}
#ifdef GPROCS
/*
* gprocs - return process table to user
*/
gprocs()
{
register p, i;
if( (p = u.u_ar0[R0]) & 1 ){
u.u_error = EINVAL; /* odd address */
return;
}
#ifndef MAX_PROC
if(p)
#ifndef _1170 | _1145
copyout(&proc[0], p, sizeof proc );
#else
copyout(&proc[0], p, sizeof proc, SEG_USD );
#endif _1170 | _1145
u.u_ar0[R0] = NPROC;
#else
i = max_proc - &proc[0] + 1;
if(p)
#ifndef _1170 | _1145
copyout(&proc[0], p, sizeof proc[0] * i);
#else
copyout(&proc[0], p, sizeof proc[0] * i, SEG_USD);
#endif _1170 | _1145
u.u_ar0[R0] = i;
#endif MAX_PROC
}
#endif