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