|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 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. ! 11: * ! 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 ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1982, 1986, 1989, 1991, 1993 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * Redistribution and use in source and binary forms, with or without ! 28: * modification, are permitted provided that the following conditions ! 29: * are met: ! 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. ! 42: * ! 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 ! 53: * SUCH DAMAGE. ! 54: * ! 55: * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94 ! 56: */ ! 57: /* HISTORY ! 58: * 04-Aug-97 Umesh Vaishampayan ([email protected]) ! 59: * Added current_proc_EXTERNAL() function for the use of kernel ! 60: * lodable modules. ! 61: * ! 62: * 05-Jun-95 Mac Gillon (mgillon) at NeXT ! 63: * New version based on 3.3NS and 4.4 ! 64: */ ! 65: ! 66: ! 67: #include <sys/param.h> ! 68: #include <sys/systm.h> ! 69: #include <sys/kernel.h> ! 70: #include <sys/proc.h> ! 71: #include <sys/buf.h> ! 72: #include <sys/acct.h> ! 73: #include <sys/wait.h> ! 74: #include <sys/file.h> ! 75: #include <ufs/ufs/quota.h> ! 76: #include <sys/uio.h> ! 77: #include <sys/malloc.h> ! 78: #include <sys/mbuf.h> ! 79: #include <sys/ioctl.h> ! 80: #include <sys/tty.h> ! 81: #include <sys/signalvar.h> ! 82: ! 83: /* ! 84: * Structure associated with user cacheing. ! 85: */ ! 86: struct uidinfo { ! 87: LIST_ENTRY(uidinfo) ui_hash; ! 88: uid_t ui_uid; ! 89: long ui_proccnt; ! 90: }; ! 91: #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) ! 92: LIST_HEAD(uihashhead, uidinfo) *uihashtbl; ! 93: u_long uihash; /* size of hash table - 1 */ ! 94: ! 95: /* ! 96: * Other process lists ! 97: */ ! 98: struct pidhashhead *pidhashtbl; ! 99: u_long pidhash; ! 100: struct pgrphashhead *pgrphashtbl; ! 101: u_long pgrphash; ! 102: struct proclist allproc; ! 103: struct proclist zombproc; ! 104: ! 105: /* ! 106: * Initialize global process hashing structures. ! 107: */ ! 108: void ! 109: procinit() ! 110: { ! 111: ! 112: LIST_INIT(&allproc); ! 113: LIST_INIT(&zombproc); ! 114: pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); ! 115: pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); ! 116: uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); ! 117: } ! 118: ! 119: /* ! 120: * Change the count associated with number of processes ! 121: * a given user is using. ! 122: */ ! 123: int ! 124: chgproccnt(uid, diff) ! 125: uid_t uid; ! 126: int diff; ! 127: { ! 128: register struct uidinfo *uip; ! 129: register struct uihashhead *uipp; ! 130: ! 131: uipp = UIHASH(uid); ! 132: for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) ! 133: if (uip->ui_uid == uid) ! 134: break; ! 135: if (uip) { ! 136: uip->ui_proccnt += diff; ! 137: if (uip->ui_proccnt > 0) ! 138: return (uip->ui_proccnt); ! 139: if (uip->ui_proccnt < 0) ! 140: panic("chgproccnt: procs < 0"); ! 141: LIST_REMOVE(uip, ui_hash); ! 142: FREE_ZONE(uip, sizeof *uip, M_PROC); ! 143: return (0); ! 144: } ! 145: if (diff <= 0) { ! 146: if (diff == 0) ! 147: return(0); ! 148: panic("chgproccnt: lost user"); ! 149: } ! 150: MALLOC_ZONE(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); ! 151: LIST_INSERT_HEAD(uipp, uip, ui_hash); ! 152: uip->ui_uid = uid; ! 153: uip->ui_proccnt = diff; ! 154: return (diff); ! 155: } ! 156: ! 157: /* ! 158: * Is p an inferior of the current process? ! 159: */ ! 160: int ! 161: inferior(p) ! 162: register struct proc *p; ! 163: { ! 164: ! 165: for (; p != current_proc(); p = p->p_pptr) ! 166: if (p->p_pid == 0) ! 167: return (0); ! 168: return (1); ! 169: } ! 170: ! 171: /* ! 172: * Locate a process by number ! 173: */ ! 174: struct proc * ! 175: pfind(pid) ! 176: register pid_t pid; ! 177: { ! 178: register struct proc *p; ! 179: ! 180: if (!pid) ! 181: return (kernproc); ! 182: ! 183: for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) ! 184: if (p->p_pid == pid) ! 185: return (p); ! 186: return (NULL); ! 187: } ! 188: ! 189: /* ! 190: * Locate a process group by number ! 191: */ ! 192: struct pgrp * ! 193: pgfind(pgid) ! 194: register pid_t pgid; ! 195: { ! 196: register struct pgrp *pgrp; ! 197: ! 198: for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next) ! 199: if (pgrp->pg_id == pgid) ! 200: return (pgrp); ! 201: return (NULL); ! 202: } ! 203: ! 204: ! 205: /* ! 206: * Move p to a new or existing process group (and session) ! 207: */ ! 208: int ! 209: enterpgrp(p, pgid, mksess) ! 210: register struct proc *p; ! 211: pid_t pgid; ! 212: int mksess; ! 213: { ! 214: register struct pgrp *pgrp = pgfind(pgid); ! 215: ! 216: #if DIAGNOSTIC ! 217: if (pgrp != NULL && mksess) /* firewalls */ ! 218: panic("enterpgrp: setsid into non-empty pgrp"); ! 219: if (SESS_LEADER(p)) ! 220: panic("enterpgrp: session leader attempted setpgrp"); ! 221: #endif ! 222: if (pgrp == NULL) { ! 223: pid_t savepid = p->p_pid; ! 224: struct proc *np; ! 225: /* ! 226: * new process group ! 227: */ ! 228: #if DIAGNOSTIC ! 229: if (p->p_pid != pgid) ! 230: panic("enterpgrp: new pgrp and pid != pgid"); ! 231: #endif ! 232: MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, ! 233: M_WAITOK); ! 234: if ((np = pfind(savepid)) == NULL || np != p) ! 235: return (ESRCH); ! 236: if (mksess) { ! 237: register struct session *sess; ! 238: ! 239: /* ! 240: * new session ! 241: */ ! 242: MALLOC_ZONE(sess, struct session *, ! 243: sizeof(struct session), M_SESSION, M_WAITOK); ! 244: sess->s_leader = p; ! 245: sess->s_count = 1; ! 246: sess->s_ttyvp = NULL; ! 247: sess->s_ttyp = NULL; ! 248: bcopy(p->p_session->s_login, sess->s_login, ! 249: sizeof(sess->s_login)); ! 250: p->p_flag &= ~P_CONTROLT; ! 251: pgrp->pg_session = sess; ! 252: #if DIAGNOSTIC ! 253: if (p != current_proc()) ! 254: panic("enterpgrp: mksession and p != curproc"); ! 255: #endif ! 256: } else { ! 257: pgrp->pg_session = p->p_session; ! 258: pgrp->pg_session->s_count++; ! 259: } ! 260: pgrp->pg_id = pgid; ! 261: LIST_INIT(&pgrp->pg_members); ! 262: LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); ! 263: pgrp->pg_jobc = 0; ! 264: } else if (pgrp == p->p_pgrp) ! 265: return (0); ! 266: ! 267: /* ! 268: * Adjust eligibility of affected pgrps to participate in job control. ! 269: * Increment eligibility counts before decrementing, otherwise we ! 270: * could reach 0 spuriously during the first call. ! 271: */ ! 272: fixjobc(p, pgrp, 1); ! 273: fixjobc(p, p->p_pgrp, 0); ! 274: ! 275: LIST_REMOVE(p, p_pglist); ! 276: if (p->p_pgrp->pg_members.lh_first == 0) ! 277: pgdelete(p->p_pgrp); ! 278: p->p_pgrp = pgrp; ! 279: LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); ! 280: return (0); ! 281: } ! 282: ! 283: /* ! 284: * remove process from process group ! 285: */ ! 286: int ! 287: leavepgrp(p) ! 288: register struct proc *p; ! 289: { ! 290: ! 291: LIST_REMOVE(p, p_pglist); ! 292: if (p->p_pgrp->pg_members.lh_first == 0) ! 293: pgdelete(p->p_pgrp); ! 294: p->p_pgrp = 0; ! 295: return (0); ! 296: } ! 297: ! 298: /* ! 299: * delete a process group ! 300: */ ! 301: void ! 302: pgdelete(pgrp) ! 303: register struct pgrp *pgrp; ! 304: { ! 305: ! 306: if (pgrp->pg_session->s_ttyp != NULL && ! 307: pgrp->pg_session->s_ttyp->t_pgrp == pgrp) ! 308: pgrp->pg_session->s_ttyp->t_pgrp = NULL; ! 309: LIST_REMOVE(pgrp, pg_hash); ! 310: if (--pgrp->pg_session->s_count == 0) ! 311: FREE_ZONE(pgrp->pg_session, sizeof(struct session), M_SESSION); ! 312: FREE_ZONE(pgrp, sizeof *pgrp, M_PGRP); ! 313: } ! 314: ! 315: void ! 316: sessrele(sess) ! 317: struct session *sess; ! 318: { ! 319: if (--sess->s_count == 0) ! 320: FREE_ZONE(sess, sizeof (struct session), M_SESSION); ! 321: } ! 322: ! 323: static void orphanpg(); ! 324: ! 325: /* ! 326: * Adjust pgrp jobc counters when specified process changes process group. ! 327: * We count the number of processes in each process group that "qualify" ! 328: * the group for terminal job control (those with a parent in a different ! 329: * process group of the same session). If that count reaches zero, the ! 330: * process group becomes orphaned. Check both the specified process' ! 331: * process group and that of its children. ! 332: * entering == 0 => p is leaving specified group. ! 333: * entering == 1 => p is entering specified group. ! 334: */ ! 335: void ! 336: fixjobc(p, pgrp, entering) ! 337: register struct proc *p; ! 338: register struct pgrp *pgrp; ! 339: int entering; ! 340: { ! 341: register struct pgrp *hispgrp; ! 342: register struct session *mysession = pgrp->pg_session; ! 343: ! 344: /* ! 345: * Check p's parent to see whether p qualifies its own process ! 346: * group; if so, adjust count for p's process group. ! 347: */ ! 348: if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && ! 349: hispgrp->pg_session == mysession) ! 350: if (entering) ! 351: pgrp->pg_jobc++; ! 352: else if (--pgrp->pg_jobc == 0) ! 353: orphanpg(pgrp); ! 354: ! 355: /* ! 356: * Check this process' children to see whether they qualify ! 357: * their process groups; if so, adjust counts for children's ! 358: * process groups. ! 359: */ ! 360: for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) ! 361: if ((hispgrp = p->p_pgrp) != pgrp && ! 362: hispgrp->pg_session == mysession && ! 363: p->p_stat != SZOMB) ! 364: if (entering) ! 365: hispgrp->pg_jobc++; ! 366: else if (--hispgrp->pg_jobc == 0) ! 367: orphanpg(hispgrp); ! 368: } ! 369: ! 370: /* ! 371: * A process group has become orphaned; ! 372: * if there are any stopped processes in the group, ! 373: * hang-up all process in that group. ! 374: */ ! 375: static void ! 376: orphanpg(pg) ! 377: struct pgrp *pg; ! 378: { ! 379: register struct proc *p; ! 380: ! 381: for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { ! 382: if (p->p_stat == SSTOP) { ! 383: for (p = pg->pg_members.lh_first; p != 0; ! 384: p = p->p_pglist.le_next) { ! 385: psignal(p, SIGHUP); ! 386: psignal(p, SIGCONT); ! 387: } ! 388: return; ! 389: } ! 390: } ! 391: } ! 392: ! 393: #ifdef DEBUG ! 394: void ! 395: pgrpdump() ! 396: { ! 397: register struct pgrp *pgrp; ! 398: register struct proc *p; ! 399: register i; ! 400: ! 401: for (i = 0; i <= pgrphash; i++) { ! 402: if (pgrp = pgrphashtbl[i].lh_first) { ! 403: printf("\tindx %d\n", i); ! 404: for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) { ! 405: printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n", ! 406: pgrp, pgrp->pg_id, pgrp->pg_session, ! 407: pgrp->pg_session->s_count, ! 408: pgrp->pg_members.lh_first); ! 409: for (p = pgrp->pg_members.lh_first; p != 0; ! 410: p = p->p_pglist.le_next) { ! 411: printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n", ! 412: p->p_pid, p, p->p_pgrp); ! 413: } ! 414: } ! 415: } ! 416: } ! 417: } ! 418: #endif /* DEBUG */ ! 419: ! 420: struct proc * current_proc_EXTERNAL() ! 421: { ! 422: return (current_proc()); ! 423: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.