]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_proc.c
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94
58 * 04-Aug-97 Umesh Vaishampayan (umeshv@apple.com)
59 * Added current_proc_EXTERNAL() function for the use of kernel
62 * 05-Jun-95 Mac Gillon (mgillon) at NeXT
63 * New version based on 3.3NS and 4.4
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
75 #include <ufs/ufs/quota.h>
77 #include <sys/malloc.h>
79 #include <sys/ioctl.h>
81 #include <sys/signalvar.h>
82 #include <sys/syslog.h>
85 * Structure associated with user cacheing.
88 LIST_ENTRY(uidinfo
) ui_hash
;
92 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
93 LIST_HEAD(uihashhead
, uidinfo
) *uihashtbl
;
94 u_long uihash
; /* size of hash table - 1 */
99 struct pidhashhead
*pidhashtbl
;
101 struct pgrphashhead
*pgrphashtbl
;
103 struct proclist allproc
;
104 struct proclist zombproc
;
106 /* Name to give to core files */
107 __private_extern__
char corefilename
[MAXPATHLEN
+1] = {"/cores/core.%P"};
109 static void orphanpg(struct pgrp
*pg
);
112 * Initialize global process hashing structures.
119 LIST_INIT(&zombproc
);
120 pidhashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pidhash
);
121 pgrphashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pgrphash
);
122 uihashtbl
= hashinit(maxproc
/ 16, M_PROC
, &uihash
);
126 * Change the count associated with number of processes
127 * a given user is using.
130 chgproccnt(uid
, diff
)
134 register struct uidinfo
*uip
;
135 register struct uihashhead
*uipp
;
138 for (uip
= uipp
->lh_first
; uip
!= 0; uip
= uip
->ui_hash
.le_next
)
139 if (uip
->ui_uid
== uid
)
142 uip
->ui_proccnt
+= diff
;
143 if (uip
->ui_proccnt
> 0)
144 return (uip
->ui_proccnt
);
145 if (uip
->ui_proccnt
< 0)
146 panic("chgproccnt: procs < 0");
147 LIST_REMOVE(uip
, ui_hash
);
148 FREE_ZONE(uip
, sizeof *uip
, M_PROC
);
154 panic("chgproccnt: lost user");
156 MALLOC_ZONE(uip
, struct uidinfo
*, sizeof(*uip
), M_PROC
, M_WAITOK
);
157 LIST_INSERT_HEAD(uipp
, uip
, ui_hash
);
159 uip
->ui_proccnt
= diff
;
164 * Is p an inferior of the current process?
168 register struct proc
*p
;
171 for (; p
!= current_proc(); p
= p
->p_pptr
)
177 * Is p an inferior of t ?
180 isinferior(struct proc
*p
, register struct proc
*t
)
183 /* if p==t they are not inferior */
186 for (; p
!= t
; p
= p
->p_pptr
)
193 * Locate a process by number
199 register struct proc
*p
;
204 for (p
= PIDHASH(pid
)->lh_first
; p
!= 0; p
= p
->p_hash
.le_next
)
211 * Locate a zombie by PID
213 __private_extern__
struct proc
*
217 register struct proc
*p
;
219 for (p
= zombproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
)
226 * Locate a process group by number
232 register struct pgrp
*pgrp
;
234 for (pgrp
= PGRPHASH(pgid
)->lh_first
; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
)
235 if (pgrp
->pg_id
== pgid
)
242 * Move p to a new or existing process group (and session)
245 enterpgrp(p
, pgid
, mksess
)
246 register struct proc
*p
;
250 register struct pgrp
*pgrp
= pgfind(pgid
);
253 if (pgrp
!= NULL
&& mksess
) /* firewalls */
254 panic("enterpgrp: setsid into non-empty pgrp");
256 panic("enterpgrp: session leader attempted setpgrp");
259 pid_t savepid
= p
->p_pid
;
265 if (p
->p_pid
!= pgid
)
266 panic("enterpgrp: new pgrp and pid != pgid");
268 MALLOC_ZONE(pgrp
, struct pgrp
*, sizeof(struct pgrp
), M_PGRP
,
270 if ((np
= pfind(savepid
)) == NULL
|| np
!= p
) {
271 FREE_ZONE(pgrp
, sizeof(struct pgrp
), M_PGRP
);
275 register struct session
*sess
;
280 MALLOC_ZONE(sess
, struct session
*,
281 sizeof(struct session
), M_SESSION
, M_WAITOK
);
283 sess
->s_sid
= p
->p_pid
;
285 sess
->s_ttyvp
= NULL
;
287 bcopy(p
->p_session
->s_login
, sess
->s_login
,
288 sizeof(sess
->s_login
));
289 p
->p_flag
&= ~P_CONTROLT
;
290 pgrp
->pg_session
= sess
;
292 if (p
!= current_proc())
293 panic("enterpgrp: mksession and p != curproc");
296 pgrp
->pg_session
= p
->p_session
;
297 pgrp
->pg_session
->s_count
++;
300 LIST_INIT(&pgrp
->pg_members
);
301 LIST_INSERT_HEAD(PGRPHASH(pgid
), pgrp
, pg_hash
);
303 } else if (pgrp
== p
->p_pgrp
)
307 * Adjust eligibility of affected pgrps to participate in job control.
308 * Increment eligibility counts before decrementing, otherwise we
309 * could reach 0 spuriously during the first call.
312 fixjobc(p
, p
->p_pgrp
, 0);
314 LIST_REMOVE(p
, p_pglist
);
315 if (p
->p_pgrp
->pg_members
.lh_first
== 0)
318 LIST_INSERT_HEAD(&pgrp
->pg_members
, p
, p_pglist
);
323 * remove process from process group
327 register struct proc
*p
;
330 LIST_REMOVE(p
, p_pglist
);
331 if (p
->p_pgrp
->pg_members
.lh_first
== 0)
338 * delete a process group
342 register struct pgrp
*pgrp
;
345 if (pgrp
->pg_session
->s_ttyp
!= NULL
&&
346 pgrp
->pg_session
->s_ttyp
->t_pgrp
== pgrp
)
347 pgrp
->pg_session
->s_ttyp
->t_pgrp
= NULL
;
348 LIST_REMOVE(pgrp
, pg_hash
);
349 if (--pgrp
->pg_session
->s_count
== 0)
350 FREE_ZONE(pgrp
->pg_session
, sizeof(struct session
), M_SESSION
);
351 FREE_ZONE(pgrp
, sizeof *pgrp
, M_PGRP
);
356 struct session
*sess
;
358 if (--sess
->s_count
== 0)
359 FREE_ZONE(sess
, sizeof (struct session
), M_SESSION
);
363 * Adjust pgrp jobc counters when specified process changes process group.
364 * We count the number of processes in each process group that "qualify"
365 * the group for terminal job control (those with a parent in a different
366 * process group of the same session). If that count reaches zero, the
367 * process group becomes orphaned. Check both the specified process'
368 * process group and that of its children.
369 * entering == 0 => p is leaving specified group.
370 * entering == 1 => p is entering specified group.
373 fixjobc(struct proc
*p
, struct pgrp
*pgrp
, int entering
)
375 register struct pgrp
*hispgrp
;
376 register struct session
*mysession
= pgrp
->pg_session
;
379 * Check p's parent to see whether p qualifies its own process
380 * group; if so, adjust count for p's process group.
382 if ((hispgrp
= p
->p_pptr
->p_pgrp
) != pgrp
&&
383 hispgrp
->pg_session
== mysession
) {
386 else if (--pgrp
->pg_jobc
== 0)
391 * Check this process' children to see whether they qualify
392 * their process groups; if so, adjust counts for children's
395 for (p
= p
->p_children
.lh_first
; p
!= 0; p
= p
->p_sibling
.le_next
)
396 if ((hispgrp
= p
->p_pgrp
) != pgrp
&&
397 hispgrp
->pg_session
== mysession
&&
398 p
->p_stat
!= SZOMB
) {
401 else if (--hispgrp
->pg_jobc
== 0)
407 * A process group has become orphaned;
408 * if there are any stopped processes in the group,
409 * hang-up all process in that group.
412 orphanpg(struct pgrp
*pg
)
414 register struct proc
*p
;
416 for (p
= pg
->pg_members
.lh_first
; p
!= 0; p
= p
->p_pglist
.le_next
) {
417 if (p
->p_stat
== SSTOP
) {
418 for (p
= pg
->pg_members
.lh_first
; p
!= 0;
419 p
= p
->p_pglist
.le_next
) {
433 register struct pgrp
*pgrp
;
434 register struct proc
*p
;
437 for (i
= 0; i
<= pgrphash
; i
++) {
438 if (pgrp
= pgrphashtbl
[i
].lh_first
) {
439 printf("\tindx %d\n", i
);
440 for (; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
) {
441 printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n",
442 pgrp
, pgrp
->pg_id
, pgrp
->pg_session
,
443 pgrp
->pg_session
->s_count
,
444 pgrp
->pg_members
.lh_first
);
445 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
446 p
= p
->p_pglist
.le_next
) {
447 printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n",
448 p
->p_pid
, p
, p
->p_pgrp
);
456 /* XXX should be __private_extern__ */
458 proc_is_classic(struct proc
*p
)
460 return (p
->p_flag
& P_CLASSIC
) ? 1 : 0;
463 /* XXX Why does this function exist? Need to kill it off... */
465 current_proc_EXTERNAL(void)
467 return (current_proc());
471 * proc_core_name(name, uid, pid)
472 * Expand the name described in corefilename, using name, uid, and pid.
473 * corefilename is a printf-like string, with three format specifiers:
474 * %N name of process ("name")
475 * %P process id (pid)
477 * For example, "%N.core" is the default; they can be disabled completely
478 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
479 * This is controlled by the sysctl variable kern.corefile (see above).
481 __private_extern__
char *
482 proc_core_name(const char *name
, uid_t uid
, pid_t pid
)
484 const char *format
, *appendstr
;
486 char id_buf
[11]; /* Buffer for pid/uid -- max 4B */
489 format
= corefilename
;
490 MALLOC(temp
, char *, MAXPATHLEN
, M_TEMP
, M_NOWAIT
| M_ZERO
);
493 for (i
= 0, n
= 0; n
< MAXPATHLEN
&& format
[i
]; i
++) {
495 case '%': /* Format character */
501 case 'N': /* process name */
504 case 'P': /* process id */
505 sprintf(id_buf
, "%u", pid
);
508 case 'U': /* user id */
509 sprintf(id_buf
, "%u", uid
);
515 "Unknown format character %c in `%s'\n",
518 l
= strlen(appendstr
);
519 if ((n
+ l
) >= MAXPATHLEN
)
521 bcopy(appendstr
, temp
+ n
, l
);
525 temp
[n
++] = format
[i
];
528 if (format
[i
] != '\0')
532 log(LOG_ERR
, "pid %ld (%s), uid (%lu): corename is too long\n",
533 (long)pid
, name
, (u_long
)uid
);