xref: /csrg-svn/sys/kern/kern_prot.c (revision 68171)
123372Smckusick /*
263182Sbostic  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
365799Sbostic  *	The Regents of the University of California.  All rights reserved.
465771Sbostic  * (c) UNIX System Laboratories, Inc.
565771Sbostic  * All or some portions of this file are derived from material licensed
665771Sbostic  * to the University of California by American Telephone and Telegraph
765771Sbostic  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
865771Sbostic  * the permission of UNIX System Laboratories, Inc.
923372Smckusick  *
1044439Sbostic  * %sccs.include.redist.c%
1137578Smckusick  *
12*68171Scgd  *	@(#)kern_prot.c	8.8 (Berkeley) 01/09/95
1323372Smckusick  */
147420Sroot 
157420Sroot /*
167498Sroot  * System calls related to processes and protection
177420Sroot  */
187420Sroot 
1957048Smckusick #include <sys/param.h>
2057048Smckusick #include <sys/acct.h>
2157048Smckusick #include <sys/systm.h>
2257048Smckusick #include <sys/ucred.h>
2357048Smckusick #include <sys/proc.h>
2457048Smckusick #include <sys/timeb.h>
2557048Smckusick #include <sys/times.h>
2657048Smckusick #include <sys/malloc.h>
277420Sroot 
2854925Storek struct args {
2954925Storek 	int	dummy;
3054925Storek };
3154925Storek 
3243393Skarels /* ARGSUSED */
3343393Skarels getpid(p, uap, retval)
3443393Skarels 	struct proc *p;
3554925Storek 	struct args *uap;
3643393Skarels 	int *retval;
3743393Skarels {
3837579Smckusick 
3943393Skarels 	*retval = p->p_pid;
4052495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
4147540Skarels 	retval[1] = p->p_pptr->p_pid;
4243393Skarels #endif
4344405Skarels 	return (0);
4443393Skarels }
4543393Skarels 
4643393Skarels /* ARGSUSED */
4743393Skarels getppid(p, uap, retval)
4843393Skarels 	struct proc *p;
4954925Storek 	struct args *uap;
5043393Skarels 	int *retval;
517498Sroot {
527498Sroot 
5347540Skarels 	*retval = p->p_pptr->p_pid;
5444405Skarels 	return (0);
557498Sroot }
567498Sroot 
5747540Skarels /* Get process group ID; note that POSIX getpgrp takes no parameter */
5843393Skarels getpgrp(p, uap, retval)
5943393Skarels 	struct proc *p;
6054925Storek 	struct args *uap;
6143393Skarels 	int *retval;
627498Sroot {
637498Sroot 
6443393Skarels 	*retval = p->p_pgrp->pg_id;
6544405Skarels 	return (0);
667498Sroot }
677498Sroot 
6843393Skarels /* ARGSUSED */
6943393Skarels getuid(p, uap, retval)
7043393Skarels 	struct proc *p;
7154925Storek 	struct args *uap;
7243393Skarels 	int *retval;
737420Sroot {
747420Sroot 
7547540Skarels 	*retval = p->p_cred->p_ruid;
7652495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
7747540Skarels 	retval[1] = p->p_ucred->cr_uid;
7843393Skarels #endif
7944405Skarels 	return (0);
807420Sroot }
817420Sroot 
8243393Skarels /* ARGSUSED */
8343393Skarels geteuid(p, uap, retval)
8443393Skarels 	struct proc *p;
8554925Storek 	struct args *uap;
8643393Skarels 	int *retval;
877498Sroot {
887498Sroot 
8947540Skarels 	*retval = p->p_ucred->cr_uid;
9044405Skarels 	return (0);
917498Sroot }
927498Sroot 
9343393Skarels /* ARGSUSED */
9443393Skarels getgid(p, uap, retval)
9543393Skarels 	struct proc *p;
9654925Storek 	struct args *uap;
9743393Skarels 	int *retval;
987498Sroot {
9943393Skarels 
10047540Skarels 	*retval = p->p_cred->p_rgid;
10152495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
10247540Skarels 	retval[1] = p->p_ucred->cr_groups[0];
10343393Skarels #endif
10444405Skarels 	return (0);
10543393Skarels }
10643393Skarels 
10743393Skarels /*
10845908Sbostic  * Get effective group ID.  The "egid" is groups[0], and could be obtained
10945908Sbostic  * via getgroups.  This syscall exists because it is somewhat painful to do
11045908Sbostic  * correctly in a library function.
11143393Skarels  */
11243393Skarels /* ARGSUSED */
11343393Skarels getegid(p, uap, retval)
11443393Skarels 	struct proc *p;
11554925Storek 	struct args *uap;
11643393Skarels 	int *retval;
11743393Skarels {
11847540Skarels 
11947540Skarels 	*retval = p->p_ucred->cr_groups[0];
12044405Skarels 	return (0);
12143393Skarels }
12243393Skarels 
12354925Storek struct getgroups_args {
12454925Storek 	u_int	gidsetsize;
12555162Smckusick 	gid_t	*gidset;
12654925Storek };
12743393Skarels getgroups(p, uap, retval)
12843393Skarels 	struct proc *p;
12954925Storek 	register struct	getgroups_args *uap;
13043393Skarels 	int *retval;
13143393Skarels {
13247540Skarels 	register struct pcred *pc = p->p_cred;
13344994Skarels 	register u_int ngrp;
13443393Skarels 	int error;
1357498Sroot 
13644994Skarels 	if ((ngrp = uap->gidsetsize) == 0) {
13747540Skarels 		*retval = pc->pc_ucred->cr_ngroups;
13844405Skarels 		return (0);
13937578Smckusick 	}
14047540Skarels 	if (ngrp < pc->pc_ucred->cr_ngroups)
14144405Skarels 		return (EINVAL);
14247540Skarels 	ngrp = pc->pc_ucred->cr_ngroups;
14355162Smckusick 	if (error = copyout((caddr_t)pc->pc_ucred->cr_groups,
14455162Smckusick 	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))
14544405Skarels 		return (error);
14644994Skarels 	*retval = ngrp;
14744405Skarels 	return (0);
1487498Sroot }
1497498Sroot 
15043393Skarels /* ARGSUSED */
15143393Skarels setsid(p, uap, retval)
15247540Skarels 	register struct proc *p;
15354925Storek 	struct args *uap;
15443393Skarels 	int *retval;
15537579Smckusick {
15637579Smckusick 
15743393Skarels 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
15844405Skarels 		return (EPERM);
15943393Skarels 	} else {
16057049Smarc 		(void)enterpgrp(p, p->p_pid, 1);
16143393Skarels 		*retval = p->p_pid;
16244405Skarels 		return (0);
16337579Smckusick 	}
16437579Smckusick }
16537579Smckusick 
16637579Smckusick /*
16747540Skarels  * set process group (setpgid/old setpgrp)
16837579Smckusick  *
16947972Smarc  * caller does setpgid(targpid, targpgid)
17040667Skarels  *
17140667Skarels  * pid must be caller or child of caller (ESRCH)
17240667Skarels  * if a child
17340667Skarels  *	pid must be in same session (EPERM)
17440667Skarels  *	pid can't have done an exec (EACCES)
17540667Skarels  * if pgid != pid
17640667Skarels  * 	there must exist some pid in same session having pgid (EPERM)
17740667Skarels  * pid must not be session leader (EPERM)
17837579Smckusick  */
17954925Storek struct setpgid_args {
18054925Storek 	int	pid;	/* target process id */
18154925Storek 	int	pgid;	/* target pgrp id */
18254925Storek };
18343393Skarels /* ARGSUSED */
18447972Smarc setpgid(curp, uap, retval)
18547972Smarc 	struct proc *curp;
18654925Storek 	register struct setpgid_args *uap;
18743393Skarels 	int *retval;
18843393Skarels {
18947972Smarc 	register struct proc *targp;		/* target process */
19048990Skarels 	register struct pgrp *pgrp;		/* target pgrp */
1917498Sroot 
19248990Skarels 	if (uap->pid != 0 && uap->pid != curp->p_pid) {
19348990Skarels 		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
19444405Skarels 			return (ESRCH);
19547972Smarc 		if (targp->p_session != curp->p_session)
19644405Skarels 			return (EPERM);
19764586Sbostic 		if (targp->p_flag & P_EXEC)
19844405Skarels 			return (EACCES);
19943393Skarels 	} else
20047972Smarc 		targp = curp;
20147972Smarc 	if (SESS_LEADER(targp))
20244405Skarels 		return (EPERM);
20348990Skarels 	if (uap->pgid == 0)
20448990Skarels 		uap->pgid = targp->p_pid;
20548990Skarels 	else if (uap->pgid != targp->p_pid)
20648990Skarels 		if ((pgrp = pgfind(uap->pgid)) == 0 ||
20748990Skarels 	            pgrp->pg_session != curp->p_session)
20845908Sbostic 			return (EPERM);
20957049Smarc 	return (enterpgrp(targp, uap->pgid, 0));
2107498Sroot }
2117498Sroot 
21254925Storek struct setuid_args {
21355162Smckusick 	uid_t	uid;
21454925Storek };
21543393Skarels /* ARGSUSED */
21643393Skarels setuid(p, uap, retval)
21747540Skarels 	struct proc *p;
21854925Storek 	struct setuid_args *uap;
21943393Skarels 	int *retval;
2207420Sroot {
22147540Skarels 	register struct pcred *pc = p->p_cred;
22243393Skarels 	register uid_t uid;
22343393Skarels 	int error;
22443393Skarels 
22543393Skarels 	uid = uap->uid;
22647540Skarels 	if (uid != pc->p_ruid &&
22747540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
22844405Skarels 		return (error);
22943393Skarels 	/*
23055403Smckusick 	 * Everything's okay, do it.
23155403Smckusick 	 * Transfer proc count to new user.
23255403Smckusick 	 * Copy credentials so other references do not see our changes.
23343393Skarels 	 */
23455403Smckusick 	(void)chgproccnt(pc->p_ruid, -1);
23555403Smckusick 	(void)chgproccnt(uid, 1);
23647540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
23747540Skarels 	pc->pc_ucred->cr_uid = uid;
23847540Skarels 	pc->p_ruid = uid;
23947540Skarels 	pc->p_svuid = uid;
24064586Sbostic 	p->p_flag |= P_SUGID;
24144405Skarels 	return (0);
24243393Skarels }
24343393Skarels 
24454925Storek struct seteuid_args {
24555162Smckusick 	uid_t	euid;
24654925Storek };
24743393Skarels /* ARGSUSED */
24843393Skarels seteuid(p, uap, retval)
24947540Skarels 	struct proc *p;
25054925Storek 	struct seteuid_args *uap;
25143393Skarels 	int *retval;
25243393Skarels {
25347540Skarels 	register struct pcred *pc = p->p_cred;
25443393Skarels 	register uid_t euid;
25543393Skarels 	int error;
25643393Skarels 
25743393Skarels 	euid = uap->euid;
25847540Skarels 	if (euid != pc->p_ruid && euid != pc->p_svuid &&
25947540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
26044405Skarels 		return (error);
26143393Skarels 	/*
26245908Sbostic 	 * Everything's okay, do it.  Copy credentials so other references do
26345908Sbostic 	 * not see our changes.
26443393Skarels 	 */
26547540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
26647540Skarels 	pc->pc_ucred->cr_uid = euid;
26764586Sbostic 	p->p_flag |= P_SUGID;
26844405Skarels 	return (0);
26943393Skarels }
27043393Skarels 
27154925Storek struct setgid_args {
27255162Smckusick 	gid_t	gid;
27354925Storek };
27443393Skarels /* ARGSUSED */
27543393Skarels setgid(p, uap, retval)
27643393Skarels 	struct proc *p;
27754925Storek 	struct setgid_args *uap;
27843393Skarels 	int *retval;
27943393Skarels {
28047540Skarels 	register struct pcred *pc = p->p_cred;
28143393Skarels 	register gid_t gid;
28243393Skarels 	int error;
28343393Skarels 
28443393Skarels 	gid = uap->gid;
28547540Skarels 	if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
28644405Skarels 		return (error);
28747540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
28847540Skarels 	pc->pc_ucred->cr_groups[0] = gid;
28947540Skarels 	pc->p_rgid = gid;
29047540Skarels 	pc->p_svgid = gid;		/* ??? */
29164586Sbostic 	p->p_flag |= P_SUGID;
29244405Skarels 	return (0);
29343393Skarels }
29443393Skarels 
29554925Storek struct setegid_args {
29655162Smckusick 	gid_t	egid;
29754925Storek };
29843393Skarels /* ARGSUSED */
29943393Skarels setegid(p, uap, retval)
30043393Skarels 	struct proc *p;
30154925Storek 	struct setegid_args *uap;
30243393Skarels 	int *retval;
30343393Skarels {
30447540Skarels 	register struct pcred *pc = p->p_cred;
30543393Skarels 	register gid_t egid;
30643393Skarels 	int error;
30743393Skarels 
30843393Skarels 	egid = uap->egid;
30947540Skarels 	if (egid != pc->p_rgid && egid != pc->p_svgid &&
31047540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
31144405Skarels 		return (error);
31247540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
31347540Skarels 	pc->pc_ucred->cr_groups[0] = egid;
31464586Sbostic 	p->p_flag |= P_SUGID;
31544405Skarels 	return (0);
31643393Skarels }
31743393Skarels 
31854925Storek struct setgroups_args {
31954925Storek 	u_int	gidsetsize;
32055162Smckusick 	gid_t	*gidset;
32154925Storek };
32243393Skarels /* ARGSUSED */
32343393Skarels setgroups(p, uap, retval)
32443393Skarels 	struct proc *p;
32554925Storek 	struct setgroups_args *uap;
32643393Skarels 	int *retval;
32743393Skarels {
32847540Skarels 	register struct pcred *pc = p->p_cred;
32944994Skarels 	register u_int ngrp;
33055162Smckusick 	int error;
3317498Sroot 
33247540Skarels 	if (error = suser(pc->pc_ucred, &p->p_acflag))
33344405Skarels 		return (error);
33444994Skarels 	if ((ngrp = uap->gidsetsize) > NGROUPS)
33544405Skarels 		return (EINVAL);
33655162Smckusick 	pc->pc_ucred = crcopy(pc->pc_ucred);
33755162Smckusick 	if (error = copyin((caddr_t)uap->gidset,
33855162Smckusick 	    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))
33944405Skarels 		return (error);
34047540Skarels 	pc->pc_ucred->cr_ngroups = ngrp;
34164586Sbostic 	p->p_flag |= P_SUGID;
34244405Skarels 	return (0);
3437498Sroot }
3447498Sroot 
34555163Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
34655163Smckusick struct setreuid_args {
34755163Smckusick 	int	ruid;
34855163Smckusick 	int	euid;
34955163Smckusick };
35055163Smckusick /* ARGSUSED */
35155163Smckusick osetreuid(p, uap, retval)
35255163Smckusick 	register struct proc *p;
35355163Smckusick 	struct setreuid_args *uap;
35455163Smckusick 	int *retval;
35555163Smckusick {
35655163Smckusick 	register struct pcred *pc = p->p_cred;
35767875Shibler 	union {
35867875Shibler 		struct setuid_args sa;
35967875Shibler 		struct seteuid_args ea;
36067875Shibler 	} args;
36155163Smckusick 
36255163Smckusick 	/*
36367875Shibler 	 * If ruid == euid then setreuid is being used to emulate setuid,
36467875Shibler 	 * just do it.
36555163Smckusick 	 */
36667875Shibler 	if (uap->ruid != -1 && uap->ruid == uap->euid) {
36767875Shibler 		args.sa.uid = uap->ruid;
36867875Shibler 		return (setuid(p, &args.sa, retval));
36967875Shibler 	}
37067875Shibler 	/*
37167875Shibler 	 * Otherwise we assume that the intent of setting ruid is to be
37267875Shibler 	 * able to get back ruid priviledge (i.e. swapping ruid and euid).
37367875Shibler 	 * So we make sure that we will be able to do so, but do not
37467875Shibler 	 * actually set the ruid.
37567875Shibler 	 */
37665512Smckusick 	if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid &&
37755163Smckusick 	    uap->ruid != pc->p_svuid)
37855163Smckusick 		return (EPERM);
37965512Smckusick 	if (uap->euid == (uid_t)-1)
38055163Smckusick 		return (0);
38167875Shibler 	args.ea.euid = uap->euid;
38267875Shibler 	return (seteuid(p, &args.ea, retval));
38355163Smckusick }
38455163Smckusick 
38555163Smckusick struct setregid_args {
38655163Smckusick 	int	rgid;
38755163Smckusick 	int	egid;
38855163Smckusick };
38955163Smckusick /* ARGSUSED */
39055163Smckusick osetregid(p, uap, retval)
39155163Smckusick 	register struct proc *p;
39255163Smckusick 	struct setregid_args *uap;
39355163Smckusick 	int *retval;
39455163Smckusick {
39555163Smckusick 	register struct pcred *pc = p->p_cred;
39667875Shibler 	union {
39767875Shibler 		struct setgid_args sa;
39867875Shibler 		struct setegid_args ea;
39967875Shibler 	} args;
40055163Smckusick 
40155163Smckusick 	/*
40267875Shibler 	 * If rgid == egid then setreuid is being used to emulate setgid,
40367875Shibler 	 * just do it.
40455163Smckusick 	 */
40567875Shibler 	if (uap->rgid != -1 && uap->rgid == uap->egid) {
40667875Shibler 		args.sa.gid = uap->rgid;
40767875Shibler 		return (setgid(p, &args.sa, retval));
40867875Shibler 	}
40967875Shibler 	/*
41067875Shibler 	 * Otherwise we assume that the intent of setting rgid is to be
41167875Shibler 	 * able to get back rgid priviledge (i.e. swapping rgid and egid).
41267875Shibler 	 * So we make sure that we will be able to do so, but do not
41367875Shibler 	 * actually set the rgid.
41467875Shibler 	 */
41565512Smckusick 	if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid &&
41655163Smckusick 	    uap->rgid != pc->p_svgid)
41755163Smckusick 		return (EPERM);
41865512Smckusick 	if (uap->egid == (gid_t)-1)
41955163Smckusick 		return (0);
42067875Shibler 	args.ea.egid = uap->egid;
42167875Shibler 	return (setegid(p, &args.ea, retval));
42255163Smckusick }
42355163Smckusick #endif /* defined(COMPAT_43) || defined(COMPAT_SUNOS) */
42455163Smckusick 
4257498Sroot /*
42637578Smckusick  * Check if gid is a member of the group set.
42711810Ssam  */
42837578Smckusick groupmember(gid, cred)
42926275Skarels 	gid_t gid;
43037578Smckusick 	register struct ucred *cred;
4317866Sroot {
43218362Skarels 	register gid_t *gp;
43337578Smckusick 	gid_t *egp;
4347866Sroot 
43537578Smckusick 	egp = &(cred->cr_groups[cred->cr_ngroups]);
43637578Smckusick 	for (gp = cred->cr_groups; gp < egp; gp++)
4377866Sroot 		if (*gp == gid)
43837578Smckusick 			return (1);
43937578Smckusick 	return (0);
4407866Sroot }
4417866Sroot 
44211810Ssam /*
44346293Skarels  * Test whether the specified credentials imply "super-user"
44446293Skarels  * privilege; if so, and we have accounting info, set the flag
44546293Skarels  * indicating use of super-powers.
44646293Skarels  * Returns 0 or error.
44711810Ssam  */
44837578Smckusick suser(cred, acflag)
44937578Smckusick 	struct ucred *cred;
450*68171Scgd 	u_short *acflag;
4517866Sroot {
45237578Smckusick 	if (cred->cr_uid == 0) {
45337578Smckusick 		if (acflag)
45437578Smckusick 			*acflag |= ASU;
45537578Smckusick 		return (0);
45618362Skarels 	}
45737578Smckusick 	return (EPERM);
4587866Sroot }
45911810Ssam 
46011810Ssam /*
46137578Smckusick  * Allocate a zeroed cred structure.
46211810Ssam  */
46337578Smckusick struct ucred *
46437578Smckusick crget()
46511810Ssam {
46637578Smckusick 	register struct ucred *cr;
46711810Ssam 
46837578Smckusick 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
46937578Smckusick 	bzero((caddr_t)cr, sizeof(*cr));
47037578Smckusick 	cr->cr_ref = 1;
47143393Skarels 	return (cr);
47211810Ssam }
47337085Skfall 
47437085Skfall /*
47537578Smckusick  * Free a cred structure.
47637578Smckusick  * Throws away space when ref count gets to 0.
47737085Skfall  */
478*68171Scgd void
47937578Smckusick crfree(cr)
48037578Smckusick 	struct ucred *cr;
48137578Smckusick {
48265537Sbostic 	int s;
48337085Skfall 
48465537Sbostic 	s = splimp();				/* ??? */
48565537Sbostic 	if (--cr->cr_ref == 0)
48665537Sbostic 		FREE((caddr_t)cr, M_CRED);
48737578Smckusick 	(void) splx(s);
48837578Smckusick }
48937578Smckusick 
49037578Smckusick /*
49137578Smckusick  * Copy cred structure to a new one and free the old one.
49237578Smckusick  */
49337578Smckusick struct ucred *
49437578Smckusick crcopy(cr)
49537578Smckusick 	struct ucred *cr;
49637085Skfall {
49737578Smckusick 	struct ucred *newcr;
49837085Skfall 
49945908Sbostic 	if (cr->cr_ref == 1)
50045908Sbostic 		return (cr);
50137578Smckusick 	newcr = crget();
50237578Smckusick 	*newcr = *cr;
50337578Smckusick 	crfree(cr);
50437578Smckusick 	newcr->cr_ref = 1;
50543393Skarels 	return (newcr);
50637085Skfall }
50737085Skfall 
50837085Skfall /*
50937578Smckusick  * Dup cred struct to a new held one.
51037085Skfall  */
51137578Smckusick struct ucred *
51237578Smckusick crdup(cr)
51337578Smckusick 	struct ucred *cr;
51437085Skfall {
51537578Smckusick 	struct ucred *newcr;
51637085Skfall 
51737578Smckusick 	newcr = crget();
51837578Smckusick 	*newcr = *cr;
51937578Smckusick 	newcr->cr_ref = 1;
52043393Skarels 	return (newcr);
52137085Skfall }
52237579Smckusick 
52337579Smckusick /*
52440667Skarels  * Get login name, if available.
52537579Smckusick  */
52654925Storek struct getlogin_args {
52754925Storek 	char	*namebuf;
52854925Storek 	u_int	namelen;
52954925Storek };
53043393Skarels /* ARGSUSED */
53143393Skarels getlogin(p, uap, retval)
53243393Skarels 	struct proc *p;
53354925Storek 	struct getlogin_args *uap;
53443393Skarels 	int *retval;
53543393Skarels {
53637579Smckusick 
53747540Skarels 	if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
53847540Skarels 		uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
53947540Skarels 	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
54047540Skarels 	    (caddr_t) uap->namebuf, uap->namelen));
54137579Smckusick }
54237579Smckusick 
54337579Smckusick /*
54440667Skarels  * Set login name.
54537579Smckusick  */
54654925Storek struct setlogin_args {
54754925Storek 	char	*namebuf;
54854925Storek };
54943393Skarels /* ARGSUSED */
55043393Skarels setlogin(p, uap, retval)
55143393Skarels 	struct proc *p;
55254925Storek 	struct setlogin_args *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