|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1986, 1989, 1991, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95 ! 59: */ ! 60: ! 61: #include <sys/param.h> ! 62: #include <sys/systm.h> ! 63: #include <sys/kernel.h> ! 64: #include <sys/proc.h> ! 65: #include <sys/buf.h> ! 66: #include <sys/acct.h> ! 67: #include <sys/wait.h> ! 68: #include <sys/file.h> ! 69: #include <ufs/ufs/quota.h> ! 70: #include <sys/uio.h> ! 71: #include <sys/malloc.h> ! 72: #include <sys/mbuf.h> ! 73: #include <sys/ioctl.h> ! 74: #include <sys/tty.h> ! 75: #include <sys/signalvar.h> ! 76: ! 77: /* ! 78: * Structure associated with user cacheing. ! 79: */ ! 80: struct uidinfo { ! 81: LIST_ENTRY(uidinfo) ui_hash; ! 82: uid_t ui_uid; ! 83: long ui_proccnt; ! 84: }; ! 85: #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) ! 86: LIST_HEAD(uihashhead, uidinfo) *uihashtbl; ! 87: u_long uihash; /* size of hash table - 1 */ ! 88: ! 89: /* ! 90: * Other process lists ! 91: */ ! 92: struct pidhashhead *pidhashtbl; ! 93: u_long pidhash; ! 94: struct pgrphashhead *pgrphashtbl; ! 95: u_long pgrphash; ! 96: struct proclist allproc; ! 97: struct proclist zombproc; ! 98: ! 99: /* ! 100: * Initialize global process hashing structures. ! 101: */ ! 102: void ! 103: procinit() ! 104: { ! 105: ! 106: LIST_INIT(&allproc); ! 107: LIST_INIT(&zombproc); ! 108: pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); ! 109: pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); ! 110: uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); ! 111: } ! 112: ! 113: /* ! 114: * Change the count associated with number of processes ! 115: * a given user is using. ! 116: */ ! 117: int ! 118: chgproccnt(uid, diff) ! 119: uid_t uid; ! 120: int diff; ! 121: { ! 122: register struct uidinfo *uip; ! 123: register struct uihashhead *uipp; ! 124: ! 125: uipp = UIHASH(uid); ! 126: for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) ! 127: if (uip->ui_uid == uid) ! 128: break; ! 129: if (uip) { ! 130: uip->ui_proccnt += diff; ! 131: if (uip->ui_proccnt > 0) ! 132: return (uip->ui_proccnt); ! 133: if (uip->ui_proccnt < 0) ! 134: panic("chgproccnt: procs < 0"); ! 135: LIST_REMOVE(uip, ui_hash); ! 136: FREE_ZONE(uip, sizeof *uip, M_PROC); ! 137: return (0); ! 138: } ! 139: if (diff <= 0) { ! 140: if (diff == 0) ! 141: return(0); ! 142: panic("chgproccnt: lost user"); ! 143: } ! 144: MALLOC_ZONE(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); ! 145: LIST_INSERT_HEAD(uipp, uip, ui_hash); ! 146: uip->ui_uid = uid; ! 147: uip->ui_proccnt = diff; ! 148: return (diff); ! 149: } ! 150: ! 151: /* ! 152: * Is p an inferior of the current process? ! 153: */ ! 154: int ! 155: inferior(p) ! 156: register struct proc *p; ! 157: { ! 158: ! 159: for (; p != current_proc(); p = p->p_pptr) ! 160: if (p->p_pid == 0) ! 161: return (0); ! 162: return (1); ! 163: } ! 164: ! 165: /* ! 166: * Locate a process by number ! 167: */ ! 168: struct proc * ! 169: pfind(pid) ! 170: register pid_t pid; ! 171: { ! 172: register struct proc *p; ! 173: ! 174: if (!pid) ! 175: return (kernproc); ! 176: ! 177: for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) ! 178: if (p->p_pid == pid) ! 179: return (p); ! 180: return (NULL); ! 181: } ! 182: ! 183: /* ! 184: * Locate a process group by number ! 185: */ ! 186: struct pgrp * ! 187: pgfind(pgid) ! 188: register pid_t pgid; ! 189: { ! 190: register struct pgrp *pgrp; ! 191: ! 192: for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next) ! 193: if (pgrp->pg_id == pgid) ! 194: return (pgrp); ! 195: return (NULL); ! 196: } ! 197: ! 198: ! 199: /* ! 200: * Move p to a new or existing process group (and session) ! 201: */ ! 202: int ! 203: enterpgrp(p, pgid, mksess) ! 204: register struct proc *p; ! 205: pid_t pgid; ! 206: int mksess; ! 207: { ! 208: register struct pgrp *pgrp = pgfind(pgid); ! 209: ! 210: #if DIAGNOSTIC ! 211: if (pgrp != NULL && mksess) /* firewalls */ ! 212: panic("enterpgrp: setsid into non-empty pgrp"); ! 213: if (SESS_LEADER(p)) ! 214: panic("enterpgrp: session leader attempted setpgrp"); ! 215: #endif ! 216: if (pgrp == NULL) { ! 217: pid_t savepid = p->p_pid; ! 218: struct proc *np; ! 219: /* ! 220: * new process group ! 221: */ ! 222: #if DIAGNOSTIC ! 223: if (p->p_pid != pgid) ! 224: panic("enterpgrp: new pgrp and pid != pgid"); ! 225: #endif ! 226: MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, ! 227: M_WAITOK); ! 228: if ((np = pfind(savepid)) == NULL || np != p) ! 229: return (ESRCH); ! 230: if (mksess) { ! 231: register struct session *sess; ! 232: ! 233: /* ! 234: * new session ! 235: */ ! 236: MALLOC_ZONE(sess, struct session *, ! 237: sizeof(struct session), M_SESSION, M_WAITOK); ! 238: sess->s_leader = p; ! 239: sess->s_count = 1; ! 240: sess->s_ttyvp = NULL; ! 241: sess->s_ttyp = NULL; ! 242: bcopy(p->p_session->s_login, sess->s_login, ! 243: sizeof(sess->s_login)); ! 244: p->p_flag &= ~P_CONTROLT; ! 245: pgrp->pg_session = sess; ! 246: #if DIAGNOSTIC ! 247: if (p != current_proc()) ! 248: panic("enterpgrp: mksession and p != curproc"); ! 249: #endif ! 250: } else { ! 251: pgrp->pg_session = p->p_session; ! 252: pgrp->pg_session->s_count++; ! 253: } ! 254: pgrp->pg_id = pgid; ! 255: LIST_INIT(&pgrp->pg_members); ! 256: LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); ! 257: pgrp->pg_jobc = 0; ! 258: } else if (pgrp == p->p_pgrp) ! 259: return (0); ! 260: ! 261: /* ! 262: * Adjust eligibility of affected pgrps to participate in job control. ! 263: * Increment eligibility counts before decrementing, otherwise we ! 264: * could reach 0 spuriously during the first call. ! 265: */ ! 266: fixjobc(p, pgrp, 1); ! 267: fixjobc(p, p->p_pgrp, 0); ! 268: ! 269: LIST_REMOVE(p, p_pglist); ! 270: if (p->p_pgrp->pg_members.lh_first == 0) ! 271: pgdelete(p->p_pgrp); ! 272: p->p_pgrp = pgrp; ! 273: LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); ! 274: return (0); ! 275: } ! 276: ! 277: /* ! 278: * remove process from process group ! 279: */ ! 280: int ! 281: leavepgrp(p) ! 282: register struct proc *p; ! 283: { ! 284: ! 285: LIST_REMOVE(p, p_pglist); ! 286: if (p->p_pgrp->pg_members.lh_first == 0) ! 287: pgdelete(p->p_pgrp); ! 288: p->p_pgrp = 0; ! 289: return (0); ! 290: } ! 291: ! 292: /* ! 293: * delete a process group ! 294: */ ! 295: void ! 296: pgdelete(pgrp) ! 297: register struct pgrp *pgrp; ! 298: { ! 299: ! 300: if (pgrp->pg_session->s_ttyp != NULL && ! 301: pgrp->pg_session->s_ttyp->t_pgrp == pgrp) ! 302: pgrp->pg_session->s_ttyp->t_pgrp = NULL; ! 303: LIST_REMOVE(pgrp, pg_hash); ! 304: if (--pgrp->pg_session->s_count == 0) ! 305: FREE_ZONE(pgrp->pg_session, sizeof(struct session), M_SESSION); ! 306: FREE_ZONE(pgrp, sizeof *pgrp, M_PGRP); ! 307: } ! 308: ! 309: void ! 310: sessrele(sess) ! 311: struct session *sess; ! 312: { ! 313: if (--sess->s_count == 0) ! 314: FREE_ZONE(sess, sizeof (struct session), M_SESSION); ! 315: } ! 316: ! 317: static void orphanpg(); ! 318: ! 319: /* ! 320: * Adjust pgrp jobc counters when specified process changes process group. ! 321: * We count the number of processes in each process group that "qualify" ! 322: * the group for terminal job control (those with a parent in a different ! 323: * process group of the same session). If that count reaches zero, the ! 324: * process group becomes orphaned. Check both the specified process' ! 325: * process group and that of its children. ! 326: * entering == 0 => p is leaving specified group. ! 327: * entering == 1 => p is entering specified group. ! 328: */ ! 329: void ! 330: fixjobc(p, pgrp, entering) ! 331: register struct proc *p; ! 332: register struct pgrp *pgrp; ! 333: int entering; ! 334: { ! 335: register struct pgrp *hispgrp; ! 336: register struct session *mysession = pgrp->pg_session; ! 337: ! 338: /* ! 339: * Check p's parent to see whether p qualifies its own process ! 340: * group; if so, adjust count for p's process group. ! 341: */ ! 342: if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && ! 343: hispgrp->pg_session == mysession) ! 344: if (entering) ! 345: pgrp->pg_jobc++; ! 346: else if (--pgrp->pg_jobc == 0) ! 347: orphanpg(pgrp); ! 348: ! 349: /* ! 350: * Check this process' children to see whether they qualify ! 351: * their process groups; if so, adjust counts for children's ! 352: * process groups. ! 353: */ ! 354: for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) ! 355: if ((hispgrp = p->p_pgrp) != pgrp && ! 356: hispgrp->pg_session == mysession && ! 357: p->p_stat != SZOMB) ! 358: if (entering) ! 359: hispgrp->pg_jobc++; ! 360: else if (--hispgrp->pg_jobc == 0) ! 361: orphanpg(hispgrp); ! 362: } ! 363: ! 364: /* ! 365: * A process group has become orphaned; ! 366: * if there are any stopped processes in the group, ! 367: * hang-up all process in that group. ! 368: */ ! 369: static void ! 370: orphanpg(pg) ! 371: struct pgrp *pg; ! 372: { ! 373: register struct proc *p; ! 374: ! 375: for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { ! 376: if (p->p_stat == SSTOP) { ! 377: for (p = pg->pg_members.lh_first; p != 0; ! 378: p = p->p_pglist.le_next) { ! 379: psignal(p, SIGHUP); ! 380: psignal(p, SIGCONT); ! 381: } ! 382: return; ! 383: } ! 384: } ! 385: } ! 386: ! 387: #ifdef DEBUG ! 388: void ! 389: pgrpdump() ! 390: { ! 391: register struct pgrp *pgrp; ! 392: register struct proc *p; ! 393: register i; ! 394: ! 395: for (i = 0; i <= pgrphash; i++) { ! 396: if (pgrp = pgrphashtbl[i].lh_first) { ! 397: printf("\tindx %d\n", i); ! 398: for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) { ! 399: printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n", ! 400: pgrp, pgrp->pg_id, pgrp->pg_session, ! 401: pgrp->pg_session->s_count, ! 402: pgrp->pg_members.lh_first); ! 403: for (p = pgrp->pg_members.lh_first; p != 0; ! 404: p = p->p_pglist.le_next) { ! 405: printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n", ! 406: p->p_pid, p, p->p_pgrp); ! 407: } ! 408: } ! 409: } ! 410: } ! 411: } ! 412: #endif /* DEBUG */ ! 413: ! 414: struct proc * current_proc_EXTERNAL() ! 415: { ! 416: return (current_proc()); ! 417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.