2.11BSD/sys/sys/kern_prot.c
/*
* Copyright (c) 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)kern_prot.c 1.4 (2.11BSD GTE) 1997/11/28
*/
/*
* System calls related to processes and protection
*/
#include "param.h"
#include "user.h"
#include "proc.h"
#include "systm.h"
#ifdef QUOTA
#include "quota.h"
#endif
getpid()
{
u.u_r.r_val1 = u.u_procp->p_pid;
u.u_r.r_val2 = u.u_procp->p_ppid; /* XXX - compatibility */
}
getppid()
{
u.u_r.r_val1 = u.u_procp->p_ppid;
}
getpgrp()
{
register struct a {
int pid;
} *uap = (struct a *)u.u_ap;
register struct proc *p;
if (uap->pid == 0) /* silly... */
uap->pid = u.u_procp->p_pid;
p = pfind(uap->pid);
if (p == 0) {
u.u_error = ESRCH;
return;
}
u.u_r.r_val1 = p->p_pgrp;
}
getuid()
{
u.u_r.r_val1 = u.u_ruid;
u.u_r.r_val2 = u.u_uid; /* XXX */
}
geteuid()
{
u.u_r.r_val1 = u.u_uid;
}
getgid()
{
u.u_r.r_val1 = u.u_rgid;
u.u_r.r_val2 = u.u_groups[0]; /* XXX */
}
getegid()
{
u.u_r.r_val1 = u.u_groups[0];
}
/*
* getgroups and setgroups differ from 4.X because the VAX stores group
* entries in the user structure as shorts and has to convert them to ints.
*/
getgroups()
{
register struct a {
u_int gidsetsize;
int *gidset;
} *uap = (struct a *)u.u_ap;
register gid_t *gp;
for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--)
if (gp[-1] != NOGROUP)
break;
if (uap->gidsetsize < gp - u.u_groups) {
u.u_error = EINVAL;
return;
}
uap->gidsetsize = gp - u.u_groups;
u.u_error = copyout((caddr_t)u.u_groups, (caddr_t)uap->gidset,
uap->gidsetsize * sizeof(u.u_groups[0]));
if (u.u_error)
return;
u.u_r.r_val1 = uap->gidsetsize;
}
setpgrp()
{
register struct proc *p;
register struct a {
int pid;
int pgrp;
} *uap = (struct a *)u.u_ap;
if (uap->pid == 0) /* silly... */
uap->pid = u.u_procp->p_pid;
p = pfind(uap->pid);
if (p == 0) {
u.u_error = ESRCH;
return;
}
/* need better control mechanisms for process groups */
if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) {
u.u_error = EPERM;
return;
}
p->p_pgrp = uap->pgrp;
}
setgroups()
{
register struct a {
u_int gidsetsize;
int *gidset;
} *uap = (struct a *)u.u_ap;
register gid_t *gp;
if (!suser())
return;
if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
u.u_error = EINVAL;
return;
}
u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)u.u_groups,
uap->gidsetsize * sizeof (u.u_groups[0]));
if (u.u_error)
return;
for (gp = &u.u_groups[uap->gidsetsize]; gp < &u.u_groups[NGROUPS]; gp++)
*gp = NOGROUP;
}
/*
* Check if gid is a member of the group set.
*/
groupmember(gid)
gid_t gid;
{
register gid_t *gp;
for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
if (*gp == gid)
return (1);
return (0);
}
/*
* Get login name, if available.
*/
int
getlogin()
{
register struct a
{
char *namebuf;
u_int namelen;
} *uap = (struct a *)u.u_ap;
register int error;
if (uap->namelen > sizeof (u.u_login))
uap->namelen = sizeof (u.u_login);
error = copyout(u.u_login, uap->namebuf, uap->namelen);
return(u.u_error = error);
}
/*
* Set login name.
* It is not clear whether this should be allowed if the process
* is not the "session leader" (the 'login' process). But since 2.11
* doesn't have sessions and it's almost impossible to know if a process
* is "login" or not we simply restrict this call to the super user.
*/
int
setlogin()
{
register struct a
{
char *namebuf;
} *uap = (struct a *)u.u_ap;
register int error;
char newname[MAXLOGNAME + 1];
if (!suser())
return(u.u_error); /* XXX - suser should be changed! */
/*
* copinstr() wants to copy a string including a nul but u_login is not
* necessarily nul-terminated. Copy into a temp that is one character
* longer then copy into place if that fit.
*/
bzero(newname, sizeof (newname));
error = copyinstr(uap->namebuf, newname, sizeof(newname), NULL);
if (error == 0)
bcopy(newname, u.u_login, sizeof (u.u_login));
return(u.u_error = error);
}