1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1991, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 6df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 7df8bae1dSRodney W. Grimes * are met: 8df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 9df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 10df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 11df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 12df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 13df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 14df8bae1dSRodney W. Grimes * must display the following acknowledgement: 15df8bae1dSRodney W. Grimes * This product includes software developed by the University of 16df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 17df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 18df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 19df8bae1dSRodney W. Grimes * without specific prior written permission. 20df8bae1dSRodney W. Grimes * 21df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31df8bae1dSRodney W. Grimes * SUCH DAMAGE. 32df8bae1dSRodney W. Grimes * 33b75356e1SJeffrey Hsu * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95 34c3aac50fSPeter Wemm * $FreeBSD$ 35df8bae1dSRodney W. Grimes */ 36df8bae1dSRodney W. Grimes 37df8bae1dSRodney W. Grimes #include <sys/param.h> 38df8bae1dSRodney W. Grimes #include <sys/systm.h> 39df8bae1dSRodney W. Grimes #include <sys/kernel.h> 40fb919e4dSMark Murray #include <sys/lock.h> 41df8bae1dSRodney W. Grimes #include <sys/malloc.h> 42fb919e4dSMark Murray #include <sys/mutex.h> 43b9df5231SPoul-Henning Kamp #include <sys/proc.h> 44fb919e4dSMark Murray #include <sys/sysctl.h> 4562d6ce3aSDon Lewis #include <sys/filedesc.h> 46df8bae1dSRodney W. Grimes #include <sys/tty.h> 47bb56ec4aSPoul-Henning Kamp #include <sys/signalvar.h> 481005a129SJohn Baldwin #include <sys/sx.h> 49fb919e4dSMark Murray #include <sys/user.h> 50fb919e4dSMark Murray #include <sys/jail.h> 51fb919e4dSMark Murray 52efeaf95aSDavid Greenman #include <vm/vm.h> 53efeaf95aSDavid Greenman #include <vm/pmap.h> 54efeaf95aSDavid Greenman #include <vm/vm_map.h> 552d8acc0fSJohn Dyson #include <vm/vm_zone.h> 56df8bae1dSRodney W. Grimes 57a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header"); 58a1c995b6SPoul-Henning Kamp MALLOC_DEFINE(M_SESSION, "session", "session header"); 59876a94eeSBruce Evans static MALLOC_DEFINE(M_PROC, "proc", "Proc structures"); 60a1c995b6SPoul-Henning Kamp MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures"); 6155166637SPoul-Henning Kamp 6287b6de2bSPoul-Henning Kamp static void pgdelete __P((struct pgrp *)); 6326f9a767SRodney W. Grimes 6498d93822SBruce Evans static void orphanpg __P((struct pgrp *pg)); 6598d93822SBruce Evans 66df8bae1dSRodney W. Grimes /* 67b75356e1SJeffrey Hsu * Other process lists 68b75356e1SJeffrey Hsu */ 69b75356e1SJeffrey Hsu struct pidhashhead *pidhashtbl; 70b75356e1SJeffrey Hsu u_long pidhash; 71b75356e1SJeffrey Hsu struct pgrphashhead *pgrphashtbl; 72b75356e1SJeffrey Hsu u_long pgrphash; 73b75356e1SJeffrey Hsu struct proclist allproc; 74b75356e1SJeffrey Hsu struct proclist zombproc; 751005a129SJohn Baldwin struct sx allproc_lock; 761005a129SJohn Baldwin struct sx proctree_lock; 772d8acc0fSJohn Dyson vm_zone_t proc_zone; 780384fff8SJason Evans vm_zone_t ithread_zone; 79b75356e1SJeffrey Hsu 80b75356e1SJeffrey Hsu /* 81b75356e1SJeffrey Hsu * Initialize global process hashing structures. 82df8bae1dSRodney W. Grimes */ 8326f9a767SRodney W. Grimes void 84b75356e1SJeffrey Hsu procinit() 85df8bae1dSRodney W. Grimes { 86393d77ffSKirk McKusick int i, j; 87df8bae1dSRodney W. Grimes 881005a129SJohn Baldwin sx_init(&allproc_lock, "allproc"); 891005a129SJohn Baldwin sx_init(&proctree_lock, "proctree"); 90b75356e1SJeffrey Hsu LIST_INIT(&allproc); 91b75356e1SJeffrey Hsu LIST_INIT(&zombproc); 92b75356e1SJeffrey Hsu pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); 93b75356e1SJeffrey Hsu pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); 942d8acc0fSJohn Dyson proc_zone = zinit("PROC", sizeof (struct proc), 0, 0, 5); 95f535380cSDon Lewis uihashinit(); 961f7d2501SKirk McKusick /* 971f7d2501SKirk McKusick * This should really be a compile time warning, but I do 981f7d2501SKirk McKusick * not know of any way to do that... 991f7d2501SKirk McKusick */ 100393d77ffSKirk McKusick if (sizeof(struct kinfo_proc) != KINFO_PROC_SIZE) { 101393d77ffSKirk McKusick printf("This message will repeat for the next 20 seconds\n"); 102393d77ffSKirk McKusick for (i = 0; i < 20; i++) { 1031aa97cdeSJohn Baldwin printf("WARNING: size of kinfo_proc (%ld) should be %d!!!\n", 1041aa97cdeSJohn Baldwin (long)sizeof(struct kinfo_proc), KINFO_PROC_SIZE); 105393d77ffSKirk McKusick printf("The kinfo_proc structure was changed "); 106393d77ffSKirk McKusick printf("incorrectly in <sys/user.h>\n"); 107393d77ffSKirk McKusick for (j = 0; j < 0x7ffffff; j++); 108393d77ffSKirk McKusick } 109393d77ffSKirk McKusick 110393d77ffSKirk McKusick } 111df8bae1dSRodney W. Grimes } 112df8bae1dSRodney W. Grimes 113df8bae1dSRodney W. Grimes /* 114b40ce416SJulian Elischer * link up a process structure and it's inbuilt threads etc. 115b40ce416SJulian Elischer */ 116b40ce416SJulian Elischer void 117b40ce416SJulian Elischer proc_linkup(struct proc *p) 118b40ce416SJulian Elischer { 119b40ce416SJulian Elischer struct thread *td; 120b40ce416SJulian Elischer 121b40ce416SJulian Elischer td = &p->p_thread; 122b40ce416SJulian Elischer 123b40ce416SJulian Elischer /**** lists headed in the proc structure ****/ 124b40ce416SJulian Elischer /* ALL KSEGRPs in this process */ 125b40ce416SJulian Elischer TAILQ_INIT( &p->p_ksegrps); /* all ksegrps in proc */ 126b40ce416SJulian Elischer TAILQ_INSERT_HEAD(&p->p_ksegrps, &p->p_ksegrp, kg_ksegrp); 127b40ce416SJulian Elischer 128b40ce416SJulian Elischer /* All threads in this process (an optimisation) */ 129b40ce416SJulian Elischer TAILQ_INIT( &p->p_threads); /* all threads in proc */ 130b40ce416SJulian Elischer TAILQ_INSERT_HEAD(&p->p_threads, &p->p_thread, td_plist); 131b40ce416SJulian Elischer 132b40ce416SJulian Elischer /**** Lists headed in the KSEGROUP structure ****/ 133b40ce416SJulian Elischer /* all thread in this ksegroup */ 134b40ce416SJulian Elischer TAILQ_INIT( &p->p_ksegrp.kg_threads); 135b40ce416SJulian Elischer TAILQ_INSERT_HEAD(&p->p_ksegrp.kg_threads, &p->p_thread, td_kglist); 136b40ce416SJulian Elischer 137b40ce416SJulian Elischer /* All runnable threads not assigned to a particular KSE */ 138b40ce416SJulian Elischer /* XXXKSE THIS MAY GO AWAY.. KSEs are never unassigned */ 139b40ce416SJulian Elischer TAILQ_INIT( &p->p_ksegrp.kg_runq); /* links with td_runq */ 140b40ce416SJulian Elischer 141b40ce416SJulian Elischer /* All threads presently not runnable (Thread starts this way) */ 142b40ce416SJulian Elischer TAILQ_INIT( &p->p_ksegrp.kg_slpq); /* links with td_runq */ 143b40ce416SJulian Elischer TAILQ_INSERT_HEAD(&p->p_ksegrp.kg_slpq, &p->p_thread, td_runq); 144b40ce416SJulian Elischer /*p->p_thread.td_flags &= ~TDF_ONRUNQ;*/ 145b40ce416SJulian Elischer 146b40ce416SJulian Elischer /* all KSEs in this ksegroup */ 147b40ce416SJulian Elischer TAILQ_INIT( &p->p_ksegrp.kg_kseq); /* all kses in ksegrp */ 148b40ce416SJulian Elischer TAILQ_INSERT_HEAD(&p->p_ksegrp.kg_kseq, &p->p_kse, ke_kglist); 149b40ce416SJulian Elischer 150b40ce416SJulian Elischer /* KSE starts out idle *//* XXXKSE */ 151b40ce416SJulian Elischer TAILQ_INIT( &p->p_ksegrp.kg_rq); /* all kses in ksegrp */ 152b40ce416SJulian Elischer TAILQ_INIT( &p->p_ksegrp.kg_iq); /* all kses in ksegrp */ 153b40ce416SJulian Elischer #if 0 154b40ce416SJulian Elischer TAILQ_INSERT_HEAD(&p->p_ksegrp.kg_iq, &p->p_kse, ke_kgrlist); 155b40ce416SJulian Elischer #endif /* is running, not idle */ 156b40ce416SJulian Elischer /*p->p_kse.ke_flags &= &KEF_ONRUNQ;*/ 157b40ce416SJulian Elischer 158b40ce416SJulian Elischer /**** Lists headed in the KSE structure ****/ 159b40ce416SJulian Elischer /* runnable threads assigned to this kse */ 160b40ce416SJulian Elischer TAILQ_INIT( &p->p_kse.ke_runq); /* links with td_runq */ 161b40ce416SJulian Elischer 162b40ce416SJulian Elischer p->p_thread.td_proc = p; 163b40ce416SJulian Elischer p->p_kse.ke_proc = p; 164b40ce416SJulian Elischer p->p_ksegrp.kg_proc = p; 165b40ce416SJulian Elischer 166b40ce416SJulian Elischer p->p_thread.td_ksegrp = &p->p_ksegrp; 167b40ce416SJulian Elischer p->p_kse.ke_ksegrp = &p->p_ksegrp; 168b40ce416SJulian Elischer 169b40ce416SJulian Elischer p->p_thread.td_last_kse = &p->p_kse; 170b40ce416SJulian Elischer p->p_thread.td_kse = &p->p_kse; 171b40ce416SJulian Elischer 172b40ce416SJulian Elischer p->p_kse.ke_thread = &p->p_thread; 173b40ce416SJulian Elischer 174b40ce416SJulian Elischer p->p_ksegrp.kg_runnable = 1; 175b40ce416SJulian Elischer p->p_ksegrp.kg_kses = 1; 176b40ce416SJulian Elischer p->p_ksegrp.kg_runq_kses = 1; /* XXXKSE change name */ 177b40ce416SJulian Elischer } 178b40ce416SJulian Elischer 179b40ce416SJulian Elischer /* 180df8bae1dSRodney W. Grimes * Is p an inferior of the current process? 181df8bae1dSRodney W. Grimes */ 1821a432a2fSDima Ruban int 183df8bae1dSRodney W. Grimes inferior(p) 184df8bae1dSRodney W. Grimes register struct proc *p; 185df8bae1dSRodney W. Grimes { 1865b29d6e9SJohn Baldwin int rval = 1; 187df8bae1dSRodney W. Grimes 1885b29d6e9SJohn Baldwin sx_assert(&proctree_lock, SX_LOCKED); 1895b29d6e9SJohn Baldwin for (; p != curproc; p = p->p_pptr) 1905b29d6e9SJohn Baldwin if (p->p_pid == 0) { 1915b29d6e9SJohn Baldwin rval = 0; 1925b29d6e9SJohn Baldwin break; 1935b29d6e9SJohn Baldwin } 19498f03f90SJake Burkholder return (rval); 195df8bae1dSRodney W. Grimes } 196df8bae1dSRodney W. Grimes 197df8bae1dSRodney W. Grimes /* 198df8bae1dSRodney W. Grimes * Locate a process by number 199df8bae1dSRodney W. Grimes */ 200df8bae1dSRodney W. Grimes struct proc * 201df8bae1dSRodney W. Grimes pfind(pid) 202df8bae1dSRodney W. Grimes register pid_t pid; 203df8bae1dSRodney W. Grimes { 204df8bae1dSRodney W. Grimes register struct proc *p; 205df8bae1dSRodney W. Grimes 2061005a129SJohn Baldwin sx_slock(&allproc_lock); 2071b727751SPoul-Henning Kamp LIST_FOREACH(p, PIDHASH(pid), p_hash) 20833a9ed9dSJohn Baldwin if (p->p_pid == pid) { 20933a9ed9dSJohn Baldwin PROC_LOCK(p); 210553629ebSJake Burkholder break; 21133a9ed9dSJohn Baldwin } 2121005a129SJohn Baldwin sx_sunlock(&allproc_lock); 213df8bae1dSRodney W. Grimes return (p); 214df8bae1dSRodney W. Grimes } 215df8bae1dSRodney W. Grimes 216df8bae1dSRodney W. Grimes /* 217df8bae1dSRodney W. Grimes * Locate a process group by number 218df8bae1dSRodney W. Grimes */ 219df8bae1dSRodney W. Grimes struct pgrp * 220df8bae1dSRodney W. Grimes pgfind(pgid) 221df8bae1dSRodney W. Grimes register pid_t pgid; 222df8bae1dSRodney W. Grimes { 223df8bae1dSRodney W. Grimes register struct pgrp *pgrp; 224df8bae1dSRodney W. Grimes 2251b727751SPoul-Henning Kamp LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) 226df8bae1dSRodney W. Grimes if (pgrp->pg_id == pgid) 227df8bae1dSRodney W. Grimes return (pgrp); 228df8bae1dSRodney W. Grimes return (NULL); 229df8bae1dSRodney W. Grimes } 230df8bae1dSRodney W. Grimes 231df8bae1dSRodney W. Grimes /* 232df8bae1dSRodney W. Grimes * Move p to a new or existing process group (and session) 233df8bae1dSRodney W. Grimes */ 23426f9a767SRodney W. Grimes int 235df8bae1dSRodney W. Grimes enterpgrp(p, pgid, mksess) 236df8bae1dSRodney W. Grimes register struct proc *p; 237df8bae1dSRodney W. Grimes pid_t pgid; 238df8bae1dSRodney W. Grimes int mksess; 239df8bae1dSRodney W. Grimes { 240df8bae1dSRodney W. Grimes register struct pgrp *pgrp = pgfind(pgid); 24115e9ec51SJohn Baldwin struct pgrp *savegrp; 242df8bae1dSRodney W. Grimes 2435526d2d9SEivind Eklund KASSERT(pgrp == NULL || !mksess, 2445526d2d9SEivind Eklund ("enterpgrp: setsid into non-empty pgrp")); 2455526d2d9SEivind Eklund KASSERT(!SESS_LEADER(p), 2465526d2d9SEivind Eklund ("enterpgrp: session leader attempted setpgrp")); 247219cbf59SEivind Eklund 248df8bae1dSRodney W. Grimes if (pgrp == NULL) { 249df8bae1dSRodney W. Grimes pid_t savepid = p->p_pid; 250df8bae1dSRodney W. Grimes struct proc *np; 251df8bae1dSRodney W. Grimes /* 252df8bae1dSRodney W. Grimes * new process group 253df8bae1dSRodney W. Grimes */ 2545526d2d9SEivind Eklund KASSERT(p->p_pid == pgid, 2555526d2d9SEivind Eklund ("enterpgrp: new pgrp and pid != pgid")); 25633a9ed9dSJohn Baldwin if ((np = pfind(savepid)) == NULL || np != p) { 25733a9ed9dSJohn Baldwin if (np != NULL) 25833a9ed9dSJohn Baldwin PROC_UNLOCK(np); 259df8bae1dSRodney W. Grimes return (ESRCH); 26033a9ed9dSJohn Baldwin } 26133a9ed9dSJohn Baldwin PROC_UNLOCK(np); 262d1cadeb0SDavid Malone MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 263d1cadeb0SDavid Malone M_WAITOK); 264df8bae1dSRodney W. Grimes if (mksess) { 265df8bae1dSRodney W. Grimes register struct session *sess; 266df8bae1dSRodney W. Grimes 267df8bae1dSRodney W. Grimes /* 268df8bae1dSRodney W. Grimes * new session 269df8bae1dSRodney W. Grimes */ 270df8bae1dSRodney W. Grimes MALLOC(sess, struct session *, sizeof(struct session), 271df8bae1dSRodney W. Grimes M_SESSION, M_WAITOK); 272df8bae1dSRodney W. Grimes sess->s_leader = p; 273643a8daaSDon Lewis sess->s_sid = p->p_pid; 274df8bae1dSRodney W. Grimes sess->s_count = 1; 275df8bae1dSRodney W. Grimes sess->s_ttyvp = NULL; 276df8bae1dSRodney W. Grimes sess->s_ttyp = NULL; 277df8bae1dSRodney W. Grimes bcopy(p->p_session->s_login, sess->s_login, 278df8bae1dSRodney W. Grimes sizeof(sess->s_login)); 27915e9ec51SJohn Baldwin PROC_LOCK(p); 280df8bae1dSRodney W. Grimes p->p_flag &= ~P_CONTROLT; 28115e9ec51SJohn Baldwin PROC_UNLOCK(p); 282df8bae1dSRodney W. Grimes pgrp->pg_session = sess; 2835526d2d9SEivind Eklund KASSERT(p == curproc, 2845526d2d9SEivind Eklund ("enterpgrp: mksession and p != curproc")); 285df8bae1dSRodney W. Grimes } else { 286df8bae1dSRodney W. Grimes pgrp->pg_session = p->p_session; 287df8bae1dSRodney W. Grimes pgrp->pg_session->s_count++; 288df8bae1dSRodney W. Grimes } 289df8bae1dSRodney W. Grimes pgrp->pg_id = pgid; 290b75356e1SJeffrey Hsu LIST_INIT(&pgrp->pg_members); 291b75356e1SJeffrey Hsu LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); 292df8bae1dSRodney W. Grimes pgrp->pg_jobc = 0; 293831d27a9SDon Lewis SLIST_INIT(&pgrp->pg_sigiolst); 294df8bae1dSRodney W. Grimes } else if (pgrp == p->p_pgrp) 295df8bae1dSRodney W. Grimes return (0); 296df8bae1dSRodney W. Grimes 297df8bae1dSRodney W. Grimes /* 298df8bae1dSRodney W. Grimes * Adjust eligibility of affected pgrps to participate in job control. 299df8bae1dSRodney W. Grimes * Increment eligibility counts before decrementing, otherwise we 300df8bae1dSRodney W. Grimes * could reach 0 spuriously during the first call. 301df8bae1dSRodney W. Grimes */ 302df8bae1dSRodney W. Grimes fixjobc(p, pgrp, 1); 303df8bae1dSRodney W. Grimes fixjobc(p, p->p_pgrp, 0); 304df8bae1dSRodney W. Grimes 30515e9ec51SJohn Baldwin PROC_LOCK(p); 306b75356e1SJeffrey Hsu LIST_REMOVE(p, p_pglist); 30715e9ec51SJohn Baldwin savegrp = p->p_pgrp; 308df8bae1dSRodney W. Grimes p->p_pgrp = pgrp; 309b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); 31015e9ec51SJohn Baldwin PROC_UNLOCK(p); 31115e9ec51SJohn Baldwin if (LIST_EMPTY(&savegrp->pg_members)) 31215e9ec51SJohn Baldwin pgdelete(savegrp); 313df8bae1dSRodney W. Grimes return (0); 314df8bae1dSRodney W. Grimes } 315df8bae1dSRodney W. Grimes 316df8bae1dSRodney W. Grimes /* 317df8bae1dSRodney W. Grimes * remove process from process group 318df8bae1dSRodney W. Grimes */ 31926f9a767SRodney W. Grimes int 320df8bae1dSRodney W. Grimes leavepgrp(p) 321df8bae1dSRodney W. Grimes register struct proc *p; 322df8bae1dSRodney W. Grimes { 32315e9ec51SJohn Baldwin struct pgrp *savegrp; 324df8bae1dSRodney W. Grimes 32515e9ec51SJohn Baldwin PROC_LOCK(p); 326b75356e1SJeffrey Hsu LIST_REMOVE(p, p_pglist); 32715e9ec51SJohn Baldwin savegrp = p->p_pgrp; 32815e9ec51SJohn Baldwin p->p_pgrp = NULL; 32915e9ec51SJohn Baldwin PROC_UNLOCK(p); 33015e9ec51SJohn Baldwin if (LIST_EMPTY(&savegrp->pg_members)) 33115e9ec51SJohn Baldwin pgdelete(savegrp); 332df8bae1dSRodney W. Grimes return (0); 333df8bae1dSRodney W. Grimes } 334df8bae1dSRodney W. Grimes 335df8bae1dSRodney W. Grimes /* 336df8bae1dSRodney W. Grimes * delete a process group 337df8bae1dSRodney W. Grimes */ 33887b6de2bSPoul-Henning Kamp static void 339df8bae1dSRodney W. Grimes pgdelete(pgrp) 340df8bae1dSRodney W. Grimes register struct pgrp *pgrp; 341df8bae1dSRodney W. Grimes { 342df8bae1dSRodney W. Grimes 343831d27a9SDon Lewis /* 344831d27a9SDon Lewis * Reset any sigio structures pointing to us as a result of 345831d27a9SDon Lewis * F_SETOWN with our pgid. 346831d27a9SDon Lewis */ 347831d27a9SDon Lewis funsetownlst(&pgrp->pg_sigiolst); 348831d27a9SDon Lewis 349df8bae1dSRodney W. Grimes if (pgrp->pg_session->s_ttyp != NULL && 350df8bae1dSRodney W. Grimes pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 351df8bae1dSRodney W. Grimes pgrp->pg_session->s_ttyp->t_pgrp = NULL; 352b75356e1SJeffrey Hsu LIST_REMOVE(pgrp, pg_hash); 353df8bae1dSRodney W. Grimes if (--pgrp->pg_session->s_count == 0) 354df8bae1dSRodney W. Grimes FREE(pgrp->pg_session, M_SESSION); 355df8bae1dSRodney W. Grimes FREE(pgrp, M_PGRP); 356df8bae1dSRodney W. Grimes } 357df8bae1dSRodney W. Grimes 358df8bae1dSRodney W. Grimes /* 359df8bae1dSRodney W. Grimes * Adjust pgrp jobc counters when specified process changes process group. 360df8bae1dSRodney W. Grimes * We count the number of processes in each process group that "qualify" 361df8bae1dSRodney W. Grimes * the group for terminal job control (those with a parent in a different 362df8bae1dSRodney W. Grimes * process group of the same session). If that count reaches zero, the 363df8bae1dSRodney W. Grimes * process group becomes orphaned. Check both the specified process' 364df8bae1dSRodney W. Grimes * process group and that of its children. 365df8bae1dSRodney W. Grimes * entering == 0 => p is leaving specified group. 366df8bae1dSRodney W. Grimes * entering == 1 => p is entering specified group. 367df8bae1dSRodney W. Grimes */ 36826f9a767SRodney W. Grimes void 369df8bae1dSRodney W. Grimes fixjobc(p, pgrp, entering) 370df8bae1dSRodney W. Grimes register struct proc *p; 371df8bae1dSRodney W. Grimes register struct pgrp *pgrp; 372df8bae1dSRodney W. Grimes int entering; 373df8bae1dSRodney W. Grimes { 374df8bae1dSRodney W. Grimes register struct pgrp *hispgrp; 375df8bae1dSRodney W. Grimes register struct session *mysession = pgrp->pg_session; 376df8bae1dSRodney W. Grimes 377df8bae1dSRodney W. Grimes /* 378df8bae1dSRodney W. Grimes * Check p's parent to see whether p qualifies its own process 379df8bae1dSRodney W. Grimes * group; if so, adjust count for p's process group. 380df8bae1dSRodney W. Grimes */ 3811005a129SJohn Baldwin sx_slock(&proctree_lock); 382df8bae1dSRodney W. Grimes if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 383dfd5dee1SPeter Wemm hispgrp->pg_session == mysession) { 384df8bae1dSRodney W. Grimes if (entering) 385df8bae1dSRodney W. Grimes pgrp->pg_jobc++; 386df8bae1dSRodney W. Grimes else if (--pgrp->pg_jobc == 0) 387df8bae1dSRodney W. Grimes orphanpg(pgrp); 388dfd5dee1SPeter Wemm } 389df8bae1dSRodney W. Grimes 390df8bae1dSRodney W. Grimes /* 391df8bae1dSRodney W. Grimes * Check this process' children to see whether they qualify 392df8bae1dSRodney W. Grimes * their process groups; if so, adjust counts for children's 393df8bae1dSRodney W. Grimes * process groups. 394df8bae1dSRodney W. Grimes */ 3951b727751SPoul-Henning Kamp LIST_FOREACH(p, &p->p_children, p_sibling) 396df8bae1dSRodney W. Grimes if ((hispgrp = p->p_pgrp) != pgrp && 397df8bae1dSRodney W. Grimes hispgrp->pg_session == mysession && 398dfd5dee1SPeter Wemm p->p_stat != SZOMB) { 399df8bae1dSRodney W. Grimes if (entering) 400df8bae1dSRodney W. Grimes hispgrp->pg_jobc++; 401df8bae1dSRodney W. Grimes else if (--hispgrp->pg_jobc == 0) 402df8bae1dSRodney W. Grimes orphanpg(hispgrp); 403df8bae1dSRodney W. Grimes } 4041005a129SJohn Baldwin sx_sunlock(&proctree_lock); 405dfd5dee1SPeter Wemm } 406df8bae1dSRodney W. Grimes 407df8bae1dSRodney W. Grimes /* 408df8bae1dSRodney W. Grimes * A process group has become orphaned; 409df8bae1dSRodney W. Grimes * if there are any stopped processes in the group, 410df8bae1dSRodney W. Grimes * hang-up all process in that group. 411df8bae1dSRodney W. Grimes */ 412df8bae1dSRodney W. Grimes static void 413df8bae1dSRodney W. Grimes orphanpg(pg) 414df8bae1dSRodney W. Grimes struct pgrp *pg; 415df8bae1dSRodney W. Grimes { 416df8bae1dSRodney W. Grimes register struct proc *p; 417df8bae1dSRodney W. Grimes 41815e9ec51SJohn Baldwin mtx_lock_spin(&sched_lock); 4191b727751SPoul-Henning Kamp LIST_FOREACH(p, &pg->pg_members, p_pglist) { 420df8bae1dSRodney W. Grimes if (p->p_stat == SSTOP) { 42115e9ec51SJohn Baldwin mtx_unlock_spin(&sched_lock); 4221b727751SPoul-Henning Kamp LIST_FOREACH(p, &pg->pg_members, p_pglist) { 42315e9ec51SJohn Baldwin PROC_LOCK(p); 424df8bae1dSRodney W. Grimes psignal(p, SIGHUP); 425df8bae1dSRodney W. Grimes psignal(p, SIGCONT); 42615e9ec51SJohn Baldwin PROC_UNLOCK(p); 427df8bae1dSRodney W. Grimes } 428df8bae1dSRodney W. Grimes return; 429df8bae1dSRodney W. Grimes } 430df8bae1dSRodney W. Grimes } 43115e9ec51SJohn Baldwin mtx_unlock_spin(&sched_lock); 432df8bae1dSRodney W. Grimes } 433df8bae1dSRodney W. Grimes 434831031ceSBruce Evans #include "opt_ddb.h" 435831031ceSBruce Evans #ifdef DDB 436831031ceSBruce Evans #include <ddb/ddb.h> 437831031ceSBruce Evans 438831031ceSBruce Evans DB_SHOW_COMMAND(pgrpdump, pgrpdump) 439df8bae1dSRodney W. Grimes { 440df8bae1dSRodney W. Grimes register struct pgrp *pgrp; 441df8bae1dSRodney W. Grimes register struct proc *p; 442876a94eeSBruce Evans register int i; 443df8bae1dSRodney W. Grimes 444b75356e1SJeffrey Hsu for (i = 0; i <= pgrphash; i++) { 4451b727751SPoul-Henning Kamp if (!LIST_EMPTY(&pgrphashtbl[i])) { 446df8bae1dSRodney W. Grimes printf("\tindx %d\n", i); 4471b727751SPoul-Henning Kamp LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) { 448ac1e407bSBruce Evans printf( 449ac1e407bSBruce Evans "\tpgrp %p, pgid %ld, sess %p, sesscnt %d, mem %p\n", 450ac1e407bSBruce Evans (void *)pgrp, (long)pgrp->pg_id, 451ac1e407bSBruce Evans (void *)pgrp->pg_session, 452b75356e1SJeffrey Hsu pgrp->pg_session->s_count, 4531b727751SPoul-Henning Kamp (void *)LIST_FIRST(&pgrp->pg_members)); 4541b727751SPoul-Henning Kamp LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { 455ac1e407bSBruce Evans printf("\t\tpid %ld addr %p pgrp %p\n", 456ac1e407bSBruce Evans (long)p->p_pid, (void *)p, 457ac1e407bSBruce Evans (void *)p->p_pgrp); 458df8bae1dSRodney W. Grimes } 459df8bae1dSRodney W. Grimes } 460df8bae1dSRodney W. Grimes } 461df8bae1dSRodney W. Grimes } 462df8bae1dSRodney W. Grimes } 463831031ceSBruce Evans #endif /* DDB */ 464972f9b20SPoul-Henning Kamp 465972f9b20SPoul-Henning Kamp /* 4661f7d2501SKirk McKusick * Fill in an kinfo_proc structure for the specified process. 467972f9b20SPoul-Henning Kamp */ 468972f9b20SPoul-Henning Kamp void 4691f7d2501SKirk McKusick fill_kinfo_proc(p, kp) 4701f7d2501SKirk McKusick struct proc *p; 4711f7d2501SKirk McKusick struct kinfo_proc *kp; 472972f9b20SPoul-Henning Kamp { 473b40ce416SJulian Elischer struct thread *td; 4741f7d2501SKirk McKusick struct tty *tp; 4751f7d2501SKirk McKusick struct session *sp; 476972f9b20SPoul-Henning Kamp 4771f7d2501SKirk McKusick bzero(kp, sizeof(*kp)); 478972f9b20SPoul-Henning Kamp 4791f7d2501SKirk McKusick kp->ki_structsize = sizeof(*kp); 4801f7d2501SKirk McKusick kp->ki_paddr = p; 48142a4ed99SJohn Baldwin PROC_LOCK(p); 482b40ce416SJulian Elischer kp->ki_addr =/* p->p_addr; */0; /* XXXKSE */ 4831f7d2501SKirk McKusick kp->ki_args = p->p_args; 4841f7d2501SKirk McKusick kp->ki_tracep = p->p_tracep; 4851f7d2501SKirk McKusick kp->ki_textvp = p->p_textvp; 4861f7d2501SKirk McKusick kp->ki_fd = p->p_fd; 4871f7d2501SKirk McKusick kp->ki_vmspace = p->p_vmspace; 488b1fc0ec1SRobert Watson if (p->p_ucred) { 489b1fc0ec1SRobert Watson kp->ki_uid = p->p_ucred->cr_uid; 490b1fc0ec1SRobert Watson kp->ki_ruid = p->p_ucred->cr_ruid; 491b1fc0ec1SRobert Watson kp->ki_svuid = p->p_ucred->cr_svuid; 4920ecd57adSPeter Wemm /* XXX bde doesn't like KI_NGROUPS */ 4930ecd57adSPeter Wemm kp->ki_ngroups = min(p->p_ucred->cr_ngroups, KI_NGROUPS); 494b1fc0ec1SRobert Watson bcopy(p->p_ucred->cr_groups, kp->ki_groups, 4950ecd57adSPeter Wemm kp->ki_ngroups * sizeof(gid_t)); 496b1fc0ec1SRobert Watson kp->ki_rgid = p->p_ucred->cr_rgid; 497b1fc0ec1SRobert Watson kp->ki_svgid = p->p_ucred->cr_svgid; 498972f9b20SPoul-Henning Kamp } 499d8c85307SJulian Elischer if (p->p_procsig) { 5001f7d2501SKirk McKusick kp->ki_sigignore = p->p_procsig->ps_sigignore; 5011f7d2501SKirk McKusick kp->ki_sigcatch = p->p_procsig->ps_sigcatch; 502d8c85307SJulian Elischer } 5039ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 504972f9b20SPoul-Henning Kamp if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) { 5051f7d2501SKirk McKusick struct vmspace *vm = p->p_vmspace; 506cd73303cSDavid Greenman 5071f7d2501SKirk McKusick kp->ki_size = vm->vm_map.size; 5081f7d2501SKirk McKusick kp->ki_rssize = vmspace_resident_count(vm); /*XXX*/ 509e414d9aaSPeter Wemm if (p->p_sflag & PS_INMEM) 510b40ce416SJulian Elischer kp->ki_rssize += UAREA_PAGES; 511b40ce416SJulian Elischer FOREACH_THREAD_IN_PROC(p, td) /* XXXKSE: thread swapout check */ 512b40ce416SJulian Elischer kp->ki_rssize += KSTACK_PAGES; 5131f7d2501SKirk McKusick kp->ki_swrss = vm->vm_swrss; 5141f7d2501SKirk McKusick kp->ki_tsize = vm->vm_tsize; 5151f7d2501SKirk McKusick kp->ki_dsize = vm->vm_dsize; 5161f7d2501SKirk McKusick kp->ki_ssize = vm->vm_ssize; 5171f7d2501SKirk McKusick } 51842a4ed99SJohn Baldwin if ((p->p_sflag & PS_INMEM) && p->p_stats) { 5191f7d2501SKirk McKusick kp->ki_start = p->p_stats->p_start; 5201f7d2501SKirk McKusick kp->ki_rusage = p->p_stats->p_ru; 5211f7d2501SKirk McKusick kp->ki_childtime.tv_sec = p->p_stats->p_cru.ru_utime.tv_sec + 5221f7d2501SKirk McKusick p->p_stats->p_cru.ru_stime.tv_sec; 5231f7d2501SKirk McKusick kp->ki_childtime.tv_usec = p->p_stats->p_cru.ru_utime.tv_usec + 5241f7d2501SKirk McKusick p->p_stats->p_cru.ru_stime.tv_usec; 5251f7d2501SKirk McKusick } 526b40ce416SJulian Elischer if (p->p_thread.td_wmesg != NULL) 527b40ce416SJulian Elischer strncpy(kp->ki_wmesg, p->p_thread.td_wmesg, sizeof(kp->ki_wmesg) - 1); 52842a4ed99SJohn Baldwin if (p->p_stat == SMTX) { 52942a4ed99SJohn Baldwin kp->ki_kiflag |= KI_MTXBLOCK; 530b40ce416SJulian Elischer strncpy(kp->ki_mtxname, p->p_thread.td_mtxname, 53177330eebSPeter Wemm sizeof(kp->ki_mtxname) - 1); 53242a4ed99SJohn Baldwin } 53342a4ed99SJohn Baldwin kp->ki_stat = p->p_stat; 5346d3e7b9bSJohn Baldwin kp->ki_sflag = p->p_sflag; 53542a4ed99SJohn Baldwin kp->ki_swtime = p->p_swtime; 53642a4ed99SJohn Baldwin kp->ki_traceflag = p->p_traceflag; 5371f7d2501SKirk McKusick kp->ki_pid = p->p_pid; 538b40ce416SJulian Elischer /* vvv XXXKSE */ 539b40ce416SJulian Elischer kp->ki_runtime = p->p_runtime; 540b40ce416SJulian Elischer kp->ki_pctcpu = p->p_kse.ke_pctcpu; 541b40ce416SJulian Elischer kp->ki_estcpu = p->p_ksegrp.kg_estcpu; 542b40ce416SJulian Elischer kp->ki_slptime = p->p_ksegrp.kg_slptime; 543b40ce416SJulian Elischer kp->ki_wchan = p->p_thread.td_wchan; 544b40ce416SJulian Elischer kp->ki_pri = p->p_ksegrp.kg_pri; 545b40ce416SJulian Elischer kp->ki_nice = p->p_ksegrp.kg_nice; 546b40ce416SJulian Elischer kp->ki_rqindex = p->p_kse.ke_rqindex; 547b40ce416SJulian Elischer kp->ki_oncpu = p->p_kse.ke_oncpu; 548b40ce416SJulian Elischer kp->ki_lastcpu = p->p_thread.td_lastcpu; 549b40ce416SJulian Elischer kp->ki_tdflags = p->p_thread.td_flags; 550b40ce416SJulian Elischer kp->ki_pcb = p->p_thread.td_pcb; 551b40ce416SJulian Elischer kp->ki_kstack = (void *)p->p_thread.td_kstack; 552b40ce416SJulian Elischer /* ^^^ XXXKSE */ 5539ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 5541f7d2501SKirk McKusick sp = NULL; 5551f7d2501SKirk McKusick if (p->p_pgrp) { 5561f7d2501SKirk McKusick kp->ki_pgid = p->p_pgrp->pg_id; 5571f7d2501SKirk McKusick kp->ki_jobc = p->p_pgrp->pg_jobc; 5581f7d2501SKirk McKusick sp = p->p_pgrp->pg_session; 5591f7d2501SKirk McKusick 5601f7d2501SKirk McKusick if (sp != NULL) { 5611f7d2501SKirk McKusick kp->ki_sid = sp->s_sid; 56277330eebSPeter Wemm strncpy(kp->ki_login, sp->s_login, 56377330eebSPeter Wemm sizeof(kp->ki_login) - 1); 5641f7d2501SKirk McKusick if (sp->s_ttyvp) 5651f7d2501SKirk McKusick kp->ki_kiflag = KI_CTTY; 5661f7d2501SKirk McKusick if (SESS_LEADER(p)) 5671f7d2501SKirk McKusick kp->ki_kiflag |= KI_SLEADER; 568cd73303cSDavid Greenman } 569cd73303cSDavid Greenman } 5701f7d2501SKirk McKusick if ((p->p_flag & P_CONTROLT) && sp && ((tp = sp->s_ttyp) != NULL)) { 5711f7d2501SKirk McKusick kp->ki_tdev = dev2udev(tp->t_dev); 5721f7d2501SKirk McKusick kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 5731f7d2501SKirk McKusick if (tp->t_session) 5741f7d2501SKirk McKusick kp->ki_tsid = tp->t_session->s_sid; 575972f9b20SPoul-Henning Kamp } else 5761f7d2501SKirk McKusick kp->ki_tdev = NOUDEV; 57777330eebSPeter Wemm if (p->p_comm[0] != '\0') { 57877330eebSPeter Wemm strncpy(kp->ki_comm, p->p_comm, sizeof(kp->ki_comm) - 1); 57977330eebSPeter Wemm strncpy(kp->ki_ocomm, p->p_comm, sizeof(kp->ki_ocomm) - 1); 58062ca2477SJohn Baldwin } 5811f7d2501SKirk McKusick kp->ki_siglist = p->p_siglist; 5821f7d2501SKirk McKusick kp->ki_sigmask = p->p_sigmask; 5831f7d2501SKirk McKusick kp->ki_xstat = p->p_xstat; 5841f7d2501SKirk McKusick kp->ki_acflag = p->p_acflag; 5851f7d2501SKirk McKusick kp->ki_flag = p->p_flag; 58691421ba2SRobert Watson /* If jailed(p->p_ucred), emulate the old P_JAILED flag. */ 58791421ba2SRobert Watson if (jailed(p->p_ucred)) 58891421ba2SRobert Watson kp->ki_flag |= P_JAILED; 5891f7d2501SKirk McKusick kp->ki_lock = p->p_lock; 59042a4ed99SJohn Baldwin if (p->p_pptr) 59142a4ed99SJohn Baldwin kp->ki_ppid = p->p_pptr->p_pid; 59215e9ec51SJohn Baldwin PROC_UNLOCK(p); 593972f9b20SPoul-Henning Kamp } 594972f9b20SPoul-Henning Kamp 59542a4ed99SJohn Baldwin /* 59642a4ed99SJohn Baldwin * Locate a zombie process by number 59742a4ed99SJohn Baldwin */ 59842a4ed99SJohn Baldwin struct proc * 5993ce93e4eSPoul-Henning Kamp zpfind(pid_t pid) 6003ce93e4eSPoul-Henning Kamp { 6013ce93e4eSPoul-Henning Kamp struct proc *p; 6023ce93e4eSPoul-Henning Kamp 6031005a129SJohn Baldwin sx_slock(&allproc_lock); 6041b727751SPoul-Henning Kamp LIST_FOREACH(p, &zombproc, p_list) 60533a9ed9dSJohn Baldwin if (p->p_pid == pid) { 60633a9ed9dSJohn Baldwin PROC_LOCK(p); 607c0c25570SJake Burkholder break; 60833a9ed9dSJohn Baldwin } 6091005a129SJohn Baldwin sx_sunlock(&allproc_lock); 6103ce93e4eSPoul-Henning Kamp return (p); 6113ce93e4eSPoul-Henning Kamp } 6123ce93e4eSPoul-Henning Kamp 6133ce93e4eSPoul-Henning Kamp 6143ce93e4eSPoul-Henning Kamp static int 6153ce93e4eSPoul-Henning Kamp sysctl_out_proc(struct proc *p, struct sysctl_req *req, int doingzomb) 6163ce93e4eSPoul-Henning Kamp { 6171f7d2501SKirk McKusick struct kinfo_proc kinfo_proc; 6183ce93e4eSPoul-Henning Kamp int error; 61933a9ed9dSJohn Baldwin struct proc *np; 6203ce93e4eSPoul-Henning Kamp pid_t pid = p->p_pid; 6213ce93e4eSPoul-Henning Kamp 6221f7d2501SKirk McKusick fill_kinfo_proc(p, &kinfo_proc); 6231f7d2501SKirk McKusick error = SYSCTL_OUT(req, (caddr_t)&kinfo_proc, sizeof(kinfo_proc)); 6243ce93e4eSPoul-Henning Kamp if (error) 6253ce93e4eSPoul-Henning Kamp return (error); 62633a9ed9dSJohn Baldwin if (doingzomb) 62733a9ed9dSJohn Baldwin np = zpfind(pid); 62833a9ed9dSJohn Baldwin else { 62933a9ed9dSJohn Baldwin if (pid == 0) 63033a9ed9dSJohn Baldwin return (0); 63133a9ed9dSJohn Baldwin np = pfind(pid); 63233a9ed9dSJohn Baldwin } 63333a9ed9dSJohn Baldwin if (np == NULL) 6343ce93e4eSPoul-Henning Kamp return EAGAIN; 63533a9ed9dSJohn Baldwin if (np != p) { 63633a9ed9dSJohn Baldwin PROC_UNLOCK(np); 6373ce93e4eSPoul-Henning Kamp return EAGAIN; 63833a9ed9dSJohn Baldwin } 63933a9ed9dSJohn Baldwin PROC_UNLOCK(np); 6403ce93e4eSPoul-Henning Kamp return (0); 6413ce93e4eSPoul-Henning Kamp } 6423ce93e4eSPoul-Henning Kamp 643972f9b20SPoul-Henning Kamp static int 64482d9ae4eSPoul-Henning Kamp sysctl_kern_proc(SYSCTL_HANDLER_ARGS) 645972f9b20SPoul-Henning Kamp { 646972f9b20SPoul-Henning Kamp int *name = (int*) arg1; 647972f9b20SPoul-Henning Kamp u_int namelen = arg2; 648972f9b20SPoul-Henning Kamp struct proc *p; 649972f9b20SPoul-Henning Kamp int doingzomb; 650972f9b20SPoul-Henning Kamp int error = 0; 651972f9b20SPoul-Henning Kamp 6523ce93e4eSPoul-Henning Kamp if (oidp->oid_number == KERN_PROC_PID) { 6533ce93e4eSPoul-Henning Kamp if (namelen != 1) 654972f9b20SPoul-Henning Kamp return (EINVAL); 6553ce93e4eSPoul-Henning Kamp p = pfind((pid_t)name[0]); 6563ce93e4eSPoul-Henning Kamp if (!p) 6573ce93e4eSPoul-Henning Kamp return (0); 658a0f75161SRobert Watson if (p_cansee(curproc, p)) { 65933a9ed9dSJohn Baldwin PROC_UNLOCK(p); 66075c13541SPoul-Henning Kamp return (0); 66133a9ed9dSJohn Baldwin } 66233a9ed9dSJohn Baldwin PROC_UNLOCK(p); 6633ce93e4eSPoul-Henning Kamp error = sysctl_out_proc(p, req, 0); 6643ce93e4eSPoul-Henning Kamp return (error); 6653ce93e4eSPoul-Henning Kamp } 6663ce93e4eSPoul-Henning Kamp if (oidp->oid_number == KERN_PROC_ALL && !namelen) 6673ce93e4eSPoul-Henning Kamp ; 6683ce93e4eSPoul-Henning Kamp else if (oidp->oid_number != KERN_PROC_ALL && namelen == 1) 6693ce93e4eSPoul-Henning Kamp ; 6703ce93e4eSPoul-Henning Kamp else 6713ce93e4eSPoul-Henning Kamp return (EINVAL); 6723ce93e4eSPoul-Henning Kamp 673972f9b20SPoul-Henning Kamp if (!req->oldptr) { 6743ce93e4eSPoul-Henning Kamp /* overestimate by 5 procs */ 675972f9b20SPoul-Henning Kamp error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5); 676972f9b20SPoul-Henning Kamp if (error) 677972f9b20SPoul-Henning Kamp return (error); 678972f9b20SPoul-Henning Kamp } 6791005a129SJohn Baldwin sx_slock(&allproc_lock); 6803ce93e4eSPoul-Henning Kamp for (doingzomb=0 ; doingzomb < 2 ; doingzomb++) { 6813ce93e4eSPoul-Henning Kamp if (!doingzomb) 6821b727751SPoul-Henning Kamp p = LIST_FIRST(&allproc); 6833ce93e4eSPoul-Henning Kamp else 6841b727751SPoul-Henning Kamp p = LIST_FIRST(&zombproc); 6851b727751SPoul-Henning Kamp for (; p != 0; p = LIST_NEXT(p, p_list)) { 686972f9b20SPoul-Henning Kamp /* 687387d2c03SRobert Watson * Show a user only appropriate processes. 68803f808c5SPaul Saab */ 689a0f75161SRobert Watson if (p_cansee(curproc, p)) 69003f808c5SPaul Saab continue; 69103f808c5SPaul Saab /* 692972f9b20SPoul-Henning Kamp * Skip embryonic processes. 693972f9b20SPoul-Henning Kamp */ 694972f9b20SPoul-Henning Kamp if (p->p_stat == SIDL) 695972f9b20SPoul-Henning Kamp continue; 696972f9b20SPoul-Henning Kamp /* 697972f9b20SPoul-Henning Kamp * TODO - make more efficient (see notes below). 698972f9b20SPoul-Henning Kamp * do by session. 699972f9b20SPoul-Henning Kamp */ 7003ce93e4eSPoul-Henning Kamp switch (oidp->oid_number) { 701972f9b20SPoul-Henning Kamp 702972f9b20SPoul-Henning Kamp case KERN_PROC_PGRP: 703972f9b20SPoul-Henning Kamp /* could do this by traversing pgrp */ 7043ce93e4eSPoul-Henning Kamp if (p->p_pgrp == NULL || 7053ce93e4eSPoul-Henning Kamp p->p_pgrp->pg_id != (pid_t)name[0]) 706972f9b20SPoul-Henning Kamp continue; 707972f9b20SPoul-Henning Kamp break; 708972f9b20SPoul-Henning Kamp 709972f9b20SPoul-Henning Kamp case KERN_PROC_TTY: 710972f9b20SPoul-Henning Kamp if ((p->p_flag & P_CONTROLT) == 0 || 711972f9b20SPoul-Henning Kamp p->p_session == NULL || 712972f9b20SPoul-Henning Kamp p->p_session->s_ttyp == NULL || 71368f7448fSPoul-Henning Kamp dev2udev(p->p_session->s_ttyp->t_dev) != 71468f7448fSPoul-Henning Kamp (udev_t)name[0]) 715972f9b20SPoul-Henning Kamp continue; 716972f9b20SPoul-Henning Kamp break; 717972f9b20SPoul-Henning Kamp 718972f9b20SPoul-Henning Kamp case KERN_PROC_UID: 7193ce93e4eSPoul-Henning Kamp if (p->p_ucred == NULL || 7203ce93e4eSPoul-Henning Kamp p->p_ucred->cr_uid != (uid_t)name[0]) 721972f9b20SPoul-Henning Kamp continue; 722972f9b20SPoul-Henning Kamp break; 723972f9b20SPoul-Henning Kamp 724972f9b20SPoul-Henning Kamp case KERN_PROC_RUID: 7253ce93e4eSPoul-Henning Kamp if (p->p_ucred == NULL || 726b1fc0ec1SRobert Watson p->p_ucred->cr_ruid != (uid_t)name[0]) 727972f9b20SPoul-Henning Kamp continue; 728972f9b20SPoul-Henning Kamp break; 729972f9b20SPoul-Henning Kamp } 730972f9b20SPoul-Henning Kamp 731a0f75161SRobert Watson if (p_cansee(curproc, p)) 73275c13541SPoul-Henning Kamp continue; 73375c13541SPoul-Henning Kamp 7343ce93e4eSPoul-Henning Kamp error = sysctl_out_proc(p, req, doingzomb); 735553629ebSJake Burkholder if (error) { 7361005a129SJohn Baldwin sx_sunlock(&allproc_lock); 737972f9b20SPoul-Henning Kamp return (error); 738972f9b20SPoul-Henning Kamp } 739972f9b20SPoul-Henning Kamp } 740553629ebSJake Burkholder } 7411005a129SJohn Baldwin sx_sunlock(&allproc_lock); 742972f9b20SPoul-Henning Kamp return (0); 743972f9b20SPoul-Henning Kamp } 744972f9b20SPoul-Henning Kamp 745b9df5231SPoul-Henning Kamp /* 746b9df5231SPoul-Henning Kamp * This sysctl allows a process to retrieve the argument list or process 747b9df5231SPoul-Henning Kamp * title for another process without groping around in the address space 748b9df5231SPoul-Henning Kamp * of the other process. It also allow a process to set its own "process 749b9df5231SPoul-Henning Kamp * title to a string of its own choice. 750b9df5231SPoul-Henning Kamp */ 751b9df5231SPoul-Henning Kamp static int 75282d9ae4eSPoul-Henning Kamp sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) 753b9df5231SPoul-Henning Kamp { 754b9df5231SPoul-Henning Kamp int *name = (int*) arg1; 755b9df5231SPoul-Henning Kamp u_int namelen = arg2; 756b9df5231SPoul-Henning Kamp struct proc *p; 757b9df5231SPoul-Henning Kamp struct pargs *pa; 758b9df5231SPoul-Henning Kamp int error = 0; 759b9df5231SPoul-Henning Kamp 760b9df5231SPoul-Henning Kamp if (namelen != 1) 761b9df5231SPoul-Henning Kamp return (EINVAL); 762b9df5231SPoul-Henning Kamp 763b9df5231SPoul-Henning Kamp p = pfind((pid_t)name[0]); 764b9df5231SPoul-Henning Kamp if (!p) 765b9df5231SPoul-Henning Kamp return (0); 766b9df5231SPoul-Henning Kamp 767a0f75161SRobert Watson if ((!ps_argsopen) && p_cansee(curproc, p)) { 76833a9ed9dSJohn Baldwin PROC_UNLOCK(p); 769b9df5231SPoul-Henning Kamp return (0); 77033a9ed9dSJohn Baldwin } 77133a9ed9dSJohn Baldwin PROC_UNLOCK(p); 772b9df5231SPoul-Henning Kamp 773b9df5231SPoul-Henning Kamp if (req->newptr && curproc != p) 774b9df5231SPoul-Henning Kamp return (EPERM); 775b9df5231SPoul-Henning Kamp 776b9df5231SPoul-Henning Kamp if (req->oldptr && p->p_args != NULL) 777b9df5231SPoul-Henning Kamp error = SYSCTL_OUT(req, p->p_args->ar_args, p->p_args->ar_length); 778b9df5231SPoul-Henning Kamp if (req->newptr == NULL) 779b9df5231SPoul-Henning Kamp return (error); 780b9df5231SPoul-Henning Kamp 78133a9ed9dSJohn Baldwin PROC_LOCK(p); 782fbd26f75SJohn Baldwin pa = p->p_args; 783b9df5231SPoul-Henning Kamp p->p_args = NULL; 78415e9ec51SJohn Baldwin PROC_UNLOCK(p); 785fbd26f75SJohn Baldwin if (pa != NULL && --pa->ar_ref == 0) 786fbd26f75SJohn Baldwin FREE(pa, M_PARGS); 787b9df5231SPoul-Henning Kamp 788b9df5231SPoul-Henning Kamp if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) 789b9df5231SPoul-Henning Kamp return (error); 790b9df5231SPoul-Henning Kamp 791b9df5231SPoul-Henning Kamp MALLOC(pa, struct pargs *, sizeof(struct pargs) + req->newlen, 792b9df5231SPoul-Henning Kamp M_PARGS, M_WAITOK); 793b9df5231SPoul-Henning Kamp pa->ar_ref = 1; 794b9df5231SPoul-Henning Kamp pa->ar_length = req->newlen; 795b9df5231SPoul-Henning Kamp error = SYSCTL_IN(req, pa->ar_args, req->newlen); 79615e9ec51SJohn Baldwin if (!error) { 79715e9ec51SJohn Baldwin PROC_LOCK(p); 798b9df5231SPoul-Henning Kamp p->p_args = pa; 79915e9ec51SJohn Baldwin PROC_UNLOCK(p); 80015e9ec51SJohn Baldwin } else 801b9df5231SPoul-Henning Kamp FREE(pa, M_PARGS); 802b9df5231SPoul-Henning Kamp return (error); 803b9df5231SPoul-Henning Kamp } 8043ce93e4eSPoul-Henning Kamp 8053ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD, 0, "Process table"); 8063ce93e4eSPoul-Henning Kamp 8073ce93e4eSPoul-Henning Kamp SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT, 8083d177f46SBill Fumerola 0, 0, sysctl_kern_proc, "S,proc", "Return entire process table"); 8093ce93e4eSPoul-Henning Kamp 8103ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_PGRP, pgrp, CTLFLAG_RD, 8113ce93e4eSPoul-Henning Kamp sysctl_kern_proc, "Process table"); 8123ce93e4eSPoul-Henning Kamp 8133ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_TTY, tty, CTLFLAG_RD, 8143ce93e4eSPoul-Henning Kamp sysctl_kern_proc, "Process table"); 8153ce93e4eSPoul-Henning Kamp 8163ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_UID, uid, CTLFLAG_RD, 8173ce93e4eSPoul-Henning Kamp sysctl_kern_proc, "Process table"); 8183ce93e4eSPoul-Henning Kamp 8193ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_RUID, ruid, CTLFLAG_RD, 8203ce93e4eSPoul-Henning Kamp sysctl_kern_proc, "Process table"); 8213ce93e4eSPoul-Henning Kamp 8223ce93e4eSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_PID, pid, CTLFLAG_RD, 823972f9b20SPoul-Henning Kamp sysctl_kern_proc, "Process table"); 824b9df5231SPoul-Henning Kamp 8259b6d9dbaSPoul-Henning Kamp SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args, CTLFLAG_RW | CTLFLAG_ANYBODY, 8269b6d9dbaSPoul-Henning Kamp sysctl_kern_proc_args, "Process argument list"); 827