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