1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/sysmacros.h>
32 #include <sys/systm.h>
33 #include <sys/errno.h>
34 #include <sys/file.h>
35 #include <sys/proc.h>
36 #include <sys/session.h>
37 #include <sys/debug.h>
38
39 /* ARGSUSED */
40 int
setpgrp(int flag,int pid,int pgid)41 setpgrp(int flag, int pid, int pgid)
42 {
43 proc_t *p = curproc;
44 int retval = 0;
45 int sid;
46
47 switch (flag) {
48
49 case 1: /* setpgrp() */
50 mutex_enter(&pidlock);
51 if (p->p_sessp->s_sidp != p->p_pidp && !pgmembers(p->p_pid)) {
52 mutex_exit(&pidlock);
53 sess_create();
54 } else
55 mutex_exit(&pidlock);
56 mutex_enter(&p->p_splock);
57 sid = p->p_sessp->s_sid;
58 mutex_exit(&p->p_splock);
59 return (sid);
60
61 case 3: /* setsid() */
62 mutex_enter(&pidlock);
63 if (p->p_pgidp == p->p_pidp || pgmembers(p->p_pid)) {
64 mutex_exit(&pidlock);
65 return (set_errno(EPERM));
66 }
67 mutex_exit(&pidlock);
68 sess_create();
69 mutex_enter(&p->p_splock);
70 sid = p->p_sessp->s_sid;
71 mutex_exit(&p->p_splock);
72 return (sid);
73
74 case 5: /* setpgid() */
75 {
76 mutex_enter(&pidlock);
77 if (pid == 0)
78 pid = p->p_pid;
79 else if (pid < 0 || pid >= maxpid) {
80 mutex_exit(&pidlock);
81 return (set_errno(EINVAL));
82 } else if (pid != p->p_pid) {
83 for (p = p->p_child; /* empty */; p = p->p_sibling) {
84 if (p == NULL) {
85 mutex_exit(&pidlock);
86 return (set_errno(ESRCH));
87 }
88 if (p->p_pid == pid)
89 break;
90 }
91 if (p->p_flag & SEXECED) {
92 mutex_exit(&pidlock);
93 return (set_errno(EACCES));
94 }
95 if (p->p_sessp != ttoproc(curthread)->p_sessp) {
96 mutex_exit(&pidlock);
97 return (set_errno(EPERM));
98 }
99 }
100
101 if (p->p_sessp->s_sid == pid) {
102 mutex_exit(&pidlock);
103 return (set_errno(EPERM));
104 }
105
106 if (pgid == 0)
107 pgid = p->p_pid;
108 else if (pgid < 0 || pgid >= maxpid) {
109 mutex_exit(&pidlock);
110 return (set_errno(EINVAL));
111 }
112
113 if (p->p_pgrp == pgid) {
114 mutex_exit(&pidlock);
115 break;
116 } else if (p->p_pid == pgid) {
117 /*
118 * We need to protect p_pgidp with p_lock because
119 * /proc looks at it while holding only p_lock.
120 */
121 mutex_enter(&p->p_lock);
122 pgexit(p);
123 pgjoin(p, p->p_pidp);
124 mutex_exit(&p->p_lock);
125 } else {
126 register proc_t *q;
127
128 if ((q = pgfind(pgid)) == NULL ||
129 q->p_sessp != p->p_sessp) {
130 mutex_exit(&pidlock);
131 return (set_errno(EPERM));
132 }
133 /*
134 * See comment above about p_lock and /proc
135 */
136 mutex_enter(&p->p_lock);
137 pgexit(p);
138 pgjoin(p, q->p_pgidp);
139 mutex_exit(&p->p_lock);
140 }
141 mutex_exit(&pidlock);
142 break;
143 }
144
145 case 0: /* getpgrp() */
146 mutex_enter(&pidlock);
147 retval = p->p_pgrp;
148 mutex_exit(&pidlock);
149 break;
150
151 case 2: /* getsid() */
152 case 4: /* getpgid() */
153 if (pid < 0 || pid >= maxpid) {
154 return (set_errno(EINVAL));
155 }
156 mutex_enter(&pidlock);
157 if (pid != 0 && p->p_pid != pid &&
158 ((p = prfind(pid)) == NULL || p->p_stat == SIDL)) {
159 mutex_exit(&pidlock);
160 return (set_errno(ESRCH));
161 }
162 if (flag == 2)
163 retval = p->p_sessp->s_sid;
164 else
165 retval = p->p_pgrp;
166 mutex_exit(&pidlock);
167 break;
168
169 }
170 return (retval);
171 }
172