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