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