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