#include "../h/local.h" #ifdef SCCS_ID static char SCCS_ID [] = "@(#)sys4.c 3.5 15:53:01 - 82/02/03 "; #endif SCCS_ID #include "../h/param.h" #include "../h/systm.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/reg.h" #include "../h/inode.h" #include "../h/proc.h" #include "../h/timeb.h" /* * Everything in this file is a routine implementing a system call. */ #ifdef SVC6 /* * Read the console switches */ getswit() { extern int csw; /* read by display() */ u.u_r.r_val1 = csw; } #endif /* * return the current time (old-style entry) */ gtime() { #ifdef SVC6 if (u.u_svc6) { u.u_r.r_val1 = 0; u.u_r.r_val2 = time; return; } #endif u.u_r.r_time = time; } /* * New time entry-- return TOD with milliseconds, timezone, * DST flag */ ftime() { register struct a { struct timeb *tp; } *uap; struct timeb t; register unsigned ms; #ifdef SVC6 if (u.u_svc6) { /* Version 6 SLEEP call */ register struct proc *p; p = u.u_procp; spl7(); p->p_clktim = u.u_ar0[R0]; while (p->p_clktim != 0) sleep((caddr_t)&p->p_clktim, PSLEP); spl0(); return; } #endif uap = (struct a *)u.u_ap; spl7(); t.time = time; ms = lbolt; spl0(); if (ms > HZ) { ms -= HZ; t.time++; } t.millitm = (1000*ms)/HZ; t.timezone = timezone; t.dstflag = dstflag; if (copyout((caddr_t)&t, (caddr_t)uap->tp, sizeof(t)) < 0) u.u_error = EFAULT; } /* * Set the time */ stime() { register struct a { time_t time; } *uap; #ifdef SVC6 if (u.u_svc6) { if (suser()) time = u.u_ap[1]; return; } #endif uap = (struct a *)u.u_ap; if(suser()) time = uap->time; } setuid() { register uid; register struct a { int uid; } *uap; uap = (struct a *)u.u_ap; uid = uap->uid; if(u.u_ruid == uid || suser()) { u.u_uid = uid; u.u_procp->p_uid = uid; u.u_ruid = uid; } } getuid() { #ifdef SVC6 if (u.u_svc6) { u.u_r.r_val1 = ((u.u_uid&0377)<<8) | (u.u_ruid&0377); return; } #endif u.u_r.r_val1 = u.u_ruid; u.u_r.r_val2 = u.u_uid; } setgid() { register gid; register struct a { int gid; } *uap; uap = (struct a *)u.u_ap; gid = uap->gid; if(u.u_rgid == gid || suser()) { u.u_gid = gid; u.u_rgid = gid; } } getgid() { #ifdef SVC6 if (u.u_svc6) { u.u_r.r_val1 = ((u.u_gid&0377)<<8) | (u.u_rgid&0377); return; } #endif u.u_r.r_val1 = u.u_rgid; u.u_r.r_val2 = u.u_gid; } getpid() { u.u_r.r_val1 = u.u_procp->p_pid; u.u_r.r_val2 = u.u_procp->p_ppid; } sync() { update(); } nice() { register n; register struct a { int niceness; } *uap; uap = (struct a *)u.u_ap; n = uap->niceness; if(n < 0 && !suser()) n = 0; n += u.u_procp->p_nice; if(n >= 2*NZERO) n = 2*NZERO -1; if(n < 0) n = 0; u.u_procp->p_nice = n; } /* * Unlink system call. * Hard to avoid races here, especially * in unlinking directories. */ unlink() { register struct inode *ip, *pp; struct a { char *fname; }; pp = namei(uchar, 2); if(pp == NULL) return; /* * Check for unlink(".") * to avoid hanging on the iget */ #ifdef USTEST if (USTOI(pp->i_number) == USTOI(u.u_dent.d_ino)) #else USTEST if (pp->i_number == u.u_dent.d_ino) #endif USTEST { ip = pp; ip->i_count++; } else ip = iget(pp->i_dev, u.u_dent.d_ino); if(ip == NULL) goto out1; if((ip->i_mode&IFMT)==IFDIR && !suser()) goto out; /* * Don't unlink a mounted file. */ if (ip->i_dev != pp->i_dev) { u.u_error = EBUSY; goto out; } if (ip->i_flag&ITEXT) xrele(ip); /* try once to free text */ if (ip->i_flag&ITEXT && ip->i_nlink==1) { u.u_error = ETXTBSY; goto out; } u.u_offset -= sizeof(struct direct); u.u_base = (caddr_t)&u.u_dent; u.u_count = sizeof(struct direct); u.u_dent.d_ino = 0; writei(pp); ip->i_nlink--; ip->i_flag |= ICHG; out: iput(ip); out1: iput(pp); } chdir() { chdirec(&u.u_cdir); } chroot() { if (suser()) chdirec(&u.u_rdir); } chdirec(ipp) register struct inode **ipp; { register struct inode *ip; struct a { char *fname; }; ip = namei(uchar, 0); if(ip == NULL) return; if((ip->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; goto bad; } if(access(ip, IEXEC)) goto bad; prele(ip); if (*ipp) { plock(*ipp); iput(*ipp); } *ipp = ip; return; bad: iput(ip); } chmod() { register struct inode *ip; register struct a { char *fname; int fmode; } *uap; uap = (struct a *)u.u_ap; if ((ip = owner()) == NULL) return; ip->i_mode &= ~07777; if (u.u_uid) uap->fmode &= ~ISVTX; ip->i_mode |= uap->fmode&07777; ip->i_flag |= ICHG; if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) xrele(ip); iput(ip); } chown() { register struct inode *ip; register struct a { char *fname; int uid; int gid; } *uap; uap = (struct a *)u.u_ap; if (!suser() || (ip = owner()) == NULL) return; #ifdef SVC6 if (u.u_svc6) { ip->i_uid = u.u_ap[1]&0377; ip->i_gid = (u.u_ap[1]>>8)&0377; } else { #endif ip->i_uid = uap->uid; ip->i_gid = uap->gid; #ifdef SVC6 } #endif ip->i_flag |= ICHG; iput(ip); } ssig() { register a; struct a { int signo; int fun; } *uap; uap = (struct a *)u.u_ap; a = uap->signo; #ifndef DEC /*** *** Signal 0 means return from signal routine (i.e. emulate rti) *** Pop PS, PC and SP off user stack. ***/ if (a == 0) { register int aps, *asp; asp = u.u_ar0[RSP]; if ((aps = fuword(asp++)) & (1<<31)) /* No user stack */ u.u_nostack = 1; u.u_ar0[RPS] = (aps & 0x100f) | (u.u_ar0[RPS] & ~0x100f); u.u_ar0[PC] = fuword(asp++); u.u_ar0[RSP] = fuword(asp); return; } #endif if(a<=0 || a>=NSIG || a==SIGKIL) { u.u_error = EINVAL; return; } u.u_r.r_val1 = u.u_signal[a]; u.u_signal[a] = uap->fun; u.u_procp->p_sig &= ~(1<<(a-1)); } kill() { register struct proc *p, *q; register a; register struct a { int pid; int signo; } *uap; int f, priv; uap = (struct a *)u.u_ap; f = 0; a = uap->pid; priv = 0; if (a==-1 && u.u_uid==0) { priv++; a = 0; } q = u.u_procp; for(p = &proc[0]; p < procNPROC; p++) { if(p->p_stat == NULL) continue; if(a != 0 && p->p_pid != a) continue; if(a==0 && ((p->p_pgrp!=q->p_pgrp&&priv==0) || p<=&proc[1])) continue; if(u.u_uid != 0 && u.u_uid != p->p_uid) continue; f++; psignal(p, uap->signo); } if(f == 0) u.u_error = ESRCH; } times() { register struct a { time_t (*times)[4]; } *uap; uap = (struct a *)u.u_ap; #ifdef SVC6 if (u.u_svc6) { register int *tp; tp = (int *)uap->times; suword(tp++, u.u_utime); suword(tp++, u.u_stime); suword(tp++, 0); suword(tp++, u.u_cutime); suword(tp++, 0); suword(tp, u.u_cstime); return; } #endif if (copyout((caddr_t)&u.u_utime, (caddr_t)uap->times, sizeof(*uap->times)) < 0) u.u_error = EFAULT; } profil() { register struct a { short *bufbase; unsigned bufsize; unsigned pcoffset; unsigned pcscale; } *uap; uap = (struct a *)u.u_ap; #ifdef SVC6 if (u.u_svc6) { u.u_prof.pr_base = (int)uap->bufbase & ~(NBPW-1); u.u_prof.pr_size = uap->bufsize; u.u_prof.pr_off = uap->pcoffset; u.u_prof.pr_scale = uap->pcscale >> 1; return; } #endif u.u_prof.pr_base = uap->bufbase; u.u_prof.pr_size = uap->bufsize; u.u_prof.pr_off = uap->pcoffset; u.u_prof.pr_scale = uap->pcscale; } /* * alarm clock signal */ alarm() { register struct proc *p; register c; register struct a { int deltat; } *uap; uap = (struct a *)u.u_ap; p = u.u_procp; c = p->p_clktim; p->p_clktim = uap->deltat; u.u_r.r_val1 = c; } /* * indefinite wait. * no one should wakeup(&u) */ pause() { for(;;) sleep((caddr_t)&u, PSLEP); } /* * mode mask for creation of files */ umask() { register struct a { int mask; } *uap; register t; uap = (struct a *)u.u_ap; t = u.u_cmask; u.u_cmask = uap->mask & 0777; u.u_r.r_val1 = t; } /* * Set IUPD and IACC times on file. * Can't set ICHG. */ utime() { register struct a { char *fname; time_t *tptr; } *uap; register struct inode *ip; time_t tv[2]; uap = (struct a *)u.u_ap; if ((ip = owner()) == NULL) return; #ifdef SVC6 if (u.u_svc6) tv[0] = tv[1] = u.u_ar0[R1]; else #endif if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { u.u_error = EFAULT; return; } ip->i_flag |= IACC|IUPD|ICHG; iupdat(ip, &tv[0], &tv[1]); iput(ip); }