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*68309Scgd * @(#)kern_prot.c 8.9 (Berkeley) 02/14/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
28*68309Scgd #include <sys/mount.h>
29*68309Scgd #include <sys/syscallargs.h>
3054925Storek
3143393Skarels /* ARGSUSED */
32*68309Scgd int
getpid(p,uap,retval)3343393Skarels getpid(p, uap, retval)
3443393Skarels struct proc *p;
35*68309Scgd void *uap;
36*68309Scgd register_t *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 */
47*68309Scgd int
getppid(p,uap,retval)4843393Skarels getppid(p, uap, retval)
4943393Skarels struct proc *p;
50*68309Scgd void *uap;
51*68309Scgd register_t *retval;
527498Sroot {
537498Sroot
5447540Skarels *retval = p->p_pptr->p_pid;
5544405Skarels return (0);
567498Sroot }
577498Sroot
5847540Skarels /* Get process group ID; note that POSIX getpgrp takes no parameter */
59*68309Scgd int
getpgrp(p,uap,retval)6043393Skarels getpgrp(p, uap, retval)
6143393Skarels struct proc *p;
62*68309Scgd void *uap;
63*68309Scgd register_t *retval;
647498Sroot {
657498Sroot
6643393Skarels *retval = p->p_pgrp->pg_id;
6744405Skarels return (0);
687498Sroot }
697498Sroot
7043393Skarels /* ARGSUSED */
71*68309Scgd int
getuid(p,uap,retval)7243393Skarels getuid(p, uap, retval)
7343393Skarels struct proc *p;
74*68309Scgd void *uap;
75*68309Scgd register_t *retval;
767420Sroot {
777420Sroot
7847540Skarels *retval = p->p_cred->p_ruid;
7952495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
8047540Skarels retval[1] = p->p_ucred->cr_uid;
8143393Skarels #endif
8244405Skarels return (0);
837420Sroot }
847420Sroot
8543393Skarels /* ARGSUSED */
86*68309Scgd int
geteuid(p,uap,retval)8743393Skarels geteuid(p, uap, retval)
8843393Skarels struct proc *p;
89*68309Scgd void *uap;
90*68309Scgd register_t *retval;
917498Sroot {
927498Sroot
9347540Skarels *retval = p->p_ucred->cr_uid;
9444405Skarels return (0);
957498Sroot }
967498Sroot
9743393Skarels /* ARGSUSED */
98*68309Scgd int
getgid(p,uap,retval)9943393Skarels getgid(p, uap, retval)
10043393Skarels struct proc *p;
101*68309Scgd void *uap;
102*68309Scgd register_t *retval;
1037498Sroot {
10443393Skarels
10547540Skarels *retval = p->p_cred->p_rgid;
10652495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
10747540Skarels retval[1] = p->p_ucred->cr_groups[0];
10843393Skarels #endif
10944405Skarels return (0);
11043393Skarels }
11143393Skarels
11243393Skarels /*
11345908Sbostic * Get effective group ID. The "egid" is groups[0], and could be obtained
11445908Sbostic * via getgroups. This syscall exists because it is somewhat painful to do
11545908Sbostic * correctly in a library function.
11643393Skarels */
11743393Skarels /* ARGSUSED */
118*68309Scgd int
getegid(p,uap,retval)11943393Skarels getegid(p, uap, retval)
12043393Skarels struct proc *p;
121*68309Scgd void *uap;
122*68309Scgd register_t *retval;
12343393Skarels {
12447540Skarels
12547540Skarels *retval = p->p_ucred->cr_groups[0];
12644405Skarels return (0);
12743393Skarels }
12843393Skarels
129*68309Scgd int
getgroups(p,uap,retval)13043393Skarels getgroups(p, uap, retval)
13143393Skarels struct proc *p;
132*68309Scgd register struct getgroups_args /* {
133*68309Scgd syscallarg(u_int) gidsetsize;
134*68309Scgd syscallarg(gid_t *) gidset;
135*68309Scgd } */ *uap;
136*68309Scgd register_t *retval;
13743393Skarels {
13847540Skarels register struct pcred *pc = p->p_cred;
13944994Skarels register u_int ngrp;
14043393Skarels int error;
1417498Sroot
142*68309Scgd if ((ngrp = SCARG(uap, gidsetsize)) == 0) {
14347540Skarels *retval = pc->pc_ucred->cr_ngroups;
14444405Skarels return (0);
14537578Smckusick }
14647540Skarels if (ngrp < pc->pc_ucred->cr_ngroups)
14744405Skarels return (EINVAL);
14847540Skarels ngrp = pc->pc_ucred->cr_ngroups;
14955162Smckusick if (error = copyout((caddr_t)pc->pc_ucred->cr_groups,
150*68309Scgd (caddr_t)SCARG(uap, gidset), ngrp * sizeof(gid_t)))
15144405Skarels return (error);
15244994Skarels *retval = ngrp;
15344405Skarels return (0);
1547498Sroot }
1557498Sroot
15643393Skarels /* ARGSUSED */
157*68309Scgd int
setsid(p,uap,retval)15843393Skarels setsid(p, uap, retval)
15947540Skarels register struct proc *p;
160*68309Scgd void *uap;
161*68309Scgd register_t *retval;
16237579Smckusick {
16337579Smckusick
16443393Skarels if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
16544405Skarels return (EPERM);
16643393Skarels } else {
16757049Smarc (void)enterpgrp(p, p->p_pid, 1);
16843393Skarels *retval = p->p_pid;
16944405Skarels return (0);
17037579Smckusick }
17137579Smckusick }
17237579Smckusick
17337579Smckusick /*
17447540Skarels * set process group (setpgid/old setpgrp)
17537579Smckusick *
17647972Smarc * caller does setpgid(targpid, targpgid)
17740667Skarels *
17840667Skarels * pid must be caller or child of caller (ESRCH)
17940667Skarels * if a child
18040667Skarels * pid must be in same session (EPERM)
18140667Skarels * pid can't have done an exec (EACCES)
18240667Skarels * if pgid != pid
18340667Skarels * there must exist some pid in same session having pgid (EPERM)
18440667Skarels * pid must not be session leader (EPERM)
18537579Smckusick */
18643393Skarels /* ARGSUSED */
187*68309Scgd int
setpgid(curp,uap,retval)18847972Smarc setpgid(curp, uap, retval)
18947972Smarc struct proc *curp;
190*68309Scgd register struct setpgid_args /* {
191*68309Scgd syscallarg(int) pid;
192*68309Scgd syscallarg(int) pgid;
193*68309Scgd } */ *uap;
194*68309Scgd register_t *retval;
19543393Skarels {
19647972Smarc register struct proc *targp; /* target process */
19748990Skarels register struct pgrp *pgrp; /* target pgrp */
1987498Sroot
199*68309Scgd if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) {
200*68309Scgd if ((targp = pfind(SCARG(uap, pid))) == 0 || !inferior(targp))
20144405Skarels return (ESRCH);
20247972Smarc if (targp->p_session != curp->p_session)
20344405Skarels return (EPERM);
20464586Sbostic if (targp->p_flag & P_EXEC)
20544405Skarels return (EACCES);
20643393Skarels } else
20747972Smarc targp = curp;
20847972Smarc if (SESS_LEADER(targp))
20944405Skarels return (EPERM);
210*68309Scgd if (SCARG(uap, pgid) == 0)
211*68309Scgd SCARG(uap, pgid) = targp->p_pid;
212*68309Scgd else if (SCARG(uap, pgid) != targp->p_pid)
213*68309Scgd if ((pgrp = pgfind(SCARG(uap, pgid))) == 0 ||
21448990Skarels pgrp->pg_session != curp->p_session)
21545908Sbostic return (EPERM);
216*68309Scgd return (enterpgrp(targp, SCARG(uap, pgid), 0));
2177498Sroot }
2187498Sroot
21943393Skarels /* ARGSUSED */
220*68309Scgd int
setuid(p,uap,retval)22143393Skarels setuid(p, uap, retval)
22247540Skarels struct proc *p;
223*68309Scgd struct setuid_args /* {
224*68309Scgd syscallarg(uid_t) uid;
225*68309Scgd } */ *uap;
226*68309Scgd register_t *retval;
2277420Sroot {
22847540Skarels register struct pcred *pc = p->p_cred;
22943393Skarels register uid_t uid;
23043393Skarels int error;
23143393Skarels
232*68309Scgd uid = SCARG(uap, uid);
23347540Skarels if (uid != pc->p_ruid &&
23447540Skarels (error = suser(pc->pc_ucred, &p->p_acflag)))
23544405Skarels return (error);
23643393Skarels /*
23755403Smckusick * Everything's okay, do it.
23855403Smckusick * Transfer proc count to new user.
23955403Smckusick * Copy credentials so other references do not see our changes.
24043393Skarels */
24155403Smckusick (void)chgproccnt(pc->p_ruid, -1);
24255403Smckusick (void)chgproccnt(uid, 1);
24347540Skarels pc->pc_ucred = crcopy(pc->pc_ucred);
24447540Skarels pc->pc_ucred->cr_uid = uid;
24547540Skarels pc->p_ruid = uid;
24647540Skarels pc->p_svuid = uid;
24764586Sbostic p->p_flag |= P_SUGID;
24844405Skarels return (0);
24943393Skarels }
25043393Skarels
25143393Skarels /* ARGSUSED */
252*68309Scgd int
seteuid(p,uap,retval)25343393Skarels seteuid(p, uap, retval)
25447540Skarels struct proc *p;
255*68309Scgd struct seteuid_args /* {
256*68309Scgd syscallarg(uid_t) euid;
257*68309Scgd } */ *uap;
258*68309Scgd register_t *retval;
25943393Skarels {
26047540Skarels register struct pcred *pc = p->p_cred;
26143393Skarels register uid_t euid;
26243393Skarels int error;
26343393Skarels
264*68309Scgd euid = SCARG(uap, euid);
26547540Skarels if (euid != pc->p_ruid && euid != pc->p_svuid &&
26647540Skarels (error = suser(pc->pc_ucred, &p->p_acflag)))
26744405Skarels return (error);
26843393Skarels /*
26945908Sbostic * Everything's okay, do it. Copy credentials so other references do
27045908Sbostic * not see our changes.
27143393Skarels */
27247540Skarels pc->pc_ucred = crcopy(pc->pc_ucred);
27347540Skarels pc->pc_ucred->cr_uid = euid;
27464586Sbostic p->p_flag |= P_SUGID;
27544405Skarels return (0);
27643393Skarels }
27743393Skarels
27843393Skarels /* ARGSUSED */
279*68309Scgd int
setgid(p,uap,retval)28043393Skarels setgid(p, uap, retval)
28143393Skarels struct proc *p;
282*68309Scgd struct setgid_args /* {
283*68309Scgd syscallarg(gid_t) gid;
284*68309Scgd } */ *uap;
285*68309Scgd register_t *retval;
28643393Skarels {
28747540Skarels register struct pcred *pc = p->p_cred;
28843393Skarels register gid_t gid;
28943393Skarels int error;
29043393Skarels
291*68309Scgd gid = SCARG(uap, gid);
29247540Skarels if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
29344405Skarels return (error);
29447540Skarels pc->pc_ucred = crcopy(pc->pc_ucred);
29547540Skarels pc->pc_ucred->cr_groups[0] = gid;
29647540Skarels pc->p_rgid = gid;
29747540Skarels pc->p_svgid = gid; /* ??? */
29864586Sbostic p->p_flag |= P_SUGID;
29944405Skarels return (0);
30043393Skarels }
30143393Skarels
30243393Skarels /* ARGSUSED */
303*68309Scgd int
setegid(p,uap,retval)30443393Skarels setegid(p, uap, retval)
30543393Skarels struct proc *p;
306*68309Scgd struct setegid_args /* {
307*68309Scgd syscallarg(gid_t) egid;
308*68309Scgd } */ *uap;
309*68309Scgd register_t *retval;
31043393Skarels {
31147540Skarels register struct pcred *pc = p->p_cred;
31243393Skarels register gid_t egid;
31343393Skarels int error;
31443393Skarels
315*68309Scgd egid = SCARG(uap, egid);
31647540Skarels if (egid != pc->p_rgid && egid != pc->p_svgid &&
31747540Skarels (error = suser(pc->pc_ucred, &p->p_acflag)))
31844405Skarels return (error);
31947540Skarels pc->pc_ucred = crcopy(pc->pc_ucred);
32047540Skarels pc->pc_ucred->cr_groups[0] = egid;
32164586Sbostic p->p_flag |= P_SUGID;
32244405Skarels return (0);
32343393Skarels }
32443393Skarels
32543393Skarels /* ARGSUSED */
326*68309Scgd int
setgroups(p,uap,retval)32743393Skarels setgroups(p, uap, retval)
32843393Skarels struct proc *p;
329*68309Scgd struct setgroups_args /* {
330*68309Scgd syscallarg(u_int) gidsetsize;
331*68309Scgd syscallarg(gid_t *) gidset;
332*68309Scgd } */ *uap;
333*68309Scgd register_t *retval;
33443393Skarels {
33547540Skarels register struct pcred *pc = p->p_cred;
33644994Skarels register u_int ngrp;
33755162Smckusick int error;
3387498Sroot
33947540Skarels if (error = suser(pc->pc_ucred, &p->p_acflag))
34044405Skarels return (error);
341*68309Scgd ngrp = SCARG(uap, gidsetsize);
342*68309Scgd if (ngrp < 1 || ngrp > NGROUPS)
34344405Skarels return (EINVAL);
34455162Smckusick pc->pc_ucred = crcopy(pc->pc_ucred);
345*68309Scgd if (error = copyin((caddr_t)SCARG(uap, gidset),
34655162Smckusick (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))
34744405Skarels return (error);
34847540Skarels pc->pc_ucred->cr_ngroups = ngrp;
34964586Sbostic p->p_flag |= P_SUGID;
35044405Skarels return (0);
3517498Sroot }
3527498Sroot
35355163Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
35455163Smckusick /* ARGSUSED */
355*68309Scgd int
compat_43_setreuid(p,uap,retval)356*68309Scgd compat_43_setreuid(p, uap, retval)
35755163Smckusick register struct proc *p;
358*68309Scgd struct compat_43_setreuid_args /* {
359*68309Scgd syscallarg(int) ruid;
360*68309Scgd syscallarg(int) euid;
361*68309Scgd } */ *uap;
362*68309Scgd register_t *retval;
36355163Smckusick {
36455163Smckusick register struct pcred *pc = p->p_cred;
36567875Shibler union {
36667875Shibler struct setuid_args sa;
36767875Shibler struct seteuid_args ea;
36867875Shibler } args;
36955163Smckusick
37055163Smckusick /*
37167875Shibler * If ruid == euid then setreuid is being used to emulate setuid,
37267875Shibler * just do it.
37355163Smckusick */
374*68309Scgd if (SCARG(uap, ruid) != -1 && SCARG(uap, ruid) == SCARG(uap, euid)) {
375*68309Scgd SCARG(&args.sa, uid) = SCARG(uap, ruid);
37667875Shibler return (setuid(p, &args.sa, retval));
37767875Shibler }
37867875Shibler /*
37967875Shibler * Otherwise we assume that the intent of setting ruid is to be
38067875Shibler * able to get back ruid priviledge (i.e. swapping ruid and euid).
38167875Shibler * So we make sure that we will be able to do so, but do not
38267875Shibler * actually set the ruid.
38367875Shibler */
384*68309Scgd if (SCARG(uap, ruid) != (uid_t)-1 && SCARG(uap, ruid) != pc->p_ruid &&
385*68309Scgd SCARG(uap, ruid) != pc->p_svuid)
38655163Smckusick return (EPERM);
387*68309Scgd if (SCARG(uap, euid) == (uid_t)-1)
38855163Smckusick return (0);
389*68309Scgd SCARG(&args.ea, euid) = SCARG(uap, euid);
39067875Shibler return (seteuid(p, &args.ea, retval));
39155163Smckusick }
39255163Smckusick
39355163Smckusick /* ARGSUSED */
394*68309Scgd int
compat_43_setregid(p,uap,retval)395*68309Scgd compat_43_setregid(p, uap, retval)
39655163Smckusick register struct proc *p;
397*68309Scgd struct compat_43_setregid_args /* {
398*68309Scgd syscallarg(int) rgid;
399*68309Scgd syscallarg(int) egid;
400*68309Scgd } */ *uap;
401*68309Scgd register_t *retval;
40255163Smckusick {
40355163Smckusick register struct pcred *pc = p->p_cred;
40467875Shibler union {
40567875Shibler struct setgid_args sa;
40667875Shibler struct setegid_args ea;
40767875Shibler } args;
40855163Smckusick
40955163Smckusick /*
41067875Shibler * If rgid == egid then setreuid is being used to emulate setgid,
41167875Shibler * just do it.
41255163Smckusick */
413*68309Scgd if (SCARG(uap, rgid) != -1 && SCARG(uap, rgid) == SCARG(uap, egid)) {
414*68309Scgd SCARG(&args.sa, gid) = SCARG(uap, rgid);
41567875Shibler return (setgid(p, &args.sa, retval));
41667875Shibler }
41767875Shibler /*
41867875Shibler * Otherwise we assume that the intent of setting rgid is to be
41967875Shibler * able to get back rgid priviledge (i.e. swapping rgid and egid).
42067875Shibler * So we make sure that we will be able to do so, but do not
42167875Shibler * actually set the rgid.
42267875Shibler */
423*68309Scgd if (SCARG(uap, rgid) != (gid_t)-1 && SCARG(uap, rgid) != pc->p_rgid &&
424*68309Scgd SCARG(uap, rgid) != pc->p_svgid)
42555163Smckusick return (EPERM);
426*68309Scgd if (SCARG(uap, egid) == (gid_t)-1)
42755163Smckusick return (0);
428*68309Scgd SCARG(&args.ea, egid) = SCARG(uap, egid);
42967875Shibler return (setegid(p, &args.ea, retval));
43055163Smckusick }
43155163Smckusick #endif /* defined(COMPAT_43) || defined(COMPAT_SUNOS) */
43255163Smckusick
4337498Sroot /*
43437578Smckusick * Check if gid is a member of the group set.
43511810Ssam */
436*68309Scgd int
groupmember(gid,cred)43737578Smckusick groupmember(gid, cred)
43826275Skarels gid_t gid;
43937578Smckusick register struct ucred *cred;
4407866Sroot {
44118362Skarels register gid_t *gp;
44237578Smckusick gid_t *egp;
4437866Sroot
44437578Smckusick egp = &(cred->cr_groups[cred->cr_ngroups]);
44537578Smckusick for (gp = cred->cr_groups; gp < egp; gp++)
4467866Sroot if (*gp == gid)
44737578Smckusick return (1);
44837578Smckusick return (0);
4497866Sroot }
4507866Sroot
45111810Ssam /*
45246293Skarels * Test whether the specified credentials imply "super-user"
45346293Skarels * privilege; if so, and we have accounting info, set the flag
45446293Skarels * indicating use of super-powers.
45546293Skarels * Returns 0 or error.
45611810Ssam */
457*68309Scgd int
suser(cred,acflag)45837578Smckusick suser(cred, acflag)
45937578Smckusick struct ucred *cred;
46068171Scgd u_short *acflag;
4617866Sroot {
46237578Smckusick if (cred->cr_uid == 0) {
46337578Smckusick if (acflag)
46437578Smckusick *acflag |= ASU;
46537578Smckusick return (0);
46618362Skarels }
46737578Smckusick return (EPERM);
4687866Sroot }
46911810Ssam
47011810Ssam /*
47137578Smckusick * Allocate a zeroed cred structure.
47211810Ssam */
47337578Smckusick struct ucred *
crget()47437578Smckusick crget()
47511810Ssam {
47637578Smckusick register struct ucred *cr;
47711810Ssam
47837578Smckusick MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
47937578Smckusick bzero((caddr_t)cr, sizeof(*cr));
48037578Smckusick cr->cr_ref = 1;
48143393Skarels return (cr);
48211810Ssam }
48337085Skfall
48437085Skfall /*
48537578Smckusick * Free a cred structure.
48637578Smckusick * Throws away space when ref count gets to 0.
48737085Skfall */
48868171Scgd void
crfree(cr)48937578Smckusick crfree(cr)
49037578Smckusick struct ucred *cr;
49137578Smckusick {
49265537Sbostic int s;
49337085Skfall
49465537Sbostic s = splimp(); /* ??? */
49565537Sbostic if (--cr->cr_ref == 0)
49665537Sbostic FREE((caddr_t)cr, M_CRED);
49737578Smckusick (void) splx(s);
49837578Smckusick }
49937578Smckusick
50037578Smckusick /*
50137578Smckusick * Copy cred structure to a new one and free the old one.
50237578Smckusick */
50337578Smckusick struct ucred *
crcopy(cr)50437578Smckusick crcopy(cr)
50537578Smckusick struct ucred *cr;
50637085Skfall {
50737578Smckusick struct ucred *newcr;
50837085Skfall
50945908Sbostic if (cr->cr_ref == 1)
51045908Sbostic return (cr);
51137578Smckusick newcr = crget();
51237578Smckusick *newcr = *cr;
51337578Smckusick crfree(cr);
51437578Smckusick newcr->cr_ref = 1;
51543393Skarels return (newcr);
51637085Skfall }
51737085Skfall
51837085Skfall /*
51937578Smckusick * Dup cred struct to a new held one.
52037085Skfall */
52137578Smckusick struct ucred *
crdup(cr)52237578Smckusick crdup(cr)
52337578Smckusick struct ucred *cr;
52437085Skfall {
52537578Smckusick struct ucred *newcr;
52637085Skfall
52737578Smckusick newcr = crget();
52837578Smckusick *newcr = *cr;
52937578Smckusick newcr->cr_ref = 1;
53043393Skarels return (newcr);
53137085Skfall }
53237579Smckusick
53337579Smckusick /*
53440667Skarels * Get login name, if available.
53537579Smckusick */
53643393Skarels /* ARGSUSED */
537*68309Scgd int
getlogin(p,uap,retval)53843393Skarels getlogin(p, uap, retval)
53943393Skarels struct proc *p;
540*68309Scgd struct getlogin_args /* {
541*68309Scgd syscallarg(char *) namebuf;
542*68309Scgd syscallarg(u_int) namelen;
543*68309Scgd } */ *uap;
544*68309Scgd register_t *retval;
54543393Skarels {
54637579Smckusick
547*68309Scgd if (SCARG(uap, namelen) > sizeof (p->p_pgrp->pg_session->s_login))
548*68309Scgd SCARG(uap, namelen) = sizeof (p->p_pgrp->pg_session->s_login);
54947540Skarels return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
550*68309Scgd (caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen)));
55137579Smckusick }
55237579Smckusick
55337579Smckusick /*
55440667Skarels * Set login name.
55537579Smckusick */
55643393Skarels /* ARGSUSED */
557*68309Scgd int
setlogin(p,uap,retval)55843393Skarels setlogin(p, uap, retval)
55943393Skarels struct proc *p;
560*68309Scgd struct setlogin_args /* {
561*68309Scgd syscallarg(char *) namebuf;
562*68309Scgd } */ *uap;
563*68309Scgd register_t *retval;
56437579Smckusick {
56540667Skarels int error;
56637579Smckusick
56747540Skarels if (error = suser(p->p_ucred, &p->p_acflag))
56844405Skarels return (error);
569*68309Scgd error = copyinstr((caddr_t) SCARG(uap, namebuf),
57047540Skarels (caddr_t) p->p_pgrp->pg_session->s_login,
57147540Skarels sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
57247540Skarels if (error == ENAMETOOLONG)
57340667Skarels error = EINVAL;
57444405Skarels return (error);
57537579Smckusick }
576