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