Ultrix-3.1/sys/sys/sys_v7m.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
/*
* SCCSID: @(#)sys_v7m.c 3.0 4/21/86
*/
/*
* This file contains system calls that are specific to
* V7M-11. They are accessed via the syslocal[] table.
*/
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <sys/systm.h>
#include <sys/utsname.h>
unsigned hnamelen = 0;
long LocalAddr;
gethostid()
{
u.u_r.r_off = LocalAddr;
}
sethostid()
{
struct a {
long hostid;
} *uap = (struct a *)u.u_ap;
if (suser())
LocalAddr = uap->hostid;
}
/* changed gethostname and sethostname for the hostname to be updated in
* utsname.nodename (in sys/utsname.h). This structure is used by uname().
* George Mathew: 7/30/85
*/
gethostname()
{
struct a {
char *hostname;
unsigned len;
};
register struct a *uap;
register unsigned len;
uap = (struct a *)u.u_ap;
len = uap->len;
if (len > hnamelen + 1)
len = hnamelen + 1;
if (copyout(utsname.nodename, uap->hostname, len))
u.u_error = EFAULT;
}
sethostname()
{
struct a {
char *hostname;
unsigned len;
};
register struct a *uap;
register unsigned len;
uap = (struct a *)u.u_ap;
if (!suser())
return;
if (uap->len > sizeof(utsname.nodename) - 1) {
u.u_error = EINVAL;
return;
}
hnamelen = uap->len;
if (copyin(uap->hostname, utsname.nodename, uap->len))
u.u_error = EFAULT;
utsname.nodename[hnamelen] = 0;
}
/*
* zaptty - zap the controlling tty. This is useful for restarting
* demons that die for some reason and they shouldn't be
* associated with any terminal. If any terminal is opened
* after the zaptty command, that terminal becomes the
* controlling tty. Obviously, this is a superuser only command.
*/
zaptty()
{
if (suser()) {
u.u_procp->p_pgrp = 0;
u.u_ttyp = 0;
u.u_ttyd = 0;
}
}
extern int fpemulation;
fpsim()
{
register struct a {
int nfpval;
} *uap = (struct a *)u.u_ap;
u.u_rval1 = fpemulation;
if (uap->nfpval == 0 || uap->nfpval == 1) {
if (u.u_uid)
u.u_error = EPERM;
else if (fpemulation != 2)
fpemulation = uap->nfpval;
else
u.u_error = ENODEV;
} else if (uap->nfpval != 2)
u.u_error = EINVAL;
}
/*
* event flag system call
*
* 1/1984 Bill Burns
*
* one syscall for all event flag functions
* usage is as follows:
*
* evntflg(req, flag, value)
* int req; request, read, write, release, set, clear
* int flag; if request then flag == mode
* if read, write, release, set or clear, then flag == efid
* long value; initail value for request
* new value for write
* bit position for set or clear
* not used for read or release.
*/
#include <sys/eflg.h>
/* extern int NEFLG; should come from sysgen (c.c) */
#define NEFLG 2
struct eflg {
int e_efid; /* unique id */
int e_pid; /* controlling pid */
int e_pgrp; /* prog group */
int e_mode; /* mode (own r/w, gr r/w, wo r/w) */
long e_flags; /* actual flags */
} eflg[NEFLG];
int efid;
evntflg()
{
struct eflg *efp, *efgp;
struct proc *pp;
long oldflg;
struct a {
int req;
int flag;
long value;
} *uap;
int req, flag;
long value;
uap = (struct a *)u.u_ap;
req = uap->req;
flag = uap->flag;
value = uap->value;
/* weed out stupid calls */
if(req == 0) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
switch(req) {
case EFREQ:
retry:
efid++;
if(efid >= 30000) {
efid = 1;
goto retry;
}
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if (efgp->e_efid==efid)
goto retry;
}
efp = NULL;
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if((efgp->e_mode == NULL) && (efgp->e_efid == NULL)) {
efp = efgp;
break;
}
}
if(!efp) {
u.u_error = ENOSPC;
u.u_r.r_off = (long)-1;
return;
}
if((flag & ~0666) || (flag == 0)){
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
efp->e_efid = efid;
efp->e_mode = flag;
efp->e_flags = value;
pp = u.u_procp;
efp->e_pid = pp->p_pid;
efp->e_pgrp = pp->p_pgrp;
u.u_r.r_off = efid;
return;
case EFRD:
if(!flag) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
efp = NULL;
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if (efgp->e_efid == flag)
efp = efgp;
}
if(efp == NULL) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
pp = u.u_procp;
if(efp->e_pid == pp->p_pid) {
if(efp->e_mode & OWR) {
u.u_r.r_off = efp->e_flags;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else if(efp->e_pgrp == pp->p_pgrp) {
if(efp->e_mode & GRR) {
u.u_r.r_off = efp->e_flags;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else {
if(efp->e_mode & WOR) {
u.u_r.r_off = efp->e_flags;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
}
case EFWRT:
if(!flag) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
efp = NULL;
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if (efgp->e_efid == flag)
efp = efgp;
}
if(efp == NULL) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
pp = u.u_procp;
if(efp->e_pid == pp->p_pid) {
if(efp->e_mode & OWW) {
oldflg = efp->e_flags;
efp->e_flags = value;
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else if(efp->e_pgrp == pp->p_pgrp) {
if(efp->e_mode & GRW) {
oldflg = efp->e_flags;
efp->e_flags = value;
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else {
if(efp->e_mode & WOW) {
oldflg = efp->e_flags;
efp->e_flags = value;
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
}
case EFSET:
if(!flag) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
efp = NULL;
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if (efgp->e_efid == flag)
efp = efgp;
}
if(efp == NULL) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
pp = u.u_procp;
if(efp->e_pid == pp->p_pid) {
if(efp->e_mode & OWW) {
oldflg = efp->e_flags;
efp->e_flags |= (1 << value);
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else if(efp->e_pgrp == pp->p_pgrp) {
if(efp->e_mode & GRW) {
oldflg = efp->e_flags;
efp->e_flags |= (1 << value);
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else {
if(efp->e_mode & WOW) {
oldflg = efp->e_flags;
efp->e_flags |= (1 << value);
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
}
case EFCLR:
if(!flag) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
efp = NULL;
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if (efgp->e_efid == flag)
efp = efgp;
}
if(efp == NULL) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
pp = u.u_procp;
if(efp->e_pid == pp->p_pid) {
if(efp->e_mode & OWW) {
oldflg = efp->e_flags;
efp->e_flags &= ~(1 << value);
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else if(efp->e_pgrp == pp->p_pgrp) {
if(efp->e_mode & GRW) {
oldflg = efp->e_flags;
efp->e_flags &= ~(1 << value);
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
} else {
if(efp->e_mode & WOW) {
oldflg = efp->e_flags;
efp->e_flags &= ~(1 << value);
u.u_r.r_off = oldflg;
return;
} else {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
}
case EFREL:
efp = NULL;
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if (efgp->e_efid == flag)
efp = efgp;
}
if(efp == NULL) {
u.u_error = EINVAL;
u.u_r.r_off = (long)-1;
return;
}
pp = u.u_procp;
if(efp->e_pid != pp->p_pid) {
u.u_error = EACCES;
u.u_r.r_off = (long)-1;
return;
}
oldflg = efp->e_flags;
efp->e_mode = 0;
efp->e_efid = 0;
u.u_r.r_off = oldflg;
return;
} /* end of switch */
}
/*
* routine called on exit of
* a process to clean out eflg
* structures.
*
*/
eflgcln(p)
struct proc *p;
{
struct eflg *efgp;
for(efgp = &eflg[0]; efgp < &eflg[NEFLG]; efgp++) {
if (efgp->e_pid == p->p_pid) {
efgp->e_efid = NULL;
efgp->e_mode = NULL;
}
}
}
getfp()
{
register struct a {
int insptr;
int bufptr;
} *uap;
register unsigned inst;
uap = (struct a *)u.u_ap;
inst = fuiword((caddr_t)uap->insptr);
suword((caddr_t)uap->bufptr, inst);
}
/*
* fperr system call
* return floating point error registers
*/
fperr()
{
u.u_rval1 = u.u_fperr.f_fec;
u.u_rval2 = u.u_fperr.f_fea;
}
/*
* nostk -- Set up the process to have no stack segment.
* The process is responsible for the management
* of its own stack, and can thus use the full
* 64k byte address space.
*/
nostk()
{
register size;
size = u.u_procp->p_size - u.u_ssize;
if (estabur(u.u_tsize, u.u_dsize, 0, u.u_sep, RO))
return;
u.u_ssize = 0;
expand(size);
}
/*
* Sleep for less than 1 second.
* Silently enforces that non-suser procesess can
* only nap for 1 second.
*/
nap()
{
register struct a {
int ticks;
};
register ticks;
register s;
extern int hz;
int wakeup();
ticks = ((struct a *)u.u_ap)->ticks;
if (ticks < 0)
return;
if (ticks > hz && u.u_uid)
ticks = hz;
s = spl6();
timeout (wakeup, (caddr_t)u.u_procp+1, ticks);
sleep((caddr_t)u.u_procp+1, PZERO-1);
splx(s);
}
/*
* renice -- change the nice value of a process
*/
renice()
{
register struct proc *p;
register struct a {
int pid;
int nice;
} *uap;
uap = (struct a *) u.u_ap;
/*
* Don't renice swapper, init, or elc!
*/
for (p = &proc[3]; p <= maxproc; p++)
if (p->p_pid == uap->pid) {
if (suser()) {
u.u_rval1 = p->p_nice;
if (uap->nice > 127)
p->p_nice = 127;
else if (uap->nice < -127)
p->p_nice = -127;
else
p->p_nice = uap->nice;
} else if (p->p_uid == u.u_uid) {
u.u_rval1 = p->p_nice;
if (uap->nice > p->p_nice) {
if (uap->nice > 127)
p->p_nice = 127;
else
p->p_nice = uap->nice;
}
u.u_error = 0;
}
return;
}
u.u_error = ESRCH;
}
#ifdef NEWLIMITS
#include <sys/acct.h>
/*
* Enforce login limits. This is called by login.
* Init calls this to set the limit. Valid limits
* are 8*17, 16*17, 32*17, and 100*17. In octal that
* is 0210, 0420, 01040, and 03244. Bits 0174103 wil
* never be set, so we check some of them to verify
* a valid user limit.
* The current number of users is kept in cnl, which
* is 131*13 + current number of users.
*/
int cnl = 131*13;
lim()
{
register struct a {
int arg;
} *uap = (struct a *) u.u_ap;
static unsigned int x = 0173355; /* garbage value */
register unsigned int a1, a2;
if (uap->arg && u.u_procp->p_pid == 1) { /* Only init can set the limit */
a2 = uap->arg;
if (!(a2&024103))
u.u_rval1 = (x = a2)/17;
else {
u.u_rval1 = 0;
x = 0173355; /* arbitray, just some bad bits */
}
return;
}
a1 = cnl;
if (!((a2 = x)&0154103)) /* Has the limit been fiddled ? */
a1 %= 131; /* nope, get # users */
a2 /= 17;
if (u.u_acflag & ARESV) /* are we already a login process? */
return; /* yep, we're already counted */
if (a1 >= a2)
u.u_error = E2BIG;
else {
u.u_acflag |= ARESV; /* The reserve bit marks login procs */
++cnl;
}
}
#endif NEWLIMITS