1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_proc.c 7.15 (Berkeley) 04/20/91 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "map.h" 13 #include "kernel.h" 14 #include "proc.h" 15 #include "buf.h" 16 #include "seg.h" 17 #include "acct.h" 18 #include "wait.h" 19 #include "file.h" 20 #include "../ufs/quota.h" 21 #include "uio.h" 22 #include "malloc.h" 23 #include "mbuf.h" 24 #include "ioctl.h" 25 #include "tty.h" 26 27 /* 28 * Is p an inferior of the current process? 29 */ 30 inferior(p) 31 register struct proc *p; 32 { 33 34 for (; p != curproc; p = p->p_pptr) 35 if (p->p_pid == 0) 36 return (0); 37 return (1); 38 } 39 40 /* 41 * Locate a process by number 42 */ 43 struct proc * 44 pfind(pid) 45 register pid; 46 { 47 register struct proc *p = pidhash[PIDHASH(pid)]; 48 49 for (; p; p = p->p_hash) 50 if (p->p_pid == pid) 51 return (p); 52 return ((struct proc *)0); 53 } 54 55 /* 56 * Locate a process group by number 57 */ 58 struct pgrp * 59 pgfind(pgid) 60 register pid_t pgid; 61 { 62 register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 63 64 for (; pgrp; pgrp = pgrp->pg_hforw) 65 if (pgrp->pg_id == pgid) 66 return (pgrp); 67 return ((struct pgrp *)0); 68 } 69 70 /* 71 * Move p to a new or existing process group (and session) 72 */ 73 enterpgrp(p, pgid, mksess) 74 register struct proc *p; 75 pid_t pgid; 76 { 77 register struct pgrp *pgrp = pgfind(pgid); 78 register struct proc **pp; 79 register struct proc *cp; 80 int n; 81 82 #ifdef DIAGNOSTIC 83 if (pgrp && mksess) /* firewalls */ 84 panic("enterpgrp: setsid into non-empty pgrp"); 85 if (SESS_LEADER(p)) 86 panic("enterpgrp: session leader attempted setpgrp"); 87 #endif 88 if (pgrp == NULL) { 89 /* 90 * new process group 91 */ 92 #ifdef DIAGNOSTIC 93 if (p->p_pid != pgid) 94 panic("enterpgrp: new pgrp and pid != pgid"); 95 #endif 96 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 97 M_WAITOK); 98 if (mksess) { 99 register struct session *sess; 100 /* 101 * new session 102 */ 103 MALLOC(sess, struct session *, sizeof(struct session), 104 M_SESSION, M_WAITOK); 105 sess->s_leader = p; 106 sess->s_count = 1; 107 sess->s_ttyvp = NULL; 108 sess->s_ttyp = NULL; 109 p->p_flag &= ~SCTTY; 110 pgrp->pg_session = sess; 111 #ifdef DIAGNOSTIC 112 if (p != curproc) 113 panic("enterpgrp: mksession and p != curproc"); 114 #endif 115 } else { 116 pgrp->pg_session = p->p_session; 117 pgrp->pg_session->s_count++; 118 } 119 pgrp->pg_id = pgid; 120 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 121 pgrphash[n] = pgrp; 122 pgrp->pg_jobc = 0; 123 pgrp->pg_mem = NULL; 124 } else if (pgrp == p->p_pgrp) 125 return; 126 127 /* 128 * Adjust eligibility of affected pgrps to participate in job control. 129 * Increment eligibility counts before decrementing, otherwise we 130 * could reach 0 spuriously during the first call. 131 */ 132 fixjobc(p, pgrp, 1); 133 fixjobc(p, p->p_pgrp, 0); 134 135 /* 136 * unlink p from old process group 137 */ 138 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) 139 if (*pp == p) { 140 *pp = p->p_pgrpnxt; 141 goto done; 142 } 143 panic("enterpgrp: can't find p on old pgrp"); 144 done: 145 /* 146 * delete old if empty 147 */ 148 if (p->p_pgrp->pg_mem == 0) 149 pgdelete(p->p_pgrp); 150 /* 151 * link into new one 152 */ 153 p->p_pgrp = pgrp; 154 p->p_pgrpnxt = pgrp->pg_mem; 155 pgrp->pg_mem = p; 156 } 157 158 /* 159 * remove process from process group 160 */ 161 leavepgrp(p) 162 register struct proc *p; 163 { 164 register struct proc **pp = &p->p_pgrp->pg_mem; 165 166 for (; *pp; pp = &(*pp)->p_pgrpnxt) 167 if (*pp == p) { 168 *pp = p->p_pgrpnxt; 169 goto done; 170 } 171 panic("leavepgrp: can't find p in pgrp"); 172 done: 173 if (!p->p_pgrp->pg_mem) 174 pgdelete(p->p_pgrp); 175 p->p_pgrp = 0; 176 } 177 178 /* 179 * delete a process group 180 */ 181 pgdelete(pgrp) 182 register struct pgrp *pgrp; 183 { 184 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 185 186 if (pgrp->pg_session->s_ttyp != NULL && 187 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 188 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 189 for (; *pgp; pgp = &(*pgp)->pg_hforw) 190 if (*pgp == pgrp) { 191 *pgp = pgrp->pg_hforw; 192 goto done; 193 } 194 panic("pgdelete: can't find pgrp on hash chain"); 195 done: 196 if (--pgrp->pg_session->s_count == 0) 197 FREE(pgrp->pg_session, M_SESSION); 198 FREE(pgrp, M_PGRP); 199 } 200 201 static orphanpg(); 202 203 /* 204 * Adjust pgrp jobc counters when specified process changes process group. 205 * We count the number of processes in each process group that "qualify" 206 * the group for terminal job control (those with a parent in a different 207 * process group of the same session). If that count reaches zero, the 208 * process group becomes orphaned. Check both the specified process' 209 * process group and that of its children. 210 * entering == 0 => p is leaving specified group. 211 * entering == 1 => p is entering specified group. 212 */ 213 fixjobc(p, pgrp, entering) 214 register struct proc *p; 215 register struct pgrp *pgrp; 216 int entering; 217 { 218 register struct pgrp *hispgrp; 219 register struct session *mysession = pgrp->pg_session; 220 221 /* 222 * Check p's parent to see whether p qualifies its own process 223 * group; if so, adjust count for p's process group. 224 */ 225 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 226 hispgrp->pg_session == mysession) 227 if (entering) 228 pgrp->pg_jobc++; 229 else if (--pgrp->pg_jobc == 0) 230 orphanpg(pgrp); 231 232 /* 233 * Check this process' children to see whether they qualify 234 * their process groups; if so, adjust counts for children's 235 * process groups. 236 */ 237 for (p = p->p_cptr; p; p = p->p_osptr) 238 if ((hispgrp = p->p_pgrp) != pgrp && 239 hispgrp->pg_session == mysession && 240 p->p_stat != SZOMB) 241 if (entering) 242 hispgrp->pg_jobc++; 243 else if (--hispgrp->pg_jobc == 0) 244 orphanpg(hispgrp); 245 } 246 247 /* 248 * A process group has become orphaned; 249 * if there are any stopped processes in the group, 250 * hang-up all process in that group. 251 */ 252 static 253 orphanpg(pg) 254 struct pgrp *pg; 255 { 256 register struct proc *p; 257 258 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 259 if (p->p_stat == SSTOP) { 260 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 261 psignal(p, SIGHUP); 262 psignal(p, SIGCONT); 263 } 264 return; 265 } 266 } 267 } 268 269 #ifdef debug 270 /* DEBUG */ 271 pgrpdump() 272 { 273 register struct pgrp *pgrp; 274 register struct proc *p; 275 register i; 276 277 for (i=0; i<PIDHSZ; i++) { 278 if (pgrphash[i]) { 279 printf("\tindx %d\n", i); 280 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 281 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 282 pgrp, pgrp->pg_id, pgrp->pg_session, 283 pgrp->pg_session->s_count, pgrp->pg_mem); 284 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 285 printf("\t\tpid %d addr %x pgrp %x\n", 286 p->p_pid, p, p->p_pgrp); 287 } 288 } 289 290 } 291 } 292 } 293 #endif /* debug */ 294