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