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

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

unix.superglobalmegacorp.com

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