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 * $Id: kern_proc.c,v 1.10 1995/05/30 08:05:37 rgrimes Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/sysctl.h> 41 #include <sys/user.h> 42 #include <sys/proc.h> 43 #include <sys/buf.h> 44 #include <sys/acct.h> 45 #include <sys/wait.h> 46 #include <sys/file.h> 47 #include <ufs/ufs/quota.h> 48 #include <sys/uio.h> 49 #include <sys/malloc.h> 50 #include <sys/mbuf.h> 51 #include <sys/ioctl.h> 52 #include <sys/tty.h> 53 #include <sys/signalvar.h> 54 55 struct prochd qs[NQS]; /* as good a place as any... */ 56 struct prochd rtqs[NQS]; /* Space for REALTIME queues too */ 57 struct prochd idqs[NQS]; /* Space for IDLE queues too */ 58 59 volatile struct proc *allproc; /* all processes */ 60 struct proc *zombproc; /* just zombies */ 61 62 void pgdelete __P((struct pgrp *)); 63 64 /* 65 * Structure associated with user cacheing. 66 */ 67 struct uidinfo { 68 struct uidinfo *ui_next; 69 struct uidinfo **ui_prev; 70 uid_t ui_uid; 71 long ui_proccnt; 72 } **uihashtbl; 73 u_long uihash; /* size of hash table - 1 */ 74 #define UIHASH(uid) ((uid) & uihash) 75 76 /* 77 * Allocate a hash table. 78 */ 79 void 80 usrinfoinit() 81 { 82 83 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 84 } 85 86 /* 87 * Change the count associated with number of processes 88 * a given user is using. 89 */ 90 int 91 chgproccnt(uid, diff) 92 uid_t uid; 93 int diff; 94 { 95 register struct uidinfo **uipp, *uip, *uiq; 96 97 uipp = &uihashtbl[UIHASH(uid)]; 98 for (uip = *uipp; uip; uip = uip->ui_next) 99 if (uip->ui_uid == uid) 100 break; 101 if (uip) { 102 uip->ui_proccnt += diff; 103 if (uip->ui_proccnt > 0) 104 return (uip->ui_proccnt); 105 if (uip->ui_proccnt < 0) 106 panic("chgproccnt: procs < 0"); 107 if ((uiq = uip->ui_next)) 108 uiq->ui_prev = uip->ui_prev; 109 *uip->ui_prev = uiq; 110 FREE(uip, M_PROC); 111 return (0); 112 } 113 if (diff <= 0) { 114 if (diff == 0) 115 return(0); 116 panic("chgproccnt: lost user"); 117 } 118 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 119 if ((uiq = *uipp)) 120 uiq->ui_prev = &uip->ui_next; 121 uip->ui_next = uiq; 122 uip->ui_prev = uipp; 123 *uipp = uip; 124 uip->ui_uid = uid; 125 uip->ui_proccnt = diff; 126 return (diff); 127 } 128 129 /* 130 * Is p an inferior of the current process? 131 */ 132 int 133 inferior(p) 134 register struct proc *p; 135 { 136 137 for (; p != curproc; p = p->p_pptr) 138 if (p->p_pid == 0) 139 return (0); 140 return (1); 141 } 142 143 /* 144 * Locate a process by number 145 */ 146 struct proc * 147 pfind(pid) 148 register pid_t pid; 149 { 150 register struct proc *p; 151 152 for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash) 153 if (p->p_pid == pid) 154 return (p); 155 return (NULL); 156 } 157 158 /* 159 * Locate a process group by number 160 */ 161 struct pgrp * 162 pgfind(pgid) 163 register pid_t pgid; 164 { 165 register struct pgrp *pgrp; 166 167 for (pgrp = pgrphash[PIDHASH(pgid)]; 168 pgrp != NULL; pgrp = pgrp->pg_hforw) 169 if (pgrp->pg_id == pgid) 170 return (pgrp); 171 return (NULL); 172 } 173 174 /* 175 * Move p to a new or existing process group (and session) 176 */ 177 int 178 enterpgrp(p, pgid, mksess) 179 register struct proc *p; 180 pid_t pgid; 181 int mksess; 182 { 183 register struct pgrp *pgrp = pgfind(pgid); 184 register struct proc **pp; 185 int n; 186 187 #ifdef DIAGNOSTIC 188 if (pgrp != NULL && mksess) /* firewalls */ 189 panic("enterpgrp: setsid into non-empty pgrp"); 190 if (SESS_LEADER(p)) 191 panic("enterpgrp: session leader attempted setpgrp"); 192 #endif 193 if (pgrp == NULL) { 194 pid_t savepid = p->p_pid; 195 struct proc *np; 196 /* 197 * new process group 198 */ 199 #ifdef DIAGNOSTIC 200 if (p->p_pid != pgid) 201 panic("enterpgrp: new pgrp and pid != pgid"); 202 #endif 203 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 204 M_WAITOK); 205 if ((np = pfind(savepid)) == NULL || np != p) 206 return (ESRCH); 207 if (mksess) { 208 register struct session *sess; 209 210 /* 211 * new session 212 */ 213 MALLOC(sess, struct session *, sizeof(struct session), 214 M_SESSION, M_WAITOK); 215 sess->s_leader = p; 216 sess->s_count = 1; 217 sess->s_ttyvp = NULL; 218 sess->s_ttyp = NULL; 219 bcopy(p->p_session->s_login, sess->s_login, 220 sizeof(sess->s_login)); 221 p->p_flag &= ~P_CONTROLT; 222 pgrp->pg_session = sess; 223 #ifdef DIAGNOSTIC 224 if (p != curproc) 225 panic("enterpgrp: mksession and p != curproc"); 226 #endif 227 } else { 228 pgrp->pg_session = p->p_session; 229 pgrp->pg_session->s_count++; 230 } 231 pgrp->pg_id = pgid; 232 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 233 pgrphash[n] = pgrp; 234 pgrp->pg_jobc = 0; 235 pgrp->pg_mem = NULL; 236 } else if (pgrp == p->p_pgrp) 237 return (0); 238 239 /* 240 * Adjust eligibility of affected pgrps to participate in job control. 241 * Increment eligibility counts before decrementing, otherwise we 242 * could reach 0 spuriously during the first call. 243 */ 244 fixjobc(p, pgrp, 1); 245 fixjobc(p, p->p_pgrp, 0); 246 247 /* 248 * unlink p from old process group 249 */ 250 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { 251 if (*pp == p) { 252 *pp = p->p_pgrpnxt; 253 break; 254 } 255 } 256 #ifdef DIAGNOSTIC 257 if (pp == NULL) 258 panic("enterpgrp: can't find p on old pgrp"); 259 #endif 260 /* 261 * delete old if empty 262 */ 263 if (p->p_pgrp->pg_mem == 0) 264 pgdelete(p->p_pgrp); 265 /* 266 * link into new one 267 */ 268 p->p_pgrp = pgrp; 269 p->p_pgrpnxt = pgrp->pg_mem; 270 pgrp->pg_mem = p; 271 return (0); 272 } 273 274 /* 275 * remove process from process group 276 */ 277 int 278 leavepgrp(p) 279 register struct proc *p; 280 { 281 register struct proc **pp = &p->p_pgrp->pg_mem; 282 283 for (; *pp; pp = &(*pp)->p_pgrpnxt) { 284 if (*pp == p) { 285 *pp = p->p_pgrpnxt; 286 break; 287 } 288 } 289 #ifdef DIAGNOSTIC 290 if (pp == NULL) 291 panic("leavepgrp: can't find p in pgrp"); 292 #endif 293 if (!p->p_pgrp->pg_mem) 294 pgdelete(p->p_pgrp); 295 p->p_pgrp = 0; 296 return (0); 297 } 298 299 /* 300 * delete a process group 301 */ 302 void 303 pgdelete(pgrp) 304 register struct pgrp *pgrp; 305 { 306 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 307 308 if (pgrp->pg_session->s_ttyp != NULL && 309 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 310 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 311 for (; *pgp; pgp = &(*pgp)->pg_hforw) { 312 if (*pgp == pgrp) { 313 *pgp = pgrp->pg_hforw; 314 break; 315 } 316 } 317 #ifdef DIAGNOSTIC 318 if (pgp == NULL) 319 panic("pgdelete: can't find pgrp on hash chain"); 320 #endif 321 if (--pgrp->pg_session->s_count == 0) 322 FREE(pgrp->pg_session, M_SESSION); 323 FREE(pgrp, M_PGRP); 324 } 325 326 static void orphanpg(); 327 328 /* 329 * Adjust pgrp jobc counters when specified process changes process group. 330 * We count the number of processes in each process group that "qualify" 331 * the group for terminal job control (those with a parent in a different 332 * process group of the same session). If that count reaches zero, the 333 * process group becomes orphaned. Check both the specified process' 334 * process group and that of its children. 335 * entering == 0 => p is leaving specified group. 336 * entering == 1 => p is entering specified group. 337 */ 338 void 339 fixjobc(p, pgrp, entering) 340 register struct proc *p; 341 register struct pgrp *pgrp; 342 int entering; 343 { 344 register struct pgrp *hispgrp; 345 register struct session *mysession = pgrp->pg_session; 346 347 /* 348 * Check p's parent to see whether p qualifies its own process 349 * group; if so, adjust count for p's process group. 350 */ 351 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 352 hispgrp->pg_session == mysession) 353 if (entering) 354 pgrp->pg_jobc++; 355 else if (--pgrp->pg_jobc == 0) 356 orphanpg(pgrp); 357 358 /* 359 * Check this process' children to see whether they qualify 360 * their process groups; if so, adjust counts for children's 361 * process groups. 362 */ 363 for (p = p->p_cptr; p; p = p->p_osptr) 364 if ((hispgrp = p->p_pgrp) != pgrp && 365 hispgrp->pg_session == mysession && 366 p->p_stat != SZOMB) 367 if (entering) 368 hispgrp->pg_jobc++; 369 else if (--hispgrp->pg_jobc == 0) 370 orphanpg(hispgrp); 371 } 372 373 /* 374 * A process group has become orphaned; 375 * if there are any stopped processes in the group, 376 * hang-up all process in that group. 377 */ 378 static void 379 orphanpg(pg) 380 struct pgrp *pg; 381 { 382 register struct proc *p; 383 384 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 385 if (p->p_stat == SSTOP) { 386 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 387 psignal(p, SIGHUP); 388 psignal(p, SIGCONT); 389 } 390 return; 391 } 392 } 393 } 394 395 #ifdef debug 396 /* DEBUG */ 397 pgrpdump() 398 { 399 register struct pgrp *pgrp; 400 register struct proc *p; 401 register i; 402 403 for (i=0; i<PIDHSZ; i++) { 404 if (pgrphash[i]) { 405 printf("\tindx %d\n", i); 406 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 407 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 408 pgrp, pgrp->pg_id, pgrp->pg_session, 409 pgrp->pg_session->s_count, pgrp->pg_mem); 410 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 411 printf("\t\tpid %d addr %x pgrp %x\n", 412 p->p_pid, p, p->p_pgrp); 413 } 414 } 415 416 } 417 } 418 } 419 #endif /* debug */ 420 421 /* 422 * Fill in an eproc structure for the specified process. 423 */ 424 void 425 fill_eproc(p, ep) 426 register struct proc *p; 427 register struct eproc *ep; 428 { 429 register struct tty *tp; 430 431 bzero(ep, sizeof(*ep)); 432 433 ep->e_paddr = p; 434 if (p->p_cred) { 435 ep->e_pcred = *p->p_cred; 436 if (p->p_ucred) 437 ep->e_ucred = *p->p_ucred; 438 } 439 if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) { 440 register struct vmspace *vm = p->p_vmspace; 441 442 #ifdef pmap_resident_count 443 ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 444 #else 445 ep->e_vm.vm_rssize = vm->vm_rssize; 446 #endif 447 ep->e_vm.vm_tsize = vm->vm_tsize; 448 ep->e_vm.vm_dsize = vm->vm_dsize; 449 ep->e_vm.vm_ssize = vm->vm_ssize; 450 #ifndef sparc 451 ep->e_vm.vm_pmap = vm->vm_pmap; 452 #endif 453 } 454 if (p->p_pptr) 455 ep->e_ppid = p->p_pptr->p_pid; 456 if (p->p_pgrp) { 457 ep->e_sess = p->p_pgrp->pg_session; 458 ep->e_pgid = p->p_pgrp->pg_id; 459 ep->e_jobc = p->p_pgrp->pg_jobc; 460 } 461 if ((p->p_flag & P_CONTROLT) && 462 (ep->e_sess != NULL) && 463 ((tp = ep->e_sess->s_ttyp) != NULL)) { 464 ep->e_tdev = tp->t_dev; 465 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 466 ep->e_tsess = tp->t_session; 467 } else 468 ep->e_tdev = NODEV; 469 if (ep->e_sess && ep->e_sess->s_ttyvp) 470 ep->e_flag = EPROC_CTTY; 471 if (SESS_LEADER(p)) 472 ep->e_flag |= EPROC_SLEADER; 473 if (p->p_wmesg) { 474 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 475 ep->e_wmesg[WMESGLEN] = 0; 476 } 477 } 478 479 static int 480 sysctl_kern_proc SYSCTL_HANDLER_ARGS 481 { 482 int *name = (int*) arg1; 483 u_int namelen = arg2; 484 struct proc *p; 485 int doingzomb; 486 struct eproc eproc; 487 int error = 0; 488 489 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 490 return (EINVAL); 491 if (!req->oldptr) { 492 /* 493 * try over estimating by 5 procs 494 */ 495 error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5); 496 if (error) 497 return (error); 498 } 499 p = (struct proc *)allproc; 500 doingzomb = 0; 501 again: 502 for (; p != NULL; p = p->p_next) { 503 /* 504 * Skip embryonic processes. 505 */ 506 if (p->p_stat == SIDL) 507 continue; 508 /* 509 * TODO - make more efficient (see notes below). 510 * do by session. 511 */ 512 switch (name[0]) { 513 514 case KERN_PROC_PID: 515 /* could do this with just a lookup */ 516 if (p->p_pid != (pid_t)name[1]) 517 continue; 518 break; 519 520 case KERN_PROC_PGRP: 521 /* could do this by traversing pgrp */ 522 if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 523 continue; 524 break; 525 526 case KERN_PROC_TTY: 527 if ((p->p_flag & P_CONTROLT) == 0 || 528 p->p_session == NULL || 529 p->p_session->s_ttyp == NULL || 530 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 531 continue; 532 break; 533 534 case KERN_PROC_UID: 535 if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 536 continue; 537 break; 538 539 case KERN_PROC_RUID: 540 if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 541 continue; 542 break; 543 } 544 545 fill_eproc(p, &eproc); 546 error = SYSCTL_OUT(req,(caddr_t)p, sizeof(struct proc)); 547 if (error) 548 return (error); 549 error = SYSCTL_OUT(req,(caddr_t)&eproc, sizeof(eproc)); 550 if (error) 551 return (error); 552 } 553 if (doingzomb == 0) { 554 p = zombproc; 555 doingzomb++; 556 goto again; 557 } 558 return (0); 559 } 560 561 SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD, 562 sysctl_kern_proc, "Process table"); 563