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 * $Id: kern_proc.c,v 1.3 1994/08/02 07:42:07 davidg Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/map.h> 40 #include <sys/kernel.h> 41 #include <sys/proc.h> 42 #include <sys/buf.h> 43 #include <sys/acct.h> 44 #include <sys/wait.h> 45 #include <sys/file.h> 46 #include <ufs/ufs/quota.h> 47 #include <sys/uio.h> 48 #include <sys/malloc.h> 49 #include <sys/mbuf.h> 50 #include <sys/ioctl.h> 51 #include <sys/tty.h> 52 53 volatile struct proc *allproc; /* all processes */ 54 struct proc *zombproc; /* just zombies */ 55 56 void pgdelete __P((struct pgrp *)); 57 void fixjobc __P((struct proc *, struct pgrp *, int)); 58 59 /* 60 * Structure associated with user cacheing. 61 */ 62 struct uidinfo { 63 struct uidinfo *ui_next; 64 struct uidinfo **ui_prev; 65 uid_t ui_uid; 66 long ui_proccnt; 67 } **uihashtbl; 68 u_long uihash; /* size of hash table - 1 */ 69 #define UIHASH(uid) ((uid) & uihash) 70 71 /* 72 * Allocate a hash table. 73 */ 74 void 75 usrinfoinit() 76 { 77 78 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 79 } 80 81 /* 82 * Change the count associated with number of processes 83 * a given user is using. 84 */ 85 int 86 chgproccnt(uid, diff) 87 uid_t uid; 88 int diff; 89 { 90 register struct uidinfo **uipp, *uip, *uiq; 91 92 uipp = &uihashtbl[UIHASH(uid)]; 93 for (uip = *uipp; uip; uip = uip->ui_next) 94 if (uip->ui_uid == uid) 95 break; 96 if (uip) { 97 uip->ui_proccnt += diff; 98 if (uip->ui_proccnt > 0) 99 return (uip->ui_proccnt); 100 if (uip->ui_proccnt < 0) 101 panic("chgproccnt: procs < 0"); 102 if (uiq = uip->ui_next) 103 uiq->ui_prev = uip->ui_prev; 104 *uip->ui_prev = uiq; 105 FREE(uip, M_PROC); 106 return (0); 107 } 108 if (diff <= 0) { 109 if (diff == 0) 110 return(0); 111 panic("chgproccnt: lost user"); 112 } 113 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 114 if (uiq = *uipp) 115 uiq->ui_prev = &uip->ui_next; 116 uip->ui_next = uiq; 117 uip->ui_prev = uipp; 118 *uipp = uip; 119 uip->ui_uid = uid; 120 uip->ui_proccnt = diff; 121 return (diff); 122 } 123 124 /* 125 * Is p an inferior of the current process? 126 */ 127 int 128 inferior(p) 129 register struct proc *p; 130 { 131 132 for (; p != curproc; p = p->p_pptr) 133 if (p->p_pid == 0) 134 return (0); 135 return (1); 136 } 137 138 /* 139 * Locate a process by number 140 */ 141 struct proc * 142 pfind(pid) 143 register pid_t pid; 144 { 145 register struct proc *p; 146 147 for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash) 148 if (p->p_pid == pid) 149 return (p); 150 return (NULL); 151 } 152 153 /* 154 * Locate a process group by number 155 */ 156 struct pgrp * 157 pgfind(pgid) 158 register pid_t pgid; 159 { 160 register struct pgrp *pgrp; 161 162 for (pgrp = pgrphash[PIDHASH(pgid)]; 163 pgrp != NULL; pgrp = pgrp->pg_hforw) 164 if (pgrp->pg_id == pgid) 165 return (pgrp); 166 return (NULL); 167 } 168 169 /* 170 * Move p to a new or existing process group (and session) 171 */ 172 int 173 enterpgrp(p, pgid, mksess) 174 register struct proc *p; 175 pid_t pgid; 176 int mksess; 177 { 178 register struct pgrp *pgrp = pgfind(pgid); 179 register struct proc **pp; 180 int n; 181 182 #ifdef DIAGNOSTIC 183 if (pgrp != NULL && mksess) /* firewalls */ 184 panic("enterpgrp: setsid into non-empty pgrp"); 185 if (SESS_LEADER(p)) 186 panic("enterpgrp: session leader attempted setpgrp"); 187 #endif 188 if (pgrp == NULL) { 189 pid_t savepid = p->p_pid; 190 struct proc *np; 191 /* 192 * new process group 193 */ 194 #ifdef DIAGNOSTIC 195 if (p->p_pid != pgid) 196 panic("enterpgrp: new pgrp and pid != pgid"); 197 #endif 198 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 199 M_WAITOK); 200 if ((np = pfind(savepid)) == NULL || np != p) 201 return (ESRCH); 202 if (mksess) { 203 register struct session *sess; 204 205 /* 206 * new session 207 */ 208 MALLOC(sess, struct session *, sizeof(struct session), 209 M_SESSION, M_WAITOK); 210 sess->s_leader = p; 211 sess->s_count = 1; 212 sess->s_ttyvp = NULL; 213 sess->s_ttyp = NULL; 214 bcopy(p->p_session->s_login, sess->s_login, 215 sizeof(sess->s_login)); 216 p->p_flag &= ~P_CONTROLT; 217 pgrp->pg_session = sess; 218 #ifdef DIAGNOSTIC 219 if (p != curproc) 220 panic("enterpgrp: mksession and p != curproc"); 221 #endif 222 } else { 223 pgrp->pg_session = p->p_session; 224 pgrp->pg_session->s_count++; 225 } 226 pgrp->pg_id = pgid; 227 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 228 pgrphash[n] = pgrp; 229 pgrp->pg_jobc = 0; 230 pgrp->pg_mem = NULL; 231 } else if (pgrp == p->p_pgrp) 232 return (0); 233 234 /* 235 * Adjust eligibility of affected pgrps to participate in job control. 236 * Increment eligibility counts before decrementing, otherwise we 237 * could reach 0 spuriously during the first call. 238 */ 239 fixjobc(p, pgrp, 1); 240 fixjobc(p, p->p_pgrp, 0); 241 242 /* 243 * unlink p from old process group 244 */ 245 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { 246 if (*pp == p) { 247 *pp = p->p_pgrpnxt; 248 break; 249 } 250 } 251 #ifdef DIAGNOSTIC 252 if (pp == NULL) 253 panic("enterpgrp: can't find p on old pgrp"); 254 #endif 255 /* 256 * delete old if empty 257 */ 258 if (p->p_pgrp->pg_mem == 0) 259 pgdelete(p->p_pgrp); 260 /* 261 * link into new one 262 */ 263 p->p_pgrp = pgrp; 264 p->p_pgrpnxt = pgrp->pg_mem; 265 pgrp->pg_mem = p; 266 return (0); 267 } 268 269 /* 270 * remove process from process group 271 */ 272 int 273 leavepgrp(p) 274 register struct proc *p; 275 { 276 register struct proc **pp = &p->p_pgrp->pg_mem; 277 278 for (; *pp; pp = &(*pp)->p_pgrpnxt) { 279 if (*pp == p) { 280 *pp = p->p_pgrpnxt; 281 break; 282 } 283 } 284 #ifdef DIAGNOSTIC 285 if (pp == NULL) 286 panic("leavepgrp: can't find p in pgrp"); 287 #endif 288 if (!p->p_pgrp->pg_mem) 289 pgdelete(p->p_pgrp); 290 p->p_pgrp = 0; 291 return (0); 292 } 293 294 /* 295 * delete a process group 296 */ 297 void 298 pgdelete(pgrp) 299 register struct pgrp *pgrp; 300 { 301 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 302 303 if (pgrp->pg_session->s_ttyp != NULL && 304 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 305 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 306 for (; *pgp; pgp = &(*pgp)->pg_hforw) { 307 if (*pgp == pgrp) { 308 *pgp = pgrp->pg_hforw; 309 break; 310 } 311 } 312 #ifdef DIAGNOSTIC 313 if (pgp == NULL) 314 panic("pgdelete: can't find pgrp on hash chain"); 315 #endif 316 if (--pgrp->pg_session->s_count == 0) 317 FREE(pgrp->pg_session, M_SESSION); 318 FREE(pgrp, M_PGRP); 319 } 320 321 static void orphanpg(); 322 323 /* 324 * Adjust pgrp jobc counters when specified process changes process group. 325 * We count the number of processes in each process group that "qualify" 326 * the group for terminal job control (those with a parent in a different 327 * process group of the same session). If that count reaches zero, the 328 * process group becomes orphaned. Check both the specified process' 329 * process group and that of its children. 330 * entering == 0 => p is leaving specified group. 331 * entering == 1 => p is entering specified group. 332 */ 333 void 334 fixjobc(p, pgrp, entering) 335 register struct proc *p; 336 register struct pgrp *pgrp; 337 int entering; 338 { 339 register struct pgrp *hispgrp; 340 register struct session *mysession = pgrp->pg_session; 341 342 /* 343 * Check p's parent to see whether p qualifies its own process 344 * group; if so, adjust count for p's process group. 345 */ 346 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 347 hispgrp->pg_session == mysession) 348 if (entering) 349 pgrp->pg_jobc++; 350 else if (--pgrp->pg_jobc == 0) 351 orphanpg(pgrp); 352 353 /* 354 * Check this process' children to see whether they qualify 355 * their process groups; if so, adjust counts for children's 356 * process groups. 357 */ 358 for (p = p->p_cptr; p; p = p->p_osptr) 359 if ((hispgrp = p->p_pgrp) != pgrp && 360 hispgrp->pg_session == mysession && 361 p->p_stat != SZOMB) 362 if (entering) 363 hispgrp->pg_jobc++; 364 else if (--hispgrp->pg_jobc == 0) 365 orphanpg(hispgrp); 366 } 367 368 /* 369 * A process group has become orphaned; 370 * if there are any stopped processes in the group, 371 * hang-up all process in that group. 372 */ 373 static void 374 orphanpg(pg) 375 struct pgrp *pg; 376 { 377 register struct proc *p; 378 379 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 380 if (p->p_stat == SSTOP) { 381 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 382 psignal(p, SIGHUP); 383 psignal(p, SIGCONT); 384 } 385 return; 386 } 387 } 388 } 389 390 #ifdef debug 391 /* DEBUG */ 392 pgrpdump() 393 { 394 register struct pgrp *pgrp; 395 register struct proc *p; 396 register i; 397 398 for (i=0; i<PIDHSZ; i++) { 399 if (pgrphash[i]) { 400 printf("\tindx %d\n", i); 401 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 402 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 403 pgrp, pgrp->pg_id, pgrp->pg_session, 404 pgrp->pg_session->s_count, pgrp->pg_mem); 405 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 406 printf("\t\tpid %d addr %x pgrp %x\n", 407 p->p_pid, p, p->p_pgrp); 408 } 409 } 410 411 } 412 } 413 } 414 #endif /* debug */ 415