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