1 |
/* Session and process group manipulation |
/* Session and process group manipulation |
2 |
Copyright (C) 1992,93,94,95,96,99,2001 Free Software Foundation, Inc. |
Copyright (C) 1992,93,94,95,96,99,2001,02 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of the GNU Hurd. |
This file is part of the GNU Hurd. |
5 |
|
|
8 |
the Free Software Foundation; either version 2, or (at your option) |
the Free Software Foundation; either version 2, or (at your option) |
9 |
any later version. |
any later version. |
10 |
|
|
11 |
The GNU Hurd is distributed in the hope that it will be useful, |
The GNU Hurd is distributed in the hope that it will be useful, |
12 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
GNU General Public License for more details. |
GNU General Public License for more details. |
38 |
struct session *sess) |
struct session *sess) |
39 |
{ |
{ |
40 |
struct pgrp *pg; |
struct pgrp *pg; |
41 |
|
|
42 |
pg = malloc (sizeof (struct pgrp)); |
pg = malloc (sizeof (struct pgrp)); |
43 |
if (! pg) |
if (! pg) |
44 |
return NULL; |
return NULL; |
46 |
pg->pg_plist = 0; |
pg->pg_plist = 0; |
47 |
pg->pg_pgid = pgid; |
pg->pg_pgid = pgid; |
48 |
pg->pg_orphcnt = 0; |
pg->pg_orphcnt = 0; |
49 |
|
|
50 |
pg->pg_session = sess; |
pg->pg_session = sess; |
51 |
pg->pg_next = sess->s_pgrps; |
pg->pg_next = sess->s_pgrps; |
52 |
if (pg->pg_next) |
if (pg->pg_next) |
53 |
pg->pg_next->pg_prevp = &pg->pg_next; |
pg->pg_next->pg_prevp = &pg->pg_next; |
54 |
sess->s_pgrps = pg; |
sess->s_pgrps = pg; |
55 |
pg->pg_prevp = &sess->s_pgrps; |
pg->pg_prevp = &sess->s_pgrps; |
56 |
|
|
57 |
add_pgrp_to_hash (pg); |
add_pgrp_to_hash (pg); |
58 |
return pg; |
return pg; |
59 |
} |
} |
63 |
new_session (struct proc *p) |
new_session (struct proc *p) |
64 |
{ |
{ |
65 |
struct session *sess; |
struct session *sess; |
66 |
|
|
67 |
sess = malloc (sizeof (struct session)); |
sess = malloc (sizeof (struct session)); |
68 |
if (! sess) |
if (! sess) |
69 |
return NULL; |
return NULL; |
73 |
sess->s_sessionid = MACH_PORT_NULL; |
sess->s_sessionid = MACH_PORT_NULL; |
74 |
|
|
75 |
add_session_to_hash (sess); |
add_session_to_hash (sess); |
76 |
|
|
77 |
return sess; |
return sess; |
78 |
} |
} |
79 |
|
|
100 |
remove_pgrp_from_hash (pg); |
remove_pgrp_from_hash (pg); |
101 |
free (pg); |
free (pg); |
102 |
} |
} |
103 |
|
|
104 |
/* Implement proc_setsid as described in <hurd/process.defs>. */ |
/* Implement proc_setsid as described in <hurd/process.defs>. */ |
105 |
kern_return_t |
kern_return_t |
106 |
S_proc_setsid (struct proc *p) |
S_proc_setsid (struct proc *p) |
107 |
{ |
{ |
108 |
struct session *sess; |
struct session *sess; |
109 |
|
|
110 |
if (!p) |
if (!p) |
111 |
return EOPNOTSUPP; |
return EOPNOTSUPP; |
112 |
|
|
113 |
if (p->p_pgrp->pg_pgid == p->p_pid || pgrp_find (p->p_pid)) |
if (p->p_pgrp->pg_pgid == p->p_pid || pgrp_find (p->p_pid)) |
114 |
return EPERM; |
return EPERM; |
115 |
|
|
116 |
leave_pgrp (p); |
leave_pgrp (p); |
117 |
|
|
118 |
sess = new_session (p); |
sess = new_session (p); |
119 |
p->p_pgrp= new_pgrp (p->p_pid, sess); |
p->p_pgrp= new_pgrp (p->p_pid, sess); |
120 |
join_pgrp (p); |
join_pgrp (p); |
127 |
boot_setsid (struct proc *p) |
boot_setsid (struct proc *p) |
128 |
{ |
{ |
129 |
struct session *sess; |
struct session *sess; |
130 |
|
|
131 |
sess = new_session (p); |
sess = new_session (p); |
132 |
p->p_pgrp = new_pgrp (p->p_pid, sess); |
p->p_pgrp = new_pgrp (p->p_pid, sess); |
133 |
assert (p->p_pgrp); |
assert (p->p_pgrp); |
156 |
S_proc_getsessionpids (struct proc *callerp, |
S_proc_getsessionpids (struct proc *callerp, |
157 |
pid_t sid, |
pid_t sid, |
158 |
pid_t **pids, |
pid_t **pids, |
159 |
u_int *npidsp) |
size_t *npidsp) |
160 |
{ |
{ |
161 |
int count; |
int count; |
162 |
struct pgrp *pg; |
struct pgrp *pg; |
164 |
struct session *s; |
struct session *s; |
165 |
pid_t *pp = *pids; |
pid_t *pp = *pids; |
166 |
u_int npids = *npidsp; |
u_int npids = *npidsp; |
167 |
|
|
168 |
/* No need to check CALLERP; we don't use it. */ |
/* No need to check CALLERP; we don't use it. */ |
169 |
|
|
170 |
s = session_find (sid); |
s = session_find (sid); |
171 |
if (!s) |
if (!s) |
172 |
return ESRCH; |
return ESRCH; |
173 |
|
|
174 |
count = 0; |
count = 0; |
175 |
for (pg = s->s_pgrps; pg; pg = pg->pg_next) |
for (pg = s->s_pgrps; pg; pg = pg->pg_next) |
176 |
for (p = pg->pg_plist; p; p = p->p_gnext) |
for (p = pg->pg_plist; p; p = p->p_gnext) |
178 |
if (++count <= npids) |
if (++count <= npids) |
179 |
*pp++ = p->p_pid; |
*pp++ = p->p_pid; |
180 |
} |
} |
181 |
|
|
182 |
if (count > npids) |
if (count > npids) |
183 |
/* They didn't all fit */ |
/* They didn't all fit */ |
184 |
{ |
{ |
203 |
S_proc_getsessionpgids (struct proc *callerp, |
S_proc_getsessionpgids (struct proc *callerp, |
204 |
pid_t sid, |
pid_t sid, |
205 |
pid_t **pgids, |
pid_t **pgids, |
206 |
u_int *npgidsp) |
size_t *npgidsp) |
207 |
{ |
{ |
208 |
int count; |
int count; |
209 |
struct pgrp *pg; |
struct pgrp *pg; |
210 |
struct session *s; |
struct session *s; |
211 |
pid_t *pp = *pgids; |
pid_t *pp = *pgids; |
212 |
int npgids = *npgidsp; |
int npgids = *npgidsp; |
213 |
|
|
214 |
/* No need to check CALLERP; we don't use it. */ |
/* No need to check CALLERP; we don't use it. */ |
215 |
|
|
216 |
s = session_find (sid); |
s = session_find (sid); |
221 |
for (pg = s->s_pgrps; pg; pg = pg->pg_next) |
for (pg = s->s_pgrps; pg; pg = pg->pg_next) |
222 |
if (++count <= npgids) |
if (++count <= npgids) |
223 |
*pp++ = pg->pg_pgid; |
*pp++ = pg->pg_pgid; |
224 |
|
|
225 |
if (count > npgids) |
if (count > npgids) |
226 |
/* They didn't all fit. */ |
/* They didn't all fit. */ |
227 |
{ |
{ |
244 |
S_proc_getpgrppids (struct proc *callerp, |
S_proc_getpgrppids (struct proc *callerp, |
245 |
pid_t pgid, |
pid_t pgid, |
246 |
pid_t **pids, |
pid_t **pids, |
247 |
u_int *npidsp) |
size_t *npidsp) |
248 |
{ |
{ |
249 |
|
|
250 |
struct proc *p; |
struct proc *p; |
251 |
struct pgrp *pg; |
struct pgrp *pg; |
252 |
pid_t *pp = *pids; |
pid_t *pp = *pids; |
253 |
unsigned int npids = *npidsp, count; |
unsigned int npids = *npidsp, count; |
254 |
|
|
255 |
/* No need to check CALLERP; we don't use it. */ |
/* No need to check CALLERP; we don't use it. */ |
256 |
|
|
257 |
if (pgid == 0) |
if (pgid == 0) |
267 |
for (p = pg->pg_plist; p; p = p->p_gnext) |
for (p = pg->pg_plist; p; p = p->p_gnext) |
268 |
if (++count <= npids) |
if (++count <= npids) |
269 |
*pp++ = p->p_pid; |
*pp++ = p->p_pid; |
270 |
|
|
271 |
if (count > npids) |
if (count > npids) |
272 |
/* They didn't all fit. */ |
/* They didn't all fit. */ |
273 |
{ |
{ |
291 |
mach_port_t *sessport, mach_msg_type_name_t *sessport_type) |
mach_port_t *sessport, mach_msg_type_name_t *sessport_type) |
292 |
{ |
{ |
293 |
error_t err = 0; |
error_t err = 0; |
294 |
|
|
295 |
if (!p) |
if (!p) |
296 |
return EOPNOTSUPP; |
return EOPNOTSUPP; |
297 |
|
|
316 |
{ |
{ |
317 |
struct proc *p; |
struct proc *p; |
318 |
struct pgrp *pg; |
struct pgrp *pg; |
319 |
|
|
320 |
if (!callerp) |
if (!callerp) |
321 |
return EOPNOTSUPP; |
return EOPNOTSUPP; |
322 |
|
|
324 |
|
|
325 |
if (!p || (p != callerp && p->p_parent != callerp)) |
if (!p || (p != callerp && p->p_parent != callerp)) |
326 |
return ESRCH; |
return ESRCH; |
327 |
|
|
328 |
if (p->p_parent == callerp && p->p_exec) |
if (p->p_parent == callerp && p->p_exec) |
329 |
return EACCES; |
return EACCES; |
330 |
|
|
331 |
if (!pgid) |
if (!pgid) |
332 |
pgid = p->p_pid; |
pgid = p->p_pid; |
333 |
pg = pgrp_find (pgid); |
pg = pgrp_find (pgid); |
337 |
|| ((pgid != p->p_pid |
|| ((pgid != p->p_pid |
338 |
&& (!pg || pg->pg_session != callerp->p_pgrp->pg_session)))) |
&& (!pg || pg->pg_session != callerp->p_pgrp->pg_session)))) |
339 |
return EPERM; |
return EPERM; |
340 |
|
|
341 |
if (p->p_pgrp != pg) |
if (p->p_pgrp != pg) |
342 |
{ |
{ |
343 |
leave_pgrp (p); |
leave_pgrp (p); |
347 |
else |
else |
348 |
nowait_msg_proc_newids (p->p_msgport, p->p_task, p->p_parent->p_pid, |
nowait_msg_proc_newids (p->p_msgport, p->p_task, p->p_parent->p_pid, |
349 |
pg->pg_pgid, !pg->pg_orphcnt); |
pg->pg_pgid, !pg->pg_orphcnt); |
350 |
|
|
351 |
return 0; |
return 0; |
352 |
} |
} |
353 |
|
|
360 |
struct proc *p = pid_find (pid); |
struct proc *p = pid_find (pid); |
361 |
|
|
362 |
/* No need to check CALLERP; we don't use it. */ |
/* No need to check CALLERP; we don't use it. */ |
363 |
|
|
364 |
if (!p) |
if (!p) |
365 |
return ESRCH; |
return ESRCH; |
366 |
|
|
367 |
if (p->p_pgrp) |
if (p->p_pgrp) |
368 |
*pgid = p->p_pgrp->pg_pgid; |
*pgid = p->p_pgrp->pg_pgid; |
369 |
|
|
370 |
return 0; |
return 0; |
371 |
} |
} |
372 |
|
|
392 |
*p->p_gprevp = p->p_gnext; |
*p->p_gprevp = p->p_gnext; |
393 |
if (p->p_gnext) |
if (p->p_gnext) |
394 |
p->p_gnext->p_gprevp = p->p_gprevp; |
p->p_gnext->p_gprevp = p->p_gprevp; |
395 |
|
|
396 |
/* If we were the last member of our pgrp, free it */ |
/* If we were the last member of our pgrp, free it */ |
397 |
if (!pg->pg_plist) |
if (!pg->pg_plist) |
398 |
free_pgrp (pg); |
free_pgrp (pg); |
404 |
an orphaned process group -- do the orphaning gook */ |
an orphaned process group -- do the orphaning gook */ |
405 |
struct proc *ip; |
struct proc *ip; |
406 |
int dosignal = 0; |
int dosignal = 0; |
407 |
|
|
408 |
for (ip = pg->pg_plist; ip; ip = ip->p_gnext) |
for (ip = pg->pg_plist; ip; ip = ip->p_gnext) |
409 |
{ |
{ |
410 |
if (ip->p_stopped) |
if (ip->p_stopped) |
435 |
if (pg->pg_plist) |
if (pg->pg_plist) |
436 |
pg->pg_plist->p_gprevp = &p->p_gnext; |
pg->pg_plist->p_gprevp = &p->p_gnext; |
437 |
pg->pg_plist = p; |
pg->pg_plist = p; |
438 |
|
|
439 |
origorphcnt = !!pg->pg_orphcnt; |
origorphcnt = !!pg->pg_orphcnt; |
440 |
if (p->p_parent->p_pgrp != pg |
if (p->p_parent->p_pgrp != pg |
441 |
&& p->p_parent->p_pgrp->pg_session == pg->pg_session) |
&& p->p_parent->p_pgrp->pg_session == pg->pg_session) |