Annotation of kernel/bsd/kern/kern_proc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.