xref: /csrg-svn/sys/kern/kern_prot.c (revision 43393)
123372Smckusick /*
2*43393Skarels  * Copyright (c) 1982, 1986, 1989, 1990 Regents of the University of California.
337578Smckusick  * All rights reserved.
423372Smckusick  *
537578Smckusick  * Redistribution and use in source and binary forms are permitted
637578Smckusick  * provided that the above copyright notice and this paragraph are
737578Smckusick  * duplicated in all such forms and that any documentation,
837578Smckusick  * advertising materials, and other materials related to such
937578Smckusick  * distribution and use acknowledge that the software was developed
1037578Smckusick  * by the University of California, Berkeley.  The name of the
1137578Smckusick  * University may not be used to endorse or promote products derived
1237578Smckusick  * from this software without specific prior written permission.
1337578Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437578Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537578Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637578Smckusick  *
17*43393Skarels  *	@(#)kern_prot.c	7.11 (Berkeley) 06/21/90
1823372Smckusick  */
197420Sroot 
207420Sroot /*
217498Sroot  * System calls related to processes and protection
227420Sroot  */
237420Sroot 
2417092Sbloom #include "param.h"
2537578Smckusick #include "acct.h"
2617092Sbloom #include "systm.h"
27*43393Skarels #include "syscontext.h"
2817092Sbloom #include "proc.h"
2917092Sbloom #include "timeb.h"
3017092Sbloom #include "times.h"
3137578Smckusick #include "malloc.h"
327420Sroot 
33*43393Skarels /* ARGSUSED */
34*43393Skarels getpid(p, uap, retval)
35*43393Skarels 	struct proc *p;
36*43393Skarels 	void *uap;
37*43393Skarels 	int *retval;
38*43393Skarels {
3937579Smckusick 
40*43393Skarels 	*retval = p->p_pid;
41*43393Skarels #ifdef COMPAT_43
42*43393Skarels 	retval[1] = p->p_ppid;
43*43393Skarels #endif
44*43393Skarels 	RETURN (0);
45*43393Skarels }
46*43393Skarels 
47*43393Skarels /* ARGSUSED */
48*43393Skarels getppid(p, uap, retval)
49*43393Skarels 	struct proc *p;
50*43393Skarels 	void *uap;
51*43393Skarels 	int *retval;
527498Sroot {
537498Sroot 
54*43393Skarels 	*retval = p->p_ppid;
55*43393Skarels 	RETURN (0);
567498Sroot }
577498Sroot 
58*43393Skarels getpgrp(p, uap, retval)
59*43393Skarels 	struct proc *p;
60*43393Skarels 	struct args {
61*43393Skarels 		int	pid;
62*43393Skarels 	} *uap;
63*43393Skarels 	int *retval;
647498Sroot {
657498Sroot 
66*43393Skarels 	if (uap->pid != 0 && (p = pfind(uap->pid)) == 0)
67*43393Skarels 		RETURN (ESRCH);
68*43393Skarels 	*retval = p->p_pgrp->pg_id;
69*43393Skarels 	RETURN (0);
707498Sroot }
717498Sroot 
72*43393Skarels /* ARGSUSED */
73*43393Skarels getuid(p, uap, retval)
74*43393Skarels 	struct proc *p;
75*43393Skarels 	void *uap;
76*43393Skarels 	int *retval;
777420Sroot {
787420Sroot 
79*43393Skarels 	*retval = p->p_ruid;
80*43393Skarels #ifdef COMPAT_43
81*43393Skarels 	retval[1] = u.u_cred->cr_uid;
82*43393Skarels #endif
83*43393Skarels 	RETURN (0);
847420Sroot }
857420Sroot 
86*43393Skarels /* ARGSUSED */
87*43393Skarels geteuid(p, uap, retval)
88*43393Skarels 	struct proc *p;
89*43393Skarels 	void *uap;
90*43393Skarels 	int *retval;
917498Sroot {
927498Sroot 
93*43393Skarels 	*retval = u.u_cred->cr_uid;
94*43393Skarels 	RETURN (0);
957498Sroot }
967498Sroot 
97*43393Skarels /* ARGSUSED */
98*43393Skarels getgid(p, uap, retval)
99*43393Skarels 	struct proc *p;
100*43393Skarels 	void *uap;
101*43393Skarels 	int *retval;
1027498Sroot {
103*43393Skarels 
104*43393Skarels 	*retval = p->p_rgid;
105*43393Skarels #ifdef COMPAT_43
106*43393Skarels 	retval[1] = u.u_cred->cr_groups[0];
107*43393Skarels #endif
108*43393Skarels 	RETURN (0);
109*43393Skarels }
110*43393Skarels 
111*43393Skarels /*
112*43393Skarels  * Get effective group ID.
113*43393Skarels  * The "egid" is groups[0], and thus could be obtained via getgroups;
114*43393Skarels  * this is somewhat painful to do correctly in a library function,
115*43393Skarels  * this the existence of this syscall.
116*43393Skarels  */
117*43393Skarels /* ARGSUSED */
118*43393Skarels getegid(p, uap, retval)
119*43393Skarels 	struct proc *p;
120*43393Skarels 	void *uap;
121*43393Skarels 	int *retval;
122*43393Skarels {
123*43393Skarels 
124*43393Skarels 	*retval = u.u_cred->cr_groups[0];
125*43393Skarels 	RETURN (0);
126*43393Skarels }
127*43393Skarels 
128*43393Skarels getgroups(p, uap, retval)
129*43393Skarels 	struct proc *p;
130*43393Skarels 	register struct	arg {
1318624Sroot 		u_int	gidsetsize;
132*43393Skarels 		int	*gidset;		/* XXX not yet POSIX */
133*43393Skarels 	} *uap;
134*43393Skarels 	int *retval;
135*43393Skarels {
13618362Skarels 	register gid_t *gp;
13718362Skarels 	register int *lp;
13818362Skarels 	int groups[NGROUPS];
139*43393Skarels 	int error;
1407498Sroot 
14137578Smckusick 	if (uap->gidsetsize == 0) {
142*43393Skarels 		*retval = u.u_cred->cr_ngroups;
143*43393Skarels 		RETURN (0);
14437578Smckusick 	}
145*43393Skarels 	if (uap->gidsetsize < u.u_cred->cr_ngroups)
146*43393Skarels 		RETURN (EINVAL);
14740667Skarels 	uap->gidsetsize = u.u_cred->cr_ngroups;
14840667Skarels 	gp = u.u_cred->cr_groups;
14937578Smckusick 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
15018362Skarels 		*lp++ = *gp++;
151*43393Skarels 	if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
152*43393Skarels 	    uap->gidsetsize * sizeof (groups[0])))
153*43393Skarels 		RETURN (error);
154*43393Skarels 	*retval = uap->gidsetsize;
155*43393Skarels 	RETURN (0);
1567498Sroot }
1577498Sroot 
158*43393Skarels /* ARGSUSED */
159*43393Skarels setsid(p, uap, retval)
160*43393Skarels 	struct proc *p;
161*43393Skarels 	void *uap;
162*43393Skarels 	int *retval;
16337579Smckusick {
16437579Smckusick 
165*43393Skarels 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
166*43393Skarels 		RETURN (EPERM);
167*43393Skarels 	} else {
16837579Smckusick 		pgmv(p, p->p_pid, 1);
169*43393Skarels 		*retval = p->p_pid;
170*43393Skarels 		RETURN (0);
17137579Smckusick 	}
17237579Smckusick }
17337579Smckusick 
17437579Smckusick /*
175*43393Skarels  * set process group (setpgrp/setpgid)
17637579Smckusick  *
17740667Skarels  * caller does setpgrp(pid, pgid)
17840667Skarels  *
17940667Skarels  * pid must be caller or child of caller (ESRCH)
18040667Skarels  * if a child
18140667Skarels  *	pid must be in same session (EPERM)
18240667Skarels  *	pid can't have done an exec (EACCES)
18340667Skarels  * if pgid != pid
18440667Skarels  * 	there must exist some pid in same session having pgid (EPERM)
18540667Skarels  * pid must not be session leader (EPERM)
18637579Smckusick  */
187*43393Skarels /* ARGSUSED */
188*43393Skarels setpgrp(cp, uap, retval)
189*43393Skarels 	struct proc *cp;
190*43393Skarels 	register struct args {
1917498Sroot 		int	pid;
19237579Smckusick 		int	pgid;
193*43393Skarels 	} *uap;
194*43393Skarels 	int *retval;
195*43393Skarels {
19637579Smckusick 	register struct proc *p;
19737579Smckusick 	register struct pgrp *pgrp;
1987498Sroot 
199*43393Skarels 	if (uap->pid != 0) {
200*43393Skarels 		if ((p = pfind(uap->pid)) == 0 || !inferior(p))
201*43393Skarels 			RETURN (ESRCH);
202*43393Skarels 		if (p->p_session != cp->p_session)
203*43393Skarels 			RETURN (EPERM);
204*43393Skarels 		if (p->p_flag&SEXEC)
205*43393Skarels 			RETURN (EACCES);
206*43393Skarels 	} else
207*43393Skarels 		p = cp;
208*43393Skarels 	if (SESS_LEADER(p))
209*43393Skarels 		RETURN (EPERM);
21037579Smckusick 	if (uap->pgid == 0)
21137579Smckusick 		uap->pgid = p->p_pid;
21237579Smckusick 	else if ((uap->pgid != p->p_pid) &&
21337579Smckusick 		(((pgrp = pgfind(uap->pgid)) == 0) ||
21437579Smckusick 		   pgrp->pg_mem == NULL ||
215*43393Skarels 	           pgrp->pg_session != u.u_procp->p_session))
216*43393Skarels 		RETURN (EPERM);
21737579Smckusick 	/*
218*43393Skarels 	 * done checking, now do it
21937579Smckusick 	 */
22037579Smckusick 	pgmv(p, uap->pgid, 0);
221*43393Skarels 	RETURN (0);
2227498Sroot }
2237498Sroot 
224*43393Skarels /* ARGSUSED */
225*43393Skarels setuid(p, uap, retval)
226*43393Skarels 	register struct proc *p;
227*43393Skarels 	struct args {
228*43393Skarels 		int	uid;
229*43393Skarels 	} *uap;
230*43393Skarels 	int *retval;
2317420Sroot {
232*43393Skarels 	register uid_t uid;
233*43393Skarels 	int error;
234*43393Skarels 
235*43393Skarels 	uid = uap->uid;
236*43393Skarels 	if (uid != p->p_ruid && (error = suser(u.u_cred, &u.u_acflag)))
237*43393Skarels 		RETURN (error);
238*43393Skarels 	/*
239*43393Skarels 	 * Everything's okay, do it.
240*43393Skarels 	 * Copy credentials so other references do not
241*43393Skarels 	 * see our changes.
242*43393Skarels 	 */
243*43393Skarels 	if (u.u_cred->cr_ref > 1)
244*43393Skarels 		u.u_cred = crcopy(u.u_cred);
245*43393Skarels 	u.u_cred->cr_uid = uid;
246*43393Skarels 	p->p_uid = uid;
247*43393Skarels 	p->p_ruid = uid;
248*43393Skarels 	p->p_svuid = uid;
249*43393Skarels 	RETURN (0);
250*43393Skarels }
251*43393Skarels 
252*43393Skarels /* ARGSUSED */
253*43393Skarels seteuid(p, uap, retval)
254*43393Skarels 	register struct proc *p;
255*43393Skarels 	struct args {
256*43393Skarels 		int	euid;
257*43393Skarels 	} *uap;
258*43393Skarels 	int *retval;
259*43393Skarels {
260*43393Skarels 	register uid_t euid;
261*43393Skarels 	int error;
262*43393Skarels 
263*43393Skarels 	euid = uap->euid;
264*43393Skarels 	if (euid != p->p_ruid && euid != p->p_svuid &&
265*43393Skarels 	    (error = suser(u.u_cred, &u.u_acflag)))
266*43393Skarels 		RETURN (error);
267*43393Skarels 	/*
268*43393Skarels 	 * Everything's okay, do it.
269*43393Skarels 	 * Copy credentials so other references do not
270*43393Skarels 	 * see our changes.
271*43393Skarels 	 */
272*43393Skarels 	if (u.u_cred->cr_ref > 1)
273*43393Skarels 		u.u_cred = crcopy(u.u_cred);
274*43393Skarels 	u.u_cred->cr_uid = euid;
275*43393Skarels 	p->p_uid = euid;
276*43393Skarels 	RETURN (0);
277*43393Skarels }
278*43393Skarels 
279*43393Skarels /* ARGSUSED */
280*43393Skarels setgid(p, uap, retval)
281*43393Skarels 	struct proc *p;
282*43393Skarels 	struct args {
283*43393Skarels 		int	gid;
284*43393Skarels 	} *uap;
285*43393Skarels 	int *retval;
286*43393Skarels {
287*43393Skarels 	register gid_t gid;
288*43393Skarels 	int error;
289*43393Skarels 
290*43393Skarels 	gid = uap->gid;
291*43393Skarels 	if (gid != p->p_rgid && (error = suser(u.u_cred, &u.u_acflag)))
292*43393Skarels 		RETURN (error);
293*43393Skarels 	if (u.u_cred->cr_ref > 1)
294*43393Skarels 		u.u_cred = crcopy(u.u_cred);
295*43393Skarels 	p->p_rgid = gid;
296*43393Skarels 	u.u_cred->cr_groups[0] = gid;
297*43393Skarels 	p->p_svgid = gid;		/* ??? */
298*43393Skarels 	RETURN (0);
299*43393Skarels }
300*43393Skarels 
301*43393Skarels /* ARGSUSED */
302*43393Skarels setegid(p, uap, retval)
303*43393Skarels 	struct proc *p;
304*43393Skarels 	struct args {
305*43393Skarels 		int	egid;
306*43393Skarels 	} *uap;
307*43393Skarels 	int *retval;
308*43393Skarels {
309*43393Skarels 	register gid_t egid;
310*43393Skarels 	int error;
311*43393Skarels 
312*43393Skarels 	egid = uap->egid;
313*43393Skarels 	if (egid != p->p_rgid && egid != p->p_svgid &&
314*43393Skarels 	    (error = suser(u.u_cred, &u.u_acflag)))
315*43393Skarels 		RETURN (error);
316*43393Skarels 	if (u.u_cred->cr_ref > 1)
317*43393Skarels 		u.u_cred = crcopy(u.u_cred);
318*43393Skarels 	u.u_cred->cr_groups[0] = egid;
319*43393Skarels 	RETURN (0);
320*43393Skarels }
321*43393Skarels 
322*43393Skarels #ifdef COMPAT_43
323*43393Skarels /* ARGSUSED */
324*43393Skarels osetreuid(p, uap, retval)
325*43393Skarels 	register struct proc *p;
326*43393Skarels 	struct args {
3279160Ssam 		int	ruid;
3289160Ssam 		int	euid;
3299160Ssam 	} *uap;
330*43393Skarels 	int *retval;
331*43393Skarels {
332*43393Skarels 	register uid_t ruid, euid;
333*43393Skarels 	int error;
3349160Ssam 
335*43393Skarels 	if (uap->ruid == -1)
33640667Skarels 		ruid = p->p_ruid;
337*43393Skarels 	else
338*43393Skarels 		ruid = uap->ruid;
339*43393Skarels 	/*
340*43393Skarels 	 * Allow setting real uid to previous effective,
341*43393Skarels 	 * for swapping real and effective.
342*43393Skarels 	 * This should be:
343*43393Skarels 	 *   if (ruid != p->p_ruid && (error = suser(u.u_cred, &u.u_acflag)))
344*43393Skarels 	 */
34540667Skarels 	if (ruid != p->p_ruid && ruid != u.u_cred->cr_uid /* XXX */ &&
346*43393Skarels 	    (error = suser(u.u_cred, &u.u_acflag)))
347*43393Skarels 		RETURN (error);
348*43393Skarels 	if (uap->euid == -1)
34940667Skarels 		euid = u.u_cred->cr_uid;
350*43393Skarels 	else
351*43393Skarels 		euid = uap->euid;
35240667Skarels 	if (euid != u.u_cred->cr_uid && euid != p->p_ruid &&
353*43393Skarels 	    euid != p->p_svuid && (error = suser(u.u_cred, &u.u_acflag)))
354*43393Skarels 		RETURN (error);
3559160Ssam 	/*
3569160Ssam 	 * Everything's okay, do it.
35737578Smckusick 	 * Copy credentials so other references do not
35837578Smckusick 	 * see our changes.
3599160Ssam 	 */
36037578Smckusick 	if (u.u_cred->cr_ref > 1)
36137578Smckusick 		u.u_cred = crcopy(u.u_cred);
36240667Skarels 	u.u_cred->cr_uid = euid;
36340667Skarels 	p->p_uid = euid;
36440667Skarels 	p->p_ruid = ruid;
365*43393Skarels 	RETURN (0);
3669160Ssam }
3679160Ssam 
368*43393Skarels /* ARGSUSED */
369*43393Skarels osetregid(p, uap, retval)
370*43393Skarels 	struct proc *p;
371*43393Skarels 	struct args {
3729160Ssam 		int	rgid;
3739160Ssam 		int	egid;
3749160Ssam 	} *uap;
375*43393Skarels 	int *retval;
376*43393Skarels {
377*43393Skarels 	register gid_t rgid, egid;
378*43393Skarels 	int error;
3799160Ssam 
380*43393Skarels 	if (uap->rgid == -1)
38140667Skarels 		rgid = p->p_rgid;
382*43393Skarels 	else
383*43393Skarels 		rgid = uap->rgid;
384*43393Skarels 	/*
385*43393Skarels 	 * Allow setting real gid to previous effective,
386*43393Skarels 	 * for swapping real and effective.  This didn't really work
387*43393Skarels 	 * correctly in 4.[23], but is preserved so old stuff doesn't fail.
388*43393Skarels 	 * This should be:
389*43393Skarels 	 *  if (rgid != p->p_rgid && (error = suser(u.u_cred, &u.u_acflag)))
390*43393Skarels 	 */
39140667Skarels 	if (rgid != p->p_rgid && rgid != u.u_cred->cr_groups[0] /* XXX */ &&
392*43393Skarels 	    (error = suser(u.u_cred, &u.u_acflag)))
393*43393Skarels 		RETURN (error);
394*43393Skarels 	if (uap->egid == -1)
39540667Skarels 		egid = u.u_cred->cr_groups[0];
396*43393Skarels 	else
397*43393Skarels 		egid = uap->egid;
39840667Skarels 	if (egid != u.u_cred->cr_groups[0] && egid != p->p_rgid &&
399*43393Skarels 	    egid != p->p_svgid && (error = suser(u.u_cred, &u.u_acflag)))
400*43393Skarels 		RETURN (error);
40137578Smckusick 	if (u.u_cred->cr_ref > 1)
40237578Smckusick 		u.u_cred = crcopy(u.u_cred);
40340667Skarels 	p->p_rgid = rgid;
40440667Skarels 	u.u_cred->cr_groups[0] = egid;
405*43393Skarels 	RETURN (0);
4069160Ssam }
407*43393Skarels #endif
4089160Ssam 
409*43393Skarels /* ARGSUSED */
410*43393Skarels setgroups(p, uap, retval)
411*43393Skarels 	struct proc *p;
412*43393Skarels 	struct args {
4138624Sroot 		u_int	gidsetsize;
4147498Sroot 		int	*gidset;
415*43393Skarels 	} *uap;
416*43393Skarels 	int *retval;
417*43393Skarels {
41818362Skarels 	register gid_t *gp;
41918362Skarels 	register int *lp;
420*43393Skarels 	int error, ngrp, groups[NGROUPS];
4217498Sroot 
422*43393Skarels 	if (error = suser(u.u_cred, &u.u_acflag))
423*43393Skarels 		RETURN (error);
42440667Skarels 	ngrp = uap->gidsetsize;
425*43393Skarels 	if (ngrp > NGROUPS)
426*43393Skarels 		RETURN (EINVAL);
427*43393Skarels 	error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
42818362Skarels 	    uap->gidsetsize * sizeof (groups[0]));
429*43393Skarels 	if (error)
430*43393Skarels 		RETURN (error);
43140667Skarels 	gp = u.u_cred->cr_groups;
43237578Smckusick 	for (lp = groups; lp < &groups[uap->gidsetsize]; )
43318362Skarels 		*gp++ = *lp++;
43440667Skarels 	u.u_cred->cr_ngroups = ngrp;
435*43393Skarels 	RETURN (0);
4367498Sroot }
4377498Sroot 
4387498Sroot /*
43937578Smckusick  * Check if gid is a member of the group set.
44011810Ssam  */
44137578Smckusick groupmember(gid, cred)
44226275Skarels 	gid_t gid;
44337578Smckusick 	register struct ucred *cred;
4447866Sroot {
44518362Skarels 	register gid_t *gp;
44637578Smckusick 	gid_t *egp;
4477866Sroot 
44837578Smckusick 	egp = &(cred->cr_groups[cred->cr_ngroups]);
44937578Smckusick 	for (gp = cred->cr_groups; gp < egp; gp++)
4507866Sroot 		if (*gp == gid)
45137578Smckusick 			return (1);
45237578Smckusick 	return (0);
4537866Sroot }
4547866Sroot 
45511810Ssam /*
45637578Smckusick  * Test if the current user is the super user.
45711810Ssam  */
45837578Smckusick suser(cred, acflag)
45937578Smckusick 	struct ucred *cred;
46037578Smckusick 	short *acflag;
4617866Sroot {
4627866Sroot 
46337578Smckusick 	if (cred->cr_uid == 0) {
46437578Smckusick 		if (acflag)
46537578Smckusick 			*acflag |= ASU;
46637578Smckusick 		return (0);
46718362Skarels 	}
46837578Smckusick 	return (EPERM);
4697866Sroot }
47011810Ssam 
47111810Ssam /*
47237578Smckusick  * Allocate a zeroed cred structure.
47311810Ssam  */
47437578Smckusick struct ucred *
47537578Smckusick crget()
47611810Ssam {
47737578Smckusick 	register struct ucred *cr;
47811810Ssam 
47937578Smckusick 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
48037578Smckusick 	bzero((caddr_t)cr, sizeof(*cr));
48137578Smckusick 	cr->cr_ref = 1;
482*43393Skarels 	return (cr);
48311810Ssam }
48437085Skfall 
48537085Skfall /*
48637578Smckusick  * Free a cred structure.
48737578Smckusick  * Throws away space when ref count gets to 0.
48837085Skfall  */
48937578Smckusick crfree(cr)
49037578Smckusick 	struct ucred *cr;
49137578Smckusick {
492*43393Skarels 	int s = splimp();
49337085Skfall 
49437578Smckusick 	if (--cr->cr_ref != 0) {
49537578Smckusick 		(void) splx(s);
49637578Smckusick 		return;
49737578Smckusick 	}
49837578Smckusick 	FREE((caddr_t)cr, M_CRED);
49937578Smckusick 	(void) splx(s);
50037578Smckusick }
50137578Smckusick 
50237578Smckusick /*
50337578Smckusick  * Copy cred structure to a new one and free the old one.
50437578Smckusick  */
50537578Smckusick struct ucred *
50637578Smckusick crcopy(cr)
50737578Smckusick 	struct ucred *cr;
50837085Skfall {
50937578Smckusick 	struct ucred *newcr;
51037085Skfall 
51137578Smckusick 	newcr = crget();
51237578Smckusick 	*newcr = *cr;
51337578Smckusick 	crfree(cr);
51437578Smckusick 	newcr->cr_ref = 1;
515*43393Skarels 	return (newcr);
51637085Skfall }
51737085Skfall 
51837085Skfall /*
51937578Smckusick  * Dup cred struct to a new held one.
52037085Skfall  */
52137578Smckusick struct ucred *
52237578Smckusick crdup(cr)
52337578Smckusick 	struct ucred *cr;
52437085Skfall {
52537578Smckusick 	struct ucred *newcr;
52637085Skfall 
52737578Smckusick 	newcr = crget();
52837578Smckusick 	*newcr = *cr;
52937578Smckusick 	newcr->cr_ref = 1;
530*43393Skarels 	return (newcr);
53137085Skfall }
53237579Smckusick 
53337579Smckusick /*
53440667Skarels  * Get login name, if available.
53537579Smckusick  */
536*43393Skarels /* ARGSUSED */
537*43393Skarels getlogin(p, uap, retval)
538*43393Skarels 	struct proc *p;
539*43393Skarels 	struct args {
54037579Smckusick 		char	*namebuf;
54137579Smckusick 		u_int	namelen;
542*43393Skarels 	} *uap;
543*43393Skarels 	int *retval;
544*43393Skarels {
54537579Smckusick 
546*43393Skarels 	if (uap->namelen > sizeof (p->p_logname))
547*43393Skarels 		uap->namelen = sizeof (p->p_logname);
548*43393Skarels 	RETURN (copyout((caddr_t)p->p_logname, (caddr_t)uap->namebuf,
549*43393Skarels 	    uap->namelen));
55037579Smckusick }
55137579Smckusick 
55237579Smckusick /*
55340667Skarels  * Set login name.
55437579Smckusick  */
555*43393Skarels /* ARGSUSED */
556*43393Skarels setlogin(p, uap, retval)
557*43393Skarels 	struct proc *p;
558*43393Skarels 	struct args {
559*43393Skarels 		char	*namebuf;
560*43393Skarels 	} *uap;
561*43393Skarels 	int *retval;
56237579Smckusick {
56340667Skarels 	int error;
56437579Smckusick 
565*43393Skarels 	if (error = suser(u.u_cred, &u.u_acflag))
566*43393Skarels 		RETURN (error);
567*43393Skarels 	error = copyinstr((caddr_t)uap->namebuf, (caddr_t)p->p_logname,
568*43393Skarels 	    sizeof (p->p_logname) - 1, (int *) 0);
56940667Skarels 	if (error == ENOENT)		/* name too long */
57040667Skarels 		error = EINVAL;
571*43393Skarels 	RETURN (error);
57237579Smckusick }
573