xref: /csrg-svn/sys/kern/kern_prot.c (revision 54339)
123372Smckusick /*
247540Skarels  * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
347540Skarels  * of California.  All rights reserved.
423372Smckusick  *
544439Sbostic  * %sccs.include.redist.c%
637578Smckusick  *
7*54339Smckusick  *	@(#)kern_prot.c	7.23 (Berkeley) 06/23/92
823372Smckusick  */
97420Sroot 
107420Sroot /*
117498Sroot  * System calls related to processes and protection
127420Sroot  */
137420Sroot 
1417092Sbloom #include "param.h"
1537578Smckusick #include "acct.h"
1617092Sbloom #include "systm.h"
1747540Skarels #include "ucred.h"
1817092Sbloom #include "proc.h"
1917092Sbloom #include "timeb.h"
2017092Sbloom #include "times.h"
2137578Smckusick #include "malloc.h"
227420Sroot 
2343393Skarels /* ARGSUSED */
2443393Skarels getpid(p, uap, retval)
2543393Skarels 	struct proc *p;
2643393Skarels 	void *uap;
2743393Skarels 	int *retval;
2843393Skarels {
2937579Smckusick 
3043393Skarels 	*retval = p->p_pid;
3152495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
3247540Skarels 	retval[1] = p->p_pptr->p_pid;
3343393Skarels #endif
3444405Skarels 	return (0);
3543393Skarels }
3643393Skarels 
3743393Skarels /* ARGSUSED */
3843393Skarels getppid(p, uap, retval)
3943393Skarels 	struct proc *p;
4043393Skarels 	void *uap;
4143393Skarels 	int *retval;
427498Sroot {
437498Sroot 
4447540Skarels 	*retval = p->p_pptr->p_pid;
4544405Skarels 	return (0);
467498Sroot }
477498Sroot 
4847540Skarels /* Get process group ID; note that POSIX getpgrp takes no parameter */
4943393Skarels getpgrp(p, uap, retval)
5043393Skarels 	struct proc *p;
5147540Skarels 	void *uap;
5243393Skarels 	int *retval;
537498Sroot {
547498Sroot 
5543393Skarels 	*retval = p->p_pgrp->pg_id;
5644405Skarels 	return (0);
577498Sroot }
587498Sroot 
5943393Skarels /* ARGSUSED */
6043393Skarels getuid(p, uap, retval)
6143393Skarels 	struct proc *p;
6243393Skarels 	void *uap;
6343393Skarels 	int *retval;
647420Sroot {
657420Sroot 
6647540Skarels 	*retval = p->p_cred->p_ruid;
6752495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
6847540Skarels 	retval[1] = p->p_ucred->cr_uid;
6943393Skarels #endif
7044405Skarels 	return (0);
717420Sroot }
727420Sroot 
7343393Skarels /* ARGSUSED */
7443393Skarels geteuid(p, uap, retval)
7543393Skarels 	struct proc *p;
7643393Skarels 	void *uap;
7743393Skarels 	int *retval;
787498Sroot {
797498Sroot 
8047540Skarels 	*retval = p->p_ucred->cr_uid;
8144405Skarels 	return (0);
827498Sroot }
837498Sroot 
8443393Skarels /* ARGSUSED */
8543393Skarels getgid(p, uap, retval)
8643393Skarels 	struct proc *p;
8743393Skarels 	void *uap;
8843393Skarels 	int *retval;
897498Sroot {
9043393Skarels 
9147540Skarels 	*retval = p->p_cred->p_rgid;
9252495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
9347540Skarels 	retval[1] = p->p_ucred->cr_groups[0];
9443393Skarels #endif
9544405Skarels 	return (0);
9643393Skarels }
9743393Skarels 
9843393Skarels /*
9945908Sbostic  * Get effective group ID.  The "egid" is groups[0], and could be obtained
10045908Sbostic  * via getgroups.  This syscall exists because it is somewhat painful to do
10145908Sbostic  * correctly in a library function.
10243393Skarels  */
10343393Skarels /* ARGSUSED */
10443393Skarels getegid(p, uap, retval)
10543393Skarels 	struct proc *p;
10643393Skarels 	void *uap;
10743393Skarels 	int *retval;
10843393Skarels {
10947540Skarels 
11047540Skarels 	*retval = p->p_ucred->cr_groups[0];
11144405Skarels 	return (0);
11243393Skarels }
11343393Skarels 
11443393Skarels getgroups(p, uap, retval)
11543393Skarels 	struct proc *p;
11643393Skarels 	register struct	arg {
1178624Sroot 		u_int	gidsetsize;
11843393Skarels 		int	*gidset;		/* XXX not yet POSIX */
11943393Skarels 	} *uap;
12043393Skarels 	int *retval;
12143393Skarels {
12247540Skarels 	register struct pcred *pc = p->p_cred;
12318362Skarels 	register gid_t *gp;
12418362Skarels 	register int *lp;
12544994Skarels 	register u_int ngrp;
12618362Skarels 	int groups[NGROUPS];
12743393Skarels 	int error;
1287498Sroot 
12944994Skarels 	if ((ngrp = uap->gidsetsize) == 0) {
13047540Skarels 		*retval = pc->pc_ucred->cr_ngroups;
13144405Skarels 		return (0);
13237578Smckusick 	}
13347540Skarels 	if (ngrp < pc->pc_ucred->cr_ngroups)
13444405Skarels 		return (EINVAL);
13547540Skarels 	ngrp = pc->pc_ucred->cr_ngroups;
13647540Skarels 	for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
13718362Skarels 		*lp++ = *gp++;
13843393Skarels 	if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
13944994Skarels 	    ngrp * sizeof (groups[0])))
14044405Skarels 		return (error);
14144994Skarels 	*retval = ngrp;
14244405Skarels 	return (0);
1437498Sroot }
1447498Sroot 
14543393Skarels /* ARGSUSED */
14643393Skarels setsid(p, uap, retval)
14747540Skarels 	register struct proc *p;
14843393Skarels 	void *uap;
14943393Skarels 	int *retval;
15037579Smckusick {
15137579Smckusick 
15243393Skarels 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
15344405Skarels 		return (EPERM);
15443393Skarels 	} else {
15547540Skarels 		enterpgrp(p, p->p_pid, 1);
15643393Skarels 		*retval = p->p_pid;
15744405Skarels 		return (0);
15837579Smckusick 	}
15937579Smckusick }
16037579Smckusick 
16137579Smckusick /*
16247540Skarels  * set process group (setpgid/old setpgrp)
16337579Smckusick  *
16447972Smarc  * caller does setpgid(targpid, targpgid)
16540667Skarels  *
16640667Skarels  * pid must be caller or child of caller (ESRCH)
16740667Skarels  * if a child
16840667Skarels  *	pid must be in same session (EPERM)
16940667Skarels  *	pid can't have done an exec (EACCES)
17040667Skarels  * if pgid != pid
17140667Skarels  * 	there must exist some pid in same session having pgid (EPERM)
17240667Skarels  * pid must not be session leader (EPERM)
17337579Smckusick  */
17443393Skarels /* ARGSUSED */
17547972Smarc setpgid(curp, uap, retval)
17647972Smarc 	struct proc *curp;
17743393Skarels 	register struct args {
17848990Skarels 		int	pid;	/* target process id */
17948990Skarels 		int	pgid;	/* target pgrp id */
18043393Skarels 	} *uap;
18143393Skarels 	int *retval;
18243393Skarels {
18347972Smarc 	register struct proc *targp;		/* target process */
18448990Skarels 	register struct pgrp *pgrp;		/* target pgrp */
1857498Sroot 
18648990Skarels 	if (uap->pid != 0 && uap->pid != curp->p_pid) {
18748990Skarels 		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
18844405Skarels 			return (ESRCH);
18947972Smarc 		if (targp->p_session != curp->p_session)
19044405Skarels 			return (EPERM);
19147972Smarc 		if (targp->p_flag&SEXEC)
19244405Skarels 			return (EACCES);
19343393Skarels 	} else
19447972Smarc 		targp = curp;
19547972Smarc 	if (SESS_LEADER(targp))
19644405Skarels 		return (EPERM);
19748990Skarels 	if (uap->pgid == 0)
19848990Skarels 		uap->pgid = targp->p_pid;
19948990Skarels 	else if (uap->pgid != targp->p_pid)
20048990Skarels 		if ((pgrp = pgfind(uap->pgid)) == 0 ||
20148990Skarels 	            pgrp->pg_session != curp->p_session)
20245908Sbostic 			return (EPERM);
20348990Skarels 	enterpgrp(targp, uap->pgid, 0);
20444405Skarels 	return (0);
2057498Sroot }
2067498Sroot 
20743393Skarels /* ARGSUSED */
20843393Skarels setuid(p, uap, retval)
20947540Skarels 	struct proc *p;
21043393Skarels 	struct args {
21143393Skarels 		int	uid;
21243393Skarels 	} *uap;
21343393Skarels 	int *retval;
2147420Sroot {
21547540Skarels 	register struct pcred *pc = p->p_cred;
21643393Skarels 	register uid_t uid;
21743393Skarels 	int error;
21843393Skarels 
21943393Skarels 	uid = uap->uid;
22047540Skarels 	if (uid != pc->p_ruid &&
22147540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
22244405Skarels 		return (error);
22343393Skarels 	/*
22445908Sbostic 	 * Everything's okay, do it.  Copy credentials so other references do
22545908Sbostic 	 * not see our changes.
22643393Skarels 	 */
22747540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
22847540Skarels 	pc->pc_ucred->cr_uid = uid;
22947540Skarels 	pc->p_ruid = uid;
23047540Skarels 	pc->p_svuid = uid;
231*54339Smckusick 	p->p_flag |= SUGID;
23244405Skarels 	return (0);
23343393Skarels }
23443393Skarels 
23543393Skarels /* ARGSUSED */
23643393Skarels seteuid(p, uap, retval)
23747540Skarels 	struct proc *p;
23843393Skarels 	struct args {
23943393Skarels 		int	euid;
24043393Skarels 	} *uap;
24143393Skarels 	int *retval;
24243393Skarels {
24347540Skarels 	register struct pcred *pc = p->p_cred;
24443393Skarels 	register uid_t euid;
24543393Skarels 	int error;
24643393Skarels 
24743393Skarels 	euid = uap->euid;
24847540Skarels 	if (euid != pc->p_ruid && euid != pc->p_svuid &&
24947540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
25044405Skarels 		return (error);
25143393Skarels 	/*
25245908Sbostic 	 * Everything's okay, do it.  Copy credentials so other references do
25345908Sbostic 	 * not see our changes.
25443393Skarels 	 */
25547540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
25647540Skarels 	pc->pc_ucred->cr_uid = euid;
257*54339Smckusick 	p->p_flag |= SUGID;
25844405Skarels 	return (0);
25943393Skarels }
26043393Skarels 
26143393Skarels /* ARGSUSED */
26243393Skarels setgid(p, uap, retval)
26343393Skarels 	struct proc *p;
26443393Skarels 	struct args {
26543393Skarels 		int	gid;
26643393Skarels 	} *uap;
26743393Skarels 	int *retval;
26843393Skarels {
26947540Skarels 	register struct pcred *pc = p->p_cred;
27043393Skarels 	register gid_t gid;
27143393Skarels 	int error;
27243393Skarels 
27343393Skarels 	gid = uap->gid;
27447540Skarels 	if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
27544405Skarels 		return (error);
27647540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
27747540Skarels 	pc->pc_ucred->cr_groups[0] = gid;
27847540Skarels 	pc->p_rgid = gid;
27947540Skarels 	pc->p_svgid = gid;		/* ??? */
280*54339Smckusick 	p->p_flag |= SUGID;
28144405Skarels 	return (0);
28243393Skarels }
28343393Skarels 
28443393Skarels /* ARGSUSED */
28543393Skarels setegid(p, uap, retval)
28643393Skarels 	struct proc *p;
28743393Skarels 	struct args {
28843393Skarels 		int	egid;
28943393Skarels 	} *uap;
29043393Skarels 	int *retval;
29143393Skarels {
29247540Skarels 	register struct pcred *pc = p->p_cred;
29343393Skarels 	register gid_t egid;
29443393Skarels 	int error;
29543393Skarels 
29643393Skarels 	egid = uap->egid;
29747540Skarels 	if (egid != pc->p_rgid && egid != pc->p_svgid &&
29847540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
29944405Skarels 		return (error);
30047540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
30147540Skarels 	pc->pc_ucred->cr_groups[0] = egid;
302*54339Smckusick 	p->p_flag |= SUGID;
30344405Skarels 	return (0);
30443393Skarels }
30543393Skarels 
30652495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
30743393Skarels /* ARGSUSED */
30843393Skarels osetreuid(p, uap, retval)
30943393Skarels 	register struct proc *p;
31043393Skarels 	struct args {
3119160Ssam 		int	ruid;
3129160Ssam 		int	euid;
3139160Ssam 	} *uap;
31443393Skarels 	int *retval;
31543393Skarels {
31647540Skarels 	register struct pcred *pc = p->p_cred;
31743393Skarels 	register uid_t ruid, euid;
31843393Skarels 	int error;
3199160Ssam 
32043393Skarels 	if (uap->ruid == -1)
32147540Skarels 		ruid = pc->p_ruid;
32243393Skarels 	else
32343393Skarels 		ruid = uap->ruid;
32443393Skarels 	/*
32545908Sbostic 	 * Allow setting real uid to previous effective, for swapping real and
32645908Sbostic 	 * effective.  This should be:
32745908Sbostic 	 *
32847540Skarels 	 * if (ruid != pc->p_ruid &&
32947540Skarels 	 *     (error = suser(pc->pc_ucred, &p->p_acflag)))
33043393Skarels 	 */
33147540Skarels 	if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
33247540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
33344405Skarels 		return (error);
33443393Skarels 	if (uap->euid == -1)
33547540Skarels 		euid = pc->pc_ucred->cr_uid;
33643393Skarels 	else
33743393Skarels 		euid = uap->euid;
33847540Skarels 	if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
33947540Skarels 	    euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
34044405Skarels 		return (error);
3419160Ssam 	/*
34245908Sbostic 	 * Everything's okay, do it.  Copy credentials so other references do
34345908Sbostic 	 * not see our changes.
3449160Ssam 	 */
34547540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
34647540Skarels 	pc->pc_ucred->cr_uid = euid;
34747540Skarels 	pc->p_ruid = ruid;
348*54339Smckusick 	p->p_flag |= SUGID;
34944405Skarels 	return (0);
3509160Ssam }
3519160Ssam 
35243393Skarels /* ARGSUSED */
35343393Skarels osetregid(p, uap, retval)
35447540Skarels 	register struct proc *p;
35543393Skarels 	struct args {
3569160Ssam 		int	rgid;
3579160Ssam 		int	egid;
3589160Ssam 	} *uap;
35943393Skarels 	int *retval;
36043393Skarels {
36147540Skarels 	register struct pcred *pc = p->p_cred;
36243393Skarels 	register gid_t rgid, egid;
36343393Skarels 	int error;
3649160Ssam 
36543393Skarels 	if (uap->rgid == -1)
36647540Skarels 		rgid = pc->p_rgid;
36743393Skarels 	else
36843393Skarels 		rgid = uap->rgid;
36943393Skarels 	/*
37045908Sbostic 	 * Allow setting real gid to previous effective, for swapping real and
37145908Sbostic 	 * effective.  This didn't really work correctly in 4.[23], but is
37245908Sbostic 	 * preserved so old stuff doesn't fail.  This should be:
37345908Sbostic 	 *
37447540Skarels 	 * if (rgid != pc->p_rgid &&
37547540Skarels 	 *     (error = suser(pc->pc_ucred, &p->p_acflag)))
37643393Skarels 	 */
37747540Skarels 	if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
37847540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
37944405Skarels 		return (error);
38043393Skarels 	if (uap->egid == -1)
38147540Skarels 		egid = pc->pc_ucred->cr_groups[0];
38243393Skarels 	else
38343393Skarels 		egid = uap->egid;
38447540Skarels 	if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
38547540Skarels 	    egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
38644405Skarels 		return (error);
38747540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
38847540Skarels 	pc->pc_ucred->cr_groups[0] = egid;
38947540Skarels 	pc->p_rgid = rgid;
390*54339Smckusick 	p->p_flag |= SUGID;
39144405Skarels 	return (0);
3929160Ssam }
39352495Storek #endif /* COMPAT_43 || COMPAT_SUNOS */
3949160Ssam 
39543393Skarels /* ARGSUSED */
39643393Skarels setgroups(p, uap, retval)
39743393Skarels 	struct proc *p;
39843393Skarels 	struct args {
3998624Sroot 		u_int	gidsetsize;
4007498Sroot 		int	*gidset;
40143393Skarels 	} *uap;
40243393Skarels 	int *retval;
40343393Skarels {
40447540Skarels 	register struct pcred *pc = p->p_cred;
40518362Skarels 	register gid_t *gp;
40644994Skarels 	register u_int ngrp;
40718362Skarels 	register int *lp;
40844942Sbostic 	int error, groups[NGROUPS];
4097498Sroot 
41047540Skarels 	if (error = suser(pc->pc_ucred, &p->p_acflag))
41144405Skarels 		return (error);
41244994Skarels 	if ((ngrp = uap->gidsetsize) > NGROUPS)
41344405Skarels 		return (EINVAL);
41444942Sbostic 	if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
41544994Skarels 	    ngrp * sizeof (groups[0])))
41644405Skarels 		return (error);
41747540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
41847540Skarels 	pc->pc_ucred->cr_ngroups = ngrp;
41944942Sbostic 	/* convert from int's to gid_t's */
42047540Skarels 	for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
42144994Skarels 		*gp++ = *lp++;
422*54339Smckusick 	p->p_flag |= SUGID;
42344405Skarels 	return (0);
4247498Sroot }
4257498Sroot 
4267498Sroot /*
42737578Smckusick  * Check if gid is a member of the group set.
42811810Ssam  */
42937578Smckusick groupmember(gid, cred)
43026275Skarels 	gid_t gid;
43137578Smckusick 	register struct ucred *cred;
4327866Sroot {
43318362Skarels 	register gid_t *gp;
43437578Smckusick 	gid_t *egp;
4357866Sroot 
43637578Smckusick 	egp = &(cred->cr_groups[cred->cr_ngroups]);
43737578Smckusick 	for (gp = cred->cr_groups; gp < egp; gp++)
4387866Sroot 		if (*gp == gid)
43937578Smckusick 			return (1);
44037578Smckusick 	return (0);
4417866Sroot }
4427866Sroot 
44311810Ssam /*
44446293Skarels  * Test whether the specified credentials imply "super-user"
44546293Skarels  * privilege; if so, and we have accounting info, set the flag
44646293Skarels  * indicating use of super-powers.
44746293Skarels  * Returns 0 or error.
44811810Ssam  */
44937578Smckusick suser(cred, acflag)
45037578Smckusick 	struct ucred *cred;
45137578Smckusick 	short *acflag;
4527866Sroot {
45337578Smckusick 	if (cred->cr_uid == 0) {
45437578Smckusick 		if (acflag)
45537578Smckusick 			*acflag |= ASU;
45637578Smckusick 		return (0);
45718362Skarels 	}
45837578Smckusick 	return (EPERM);
4597866Sroot }
46011810Ssam 
46111810Ssam /*
46237578Smckusick  * Allocate a zeroed cred structure.
46311810Ssam  */
46437578Smckusick struct ucred *
46537578Smckusick crget()
46611810Ssam {
46737578Smckusick 	register struct ucred *cr;
46811810Ssam 
46937578Smckusick 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
47037578Smckusick 	bzero((caddr_t)cr, sizeof(*cr));
47137578Smckusick 	cr->cr_ref = 1;
47243393Skarels 	return (cr);
47311810Ssam }
47437085Skfall 
47537085Skfall /*
47637578Smckusick  * Free a cred structure.
47737578Smckusick  * Throws away space when ref count gets to 0.
47837085Skfall  */
47937578Smckusick crfree(cr)
48037578Smckusick 	struct ucred *cr;
48137578Smckusick {
48247540Skarels 	int s = splimp();			/* ??? */
48337085Skfall 
48437578Smckusick 	if (--cr->cr_ref != 0) {
48537578Smckusick 		(void) splx(s);
48637578Smckusick 		return;
48737578Smckusick 	}
48837578Smckusick 	FREE((caddr_t)cr, M_CRED);
48937578Smckusick 	(void) splx(s);
49037578Smckusick }
49137578Smckusick 
49237578Smckusick /*
49337578Smckusick  * Copy cred structure to a new one and free the old one.
49437578Smckusick  */
49537578Smckusick struct ucred *
49637578Smckusick crcopy(cr)
49737578Smckusick 	struct ucred *cr;
49837085Skfall {
49937578Smckusick 	struct ucred *newcr;
50037085Skfall 
50145908Sbostic 	if (cr->cr_ref == 1)
50245908Sbostic 		return (cr);
50337578Smckusick 	newcr = crget();
50437578Smckusick 	*newcr = *cr;
50537578Smckusick 	crfree(cr);
50637578Smckusick 	newcr->cr_ref = 1;
50743393Skarels 	return (newcr);
50837085Skfall }
50937085Skfall 
51037085Skfall /*
51137578Smckusick  * Dup cred struct to a new held one.
51237085Skfall  */
51337578Smckusick struct ucred *
51437578Smckusick crdup(cr)
51537578Smckusick 	struct ucred *cr;
51637085Skfall {
51737578Smckusick 	struct ucred *newcr;
51837085Skfall 
51937578Smckusick 	newcr = crget();
52037578Smckusick 	*newcr = *cr;
52137578Smckusick 	newcr->cr_ref = 1;
52243393Skarels 	return (newcr);
52337085Skfall }
52437579Smckusick 
52537579Smckusick /*
52640667Skarels  * Get login name, if available.
52737579Smckusick  */
52843393Skarels /* ARGSUSED */
52943393Skarels getlogin(p, uap, retval)
53043393Skarels 	struct proc *p;
53143393Skarels 	struct args {
53237579Smckusick 		char	*namebuf;
53337579Smckusick 		u_int	namelen;
53443393Skarels 	} *uap;
53543393Skarels 	int *retval;
53643393Skarels {
53737579Smckusick 
53847540Skarels 	if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
53947540Skarels 		uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
54047540Skarels 	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
54147540Skarels 	    (caddr_t) uap->namebuf, uap->namelen));
54237579Smckusick }
54337579Smckusick 
54437579Smckusick /*
54540667Skarels  * Set login name.
54637579Smckusick  */
54743393Skarels /* ARGSUSED */
54843393Skarels setlogin(p, uap, retval)
54943393Skarels 	struct proc *p;
55043393Skarels 	struct args {
55143393Skarels 		char	*namebuf;
55243393Skarels 	} *uap;
55343393Skarels 	int *retval;
55437579Smckusick {
55540667Skarels 	int error;
55637579Smckusick 
55747540Skarels 	if (error = suser(p->p_ucred, &p->p_acflag))
55844405Skarels 		return (error);
55947540Skarels 	error = copyinstr((caddr_t) uap->namebuf,
56047540Skarels 	    (caddr_t) p->p_pgrp->pg_session->s_login,
56147540Skarels 	    sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
56247540Skarels 	if (error == ENAMETOOLONG)
56340667Skarels 		error = EINVAL;
56444405Skarels 	return (error);
56537579Smckusick }
566