1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_proc.c 8.4 (Berkeley) 01/04/94 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_t pid; 109 { 110 register struct proc *p; 111 112 for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash) 113 if (p->p_pid == pid) 114 return (p); 115 return (NULL); 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; 126 127 for (pgrp = pgrphash[PIDHASH(pgid)]; 128 pgrp != NULL; pgrp = pgrp->pg_hforw) 129 if (pgrp->pg_id == pgid) 130 return (pgrp); 131 return (NULL); 132 } 133 134 /* 135 * Move p to a new or existing process group (and session) 136 */ 137 enterpgrp(p, pgid, mksess) 138 register struct proc *p; 139 pid_t pgid; 140 int mksess; 141 { 142 register struct pgrp *pgrp = pgfind(pgid); 143 register struct proc **pp; 144 int n; 145 146 #ifdef DIAGNOSTIC 147 if (pgrp != NULL && 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 pid_t savepid = p->p_pid; 154 struct proc *np; 155 /* 156 * new process group 157 */ 158 #ifdef DIAGNOSTIC 159 if (p->p_pid != pgid) 160 panic("enterpgrp: new pgrp and pid != pgid"); 161 #endif 162 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 163 M_WAITOK); 164 if ((np = pfind(savepid)) == NULL || np != p) 165 return (ESRCH); 166 if (mksess) { 167 register struct session *sess; 168 169 /* 170 * new session 171 */ 172 MALLOC(sess, struct session *, sizeof(struct session), 173 M_SESSION, M_WAITOK); 174 sess->s_leader = p; 175 sess->s_count = 1; 176 sess->s_ttyvp = NULL; 177 sess->s_ttyp = NULL; 178 bcopy(p->p_session->s_login, sess->s_login, 179 sizeof(sess->s_login)); 180 p->p_flag &= ~P_CONTROLT; 181 pgrp->pg_session = sess; 182 #ifdef DIAGNOSTIC 183 if (p != curproc) 184 panic("enterpgrp: mksession and p != curproc"); 185 #endif 186 } else { 187 pgrp->pg_session = p->p_session; 188 pgrp->pg_session->s_count++; 189 } 190 pgrp->pg_id = pgid; 191 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 192 pgrphash[n] = pgrp; 193 pgrp->pg_jobc = 0; 194 pgrp->pg_mem = NULL; 195 } else if (pgrp == p->p_pgrp) 196 return (0); 197 198 /* 199 * Adjust eligibility of affected pgrps to participate in job control. 200 * Increment eligibility counts before decrementing, otherwise we 201 * could reach 0 spuriously during the first call. 202 */ 203 fixjobc(p, pgrp, 1); 204 fixjobc(p, p->p_pgrp, 0); 205 206 /* 207 * unlink p from old process group 208 */ 209 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { 210 if (*pp == p) { 211 *pp = p->p_pgrpnxt; 212 break; 213 } 214 } 215 #ifdef DIAGNOSTIC 216 if (pp == NULL) 217 panic("enterpgrp: can't find p on old pgrp"); 218 #endif 219 /* 220 * delete old if empty 221 */ 222 if (p->p_pgrp->pg_mem == 0) 223 pgdelete(p->p_pgrp); 224 /* 225 * link into new one 226 */ 227 p->p_pgrp = pgrp; 228 p->p_pgrpnxt = pgrp->pg_mem; 229 pgrp->pg_mem = p; 230 return (0); 231 } 232 233 /* 234 * remove process from process group 235 */ 236 leavepgrp(p) 237 register struct proc *p; 238 { 239 register struct proc **pp = &p->p_pgrp->pg_mem; 240 241 for (; *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("leavepgrp: can't find p in pgrp"); 250 #endif 251 if (!p->p_pgrp->pg_mem) 252 pgdelete(p->p_pgrp); 253 p->p_pgrp = 0; 254 return (0); 255 } 256 257 /* 258 * delete a process group 259 */ 260 pgdelete(pgrp) 261 register struct pgrp *pgrp; 262 { 263 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 264 265 if (pgrp->pg_session->s_ttyp != NULL && 266 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 267 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 268 for (; *pgp; pgp = &(*pgp)->pg_hforw) { 269 if (*pgp == pgrp) { 270 *pgp = pgrp->pg_hforw; 271 break; 272 } 273 } 274 #ifdef DIAGNOSTIC 275 if (pgp == NULL) 276 panic("pgdelete: can't find pgrp on hash chain"); 277 #endif 278 if (--pgrp->pg_session->s_count == 0) 279 FREE(pgrp->pg_session, M_SESSION); 280 FREE(pgrp, M_PGRP); 281 } 282 283 static void orphanpg(); 284 285 /* 286 * Adjust pgrp jobc counters when specified process changes process group. 287 * We count the number of processes in each process group that "qualify" 288 * the group for terminal job control (those with a parent in a different 289 * process group of the same session). If that count reaches zero, the 290 * process group becomes orphaned. Check both the specified process' 291 * process group and that of its children. 292 * entering == 0 => p is leaving specified group. 293 * entering == 1 => p is entering specified group. 294 */ 295 fixjobc(p, pgrp, entering) 296 register struct proc *p; 297 register struct pgrp *pgrp; 298 int entering; 299 { 300 register struct pgrp *hispgrp; 301 register struct session *mysession = pgrp->pg_session; 302 303 /* 304 * Check p's parent to see whether p qualifies its own process 305 * group; if so, adjust count for p's process group. 306 */ 307 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 308 hispgrp->pg_session == mysession) 309 if (entering) 310 pgrp->pg_jobc++; 311 else if (--pgrp->pg_jobc == 0) 312 orphanpg(pgrp); 313 314 /* 315 * Check this process' children to see whether they qualify 316 * their process groups; if so, adjust counts for children's 317 * process groups. 318 */ 319 for (p = p->p_cptr; p; p = p->p_osptr) 320 if ((hispgrp = p->p_pgrp) != pgrp && 321 hispgrp->pg_session == mysession && 322 p->p_stat != SZOMB) 323 if (entering) 324 hispgrp->pg_jobc++; 325 else if (--hispgrp->pg_jobc == 0) 326 orphanpg(hispgrp); 327 } 328 329 /* 330 * A process group has become orphaned; 331 * if there are any stopped processes in the group, 332 * hang-up all process in that group. 333 */ 334 static void 335 orphanpg(pg) 336 struct pgrp *pg; 337 { 338 register struct proc *p; 339 340 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 341 if (p->p_stat == SSTOP) { 342 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 343 psignal(p, SIGHUP); 344 psignal(p, SIGCONT); 345 } 346 return; 347 } 348 } 349 } 350 351 #ifdef debug 352 /* DEBUG */ 353 pgrpdump() 354 { 355 register struct pgrp *pgrp; 356 register struct proc *p; 357 register i; 358 359 for (i=0; i<PIDHSZ; i++) { 360 if (pgrphash[i]) { 361 printf("\tindx %d\n", i); 362 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 363 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 364 pgrp, pgrp->pg_id, pgrp->pg_session, 365 pgrp->pg_session->s_count, pgrp->pg_mem); 366 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 367 printf("\t\tpid %d addr %x pgrp %x\n", 368 p->p_pid, p, p->p_pgrp); 369 } 370 } 371 372 } 373 } 374 } 375 #endif /* debug */ 376