1*8030Sroot /* kern_proc.c 4.36 82/09/04 */ 236Sbill 336Sbill #include "../h/param.h" 436Sbill #include "../h/systm.h" 536Sbill #include "../h/map.h" 636Sbill #include "../h/mtpr.h" 736Sbill #include "../h/dir.h" 836Sbill #include "../h/user.h" 9*8030Sroot #include "../h/kernel.h" 1036Sbill #include "../h/proc.h" 1136Sbill #include "../h/buf.h" 1236Sbill #include "../h/reg.h" 1336Sbill #include "../h/inode.h" 1436Sbill #include "../h/seg.h" 1536Sbill #include "../h/acct.h" 16215Sbill #include "/usr/include/wait.h" 1736Sbill #include "../h/pte.h" 1836Sbill #include "../h/vm.h" 1936Sbill #include "../h/text.h" 20188Sbill #include "../h/psl.h" 21890Sbill #include "../h/file.h" 227488Skre #include "../h/quota.h" 237497Sroot #include "../h/descrip.h" 247713Sroot #include "../h/uio.h" 25*8030Sroot #include "../h/mbuf.h" 2636Sbill 27*8030Sroot gethostid() 28*8030Sroot { 29*8030Sroot 30*8030Sroot } 31*8030Sroot 32*8030Sroot sethostid() 33*8030Sroot { 34*8030Sroot 35*8030Sroot } 36*8030Sroot 3736Sbill /* 3836Sbill * exec system call, with and without environments. 3936Sbill */ 4036Sbill struct execa { 4136Sbill char *fname; 4236Sbill char **argp; 4336Sbill char **envp; 4436Sbill }; 4536Sbill 46*8030Sroot execv() 4736Sbill { 4836Sbill ((struct execa *)u.u_ap)->envp = NULL; 49*8030Sroot execve(); 5036Sbill } 5136Sbill 52*8030Sroot execve() 5336Sbill { 5436Sbill register nc; 5536Sbill register char *cp; 5636Sbill register struct buf *bp; 5736Sbill register struct execa *uap; 5836Sbill int na, ne, ucp, ap, c; 592301Skre int indir, uid, gid; 602301Skre char *sharg; 6136Sbill struct inode *ip; 6236Sbill swblk_t bno; 636568Smckusic char cfname[MAXNAMLEN + 1]; 642301Skre char cfarg[SHSIZE]; 657748Sroot int resid; 6636Sbill 675991Swnj if ((ip = namei(uchar, 0, 1)) == NULL) 6836Sbill return; 6936Sbill bno = 0; 7036Sbill bp = 0; 712301Skre indir = 0; 722301Skre uid = u.u_uid; 732301Skre gid = u.u_gid; 742301Skre if (ip->i_mode & ISUID) 752301Skre uid = ip->i_uid; 762301Skre if (ip->i_mode & ISGID) 772301Skre gid = ip->i_gid; 782301Skre 792301Skre again: 804827Swnj if (access(ip, IEXEC)) 8136Sbill goto bad; 824827Swnj if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) 832330Swnj goto bad; 844827Swnj if ((ip->i_mode & IFMT) != IFREG || 8536Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 8636Sbill u.u_error = EACCES; 8736Sbill goto bad; 8836Sbill } 892301Skre 9036Sbill /* 912301Skre * Read in first few bytes of file for segment sizes, ux_mag: 922301Skre * 407 = plain executable 932301Skre * 410 = RO text 942301Skre * 413 = demand paged RO text 952301Skre * Also an ASCII line beginning with #! is 962301Skre * the file name of a ``shell'' and arguments may be prepended 972301Skre * to the argument list if given here. 982301Skre * 992301Skre * SHELL NAMES ARE LIMITED IN LENGTH. 1002301Skre * 1012301Skre * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 1022301Skre * THE ASCII LINE. 1032301Skre */ 1047816Sroot u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata), 1057748Sroot 0, 1, &resid); 1064827Swnj if (u.u_error) 1072301Skre goto bad; 1087748Sroot u.u_count = resid; 1097816Sroot #ifndef lint 1104982Swnj if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && 1114982Swnj u.u_exdata.ux_shell[0] != '#') { 1122301Skre u.u_error = ENOEXEC; 1132301Skre goto bad; 1142301Skre } 1157816Sroot #endif 1162301Skre switch (u.u_exdata.ux_mag) { 1172301Skre 1182301Skre case 0407: 1192301Skre u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 1202301Skre u.u_exdata.ux_tsize = 0; 1212301Skre break; 1222301Skre 1232301Skre case 0413: 1242301Skre case 0410: 1252301Skre if (u.u_exdata.ux_tsize == 0) { 1262301Skre u.u_error = ENOEXEC; 1272301Skre goto bad; 1282301Skre } 1292301Skre break; 1302301Skre 1312301Skre default: 1322301Skre if (u.u_exdata.ux_shell[0] != '#' || 1332301Skre u.u_exdata.ux_shell[1] != '!' || 1342301Skre indir) { 1352301Skre u.u_error = ENOEXEC; 1362301Skre goto bad; 1372301Skre } 1382301Skre cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 1392301Skre while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 1402301Skre if (*cp == '\t') 1412301Skre *cp = ' '; 1422301Skre else if (*cp == '\n') { 1432301Skre *cp = '\0'; 1442301Skre break; 1452301Skre } 1462301Skre cp++; 1472301Skre } 1482301Skre if (*cp != '\0') { 1492301Skre u.u_error = ENOEXEC; 1502301Skre goto bad; 1512301Skre } 1522301Skre cp = &u.u_exdata.ux_shell[2]; 1532301Skre while (*cp == ' ') 1542301Skre cp++; 1552301Skre u.u_dirp = cp; 1562301Skre while (*cp && *cp != ' ') 1572301Skre cp++; 1582301Skre sharg = NULL; 1592301Skre if (*cp) { 1602301Skre *cp++ = '\0'; 1612301Skre while (*cp == ' ') 1622301Skre cp++; 1632301Skre if (*cp) { 1642301Skre bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 1652301Skre sharg = cfarg; 1662301Skre } 1672301Skre } 1686568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, 1697816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 1702301Skre indir = 1; 1712301Skre iput(ip); 1725991Swnj ip = namei(schar, 0, 1); 1732301Skre if (ip == NULL) 1742301Skre return; 1752301Skre goto again; 1762301Skre } 1772301Skre 1782301Skre /* 17936Sbill * Collect arguments on "file" in swap space. 18036Sbill */ 18136Sbill na = 0; 18236Sbill ne = 0; 18336Sbill nc = 0; 18436Sbill uap = (struct execa *)u.u_ap; 1852780Swnj if ((bno = rmalloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 18636Sbill swkill(u.u_procp, "exece"); 18736Sbill goto bad; 18836Sbill } 18936Sbill if (bno % CLSIZE) 1902780Swnj panic("execa rmalloc"); 19136Sbill if (uap->argp) for (;;) { 19236Sbill ap = NULL; 1933621Sroot if (indir && (na == 1 || na == 2 && sharg)) 1942301Skre ap = (int)uap->fname; 1952301Skre else if (uap->argp) { 19636Sbill ap = fuword((caddr_t)uap->argp); 19736Sbill uap->argp++; 19836Sbill } 19936Sbill if (ap==NULL && uap->envp) { 20036Sbill uap->argp = NULL; 20136Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 20236Sbill break; 20336Sbill uap->envp++; 20436Sbill ne++; 20536Sbill } 2066568Smckusic if (ap == NULL) 20736Sbill break; 20836Sbill na++; 2094827Swnj if (ap == -1) 21036Sbill u.u_error = EFAULT; 21136Sbill do { 21236Sbill if (nc >= NCARGS-1) 21336Sbill u.u_error = E2BIG; 2142301Skre if (indir && na == 2 && sharg != NULL) 2152301Skre c = *sharg++ & 0377; 2162301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 21736Sbill u.u_error = EFAULT; 21883Sbill if (u.u_error) { 21983Sbill if (bp) 22083Sbill brelse(bp); 22183Sbill bp = 0; 22236Sbill goto badarg; 22383Sbill } 2246568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 22536Sbill if (bp) 22636Sbill bdwrite(bp); 2276568Smckusic bp = getblk(argdev, bno + nc / NBPG, 2286568Smckusic CLSIZE*NBPG); 22936Sbill cp = bp->b_un.b_addr; 23036Sbill } 23136Sbill nc++; 23236Sbill *cp++ = c; 2336568Smckusic } while (c > 0); 23436Sbill } 23536Sbill if (bp) 23636Sbill bdwrite(bp); 23736Sbill bp = 0; 23836Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 2396568Smckusic if (indir) { 2406568Smckusic u.u_dent.d_namlen = strlen(cfname); 2416568Smckusic bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, 2427816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2436568Smckusic } 2442301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 245912Sbill if (u.u_error) { 24636Sbill badarg: 2476568Smckusic for (c = 0; c < nc; c += CLSIZE*NBPG) 2486568Smckusic if (bp = baddr(argdev, bno + c / NBPG, CLSIZE*NBPG)) { 24936Sbill bp->b_flags |= B_AGE; /* throw away */ 25036Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 25136Sbill brelse(bp); 25236Sbill bp = 0; 25336Sbill } 25436Sbill goto bad; 25536Sbill } 25636Sbill 25736Sbill /* 25836Sbill * copy back arglist 25936Sbill */ 26036Sbill ucp = USRSTACK - nc - NBPW; 26136Sbill ap = ucp - na*NBPW - 3*NBPW; 26236Sbill u.u_ar0[SP] = ap; 263132Sbill (void) suword((caddr_t)ap, na-ne); 26436Sbill nc = 0; 26536Sbill for (;;) { 26636Sbill ap += NBPW; 26736Sbill if (na==ne) { 268132Sbill (void) suword((caddr_t)ap, 0); 26936Sbill ap += NBPW; 27036Sbill } 27136Sbill if (--na < 0) 27236Sbill break; 273132Sbill (void) suword((caddr_t)ap, ucp); 27436Sbill do { 2756568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 27636Sbill if (bp) 27736Sbill brelse(bp); 2786568Smckusic bp = bread(argdev, bno + nc / NBPG, 2796568Smckusic CLSIZE*NBPG); 28036Sbill bp->b_flags |= B_AGE; /* throw away */ 28136Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 28236Sbill cp = bp->b_un.b_addr; 28336Sbill } 284132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 28536Sbill nc++; 28636Sbill } while(c&0377); 28736Sbill } 288132Sbill (void) suword((caddr_t)ap, 0); 289132Sbill (void) suword((caddr_t)ucp, 0); 29036Sbill setregs(); 29136Sbill bad: 29236Sbill if (bp) 29336Sbill brelse(bp); 29436Sbill if (bno) 2952780Swnj rmfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); 29636Sbill iput(ip); 29736Sbill } 29836Sbill 29936Sbill /* 30036Sbill * Read in and set up memory for executed file. 30136Sbill */ 3022301Skre getxfile(ip, nargc, uid, gid) 30336Sbill register struct inode *ip; 30436Sbill { 30536Sbill register size_t ts, ds, ss; 3062301Skre int pagi; 30736Sbill 3082301Skre if (u.u_exdata.ux_mag == 0413) 30936Sbill pagi = SPAGI; 3102301Skre else 3112301Skre pagi = 0; 3124827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 3134827Swnj ip->i_count!=1) { 314890Sbill register struct file *fp; 315890Sbill 3164827Swnj for (fp = file; fp < fileNFILE; fp++) { 3177497Sroot if (fp->f_type == DTYPE_FILE && 3187497Sroot fp->f_inode == ip && (fp->f_flag&FWRITE)) { 319890Sbill u.u_error = ETXTBSY; 320890Sbill goto bad; 321890Sbill } 3224827Swnj } 32336Sbill } 32436Sbill 32536Sbill /* 3264827Swnj * Compute text and data sizes and make sure not too large. 32736Sbill */ 32836Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 32936Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 33036Sbill ss = clrnd(SSIZE + btoc(nargc)); 331912Sbill if (chksize(ts, ds, ss)) 332912Sbill goto bad; 3334827Swnj 3344827Swnj /* 3354827Swnj * Make sure enough space to start process. 3364827Swnj */ 337912Sbill u.u_cdmap = zdmap; 338912Sbill u.u_csmap = zdmap; 339912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 340912Sbill goto bad; 34136Sbill 342912Sbill /* 343912Sbill * At this point, committed to the new image! 344912Sbill * Release virtual memory resources of old process, and 345912Sbill * initialize the virtual memory of the new process. 346912Sbill * If we resulted from vfork(), instead wakeup our 347912Sbill * parent who will set SVFDONE when he has taken back 348912Sbill * our resources. 349912Sbill */ 350912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 351912Sbill vrelvm(); 352912Sbill else { 353912Sbill u.u_procp->p_flag &= ~SVFORK; 354912Sbill u.u_procp->p_flag |= SKEEP; 355912Sbill wakeup((caddr_t)u.u_procp); 356912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 357912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 358912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 359912Sbill } 3603592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 361912Sbill u.u_procp->p_flag |= pagi; 362912Sbill u.u_dmap = u.u_cdmap; 363912Sbill u.u_smap = u.u_csmap; 364912Sbill vgetvm(ts, ds, ss); 365912Sbill 3667748Sroot if (pagi == 0) 3677816Sroot u.u_error = 3687816Sroot rdwri(UIO_READ, ip, 3697816Sroot (char*)ctob(ts), (int)u.u_exdata.ux_dsize, 3707816Sroot (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), 3717816Sroot 0, (int *)0); 372912Sbill xalloc(ip, pagi); 373912Sbill if (pagi && u.u_procp->p_textp) 374912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 375912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 376912Sbill 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 37736Sbill 378912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 379912Sbill mtpr(TBIA, 0); 38036Sbill 3817530Sroot if (u.u_error) 3827530Sroot swkill(u.u_procp, "i/o error mapping pages"); 383912Sbill /* 384912Sbill * set SUID/SGID protections, if no tracing 385912Sbill */ 386912Sbill if ((u.u_procp->p_flag&STRC)==0) { 3874827Swnj u.u_uid = uid; 3884827Swnj u.u_procp->p_uid = uid; 3892301Skre u.u_gid = gid; 3907865Sroot entergroup(gid); 391912Sbill } else 392912Sbill psignal(u.u_procp, SIGTRAP); 39336Sbill u.u_tsize = ts; 39436Sbill u.u_dsize = ds; 39536Sbill u.u_ssize = ss; 39636Sbill bad: 397912Sbill return; 39836Sbill } 39936Sbill 40036Sbill /* 40136Sbill * Clear registers on exec 40236Sbill */ 40336Sbill setregs() 40436Sbill { 405173Sbill register int (**rp)(); 40636Sbill register i; 407188Sbill long sigmask; 40836Sbill 4096464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 410188Sbill sigmask <<= 1, rp++) { 411188Sbill switch (*rp) { 412188Sbill 413188Sbill case SIG_IGN: 414188Sbill case SIG_DFL: 415188Sbill case SIG_HOLD: 416188Sbill continue; 417188Sbill 418188Sbill default: 419188Sbill /* 420206Sbill * Normal or deferring catch; revert to default. 421188Sbill */ 422206Sbill (void) spl6(); 423206Sbill *rp = SIG_DFL; 424188Sbill if ((int)*rp & 1) 425188Sbill u.u_procp->p_siga0 |= sigmask; 426188Sbill else 4276327Swnj u.u_procp->p_siga0 &= ~sigmask; 428188Sbill if ((int)*rp & 2) 429188Sbill u.u_procp->p_siga1 |= sigmask; 430188Sbill else 431188Sbill u.u_procp->p_siga1 &= ~sigmask; 432206Sbill (void) spl0(); 433188Sbill continue; 434188Sbill } 435188Sbill } 43636Sbill /* 4374827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 43836Sbill *rp++ = 0; 43936Sbill */ 44036Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 4414827Swnj for (i=0; i<NOFILE; i++) { 44236Sbill if (u.u_pofile[i]&EXCLOSE) { 4437697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 44436Sbill u.u_ofile[i] = NULL; 4457697Ssam u.u_pofile[i] = 0; 44636Sbill } 44736Sbill } 4484827Swnj 44936Sbill /* 45036Sbill * Remember file name for accounting. 45136Sbill */ 45236Sbill u.u_acflag &= ~AFORK; 4536568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm, 4547816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 45536Sbill } 45636Sbill 45736Sbill /* 4584827Swnj * Exit system call: pass back caller's arg 45936Sbill */ 46036Sbill rexit() 46136Sbill { 46236Sbill register struct a { 46336Sbill int rval; 46436Sbill } *uap; 46536Sbill 46636Sbill uap = (struct a *)u.u_ap; 46736Sbill exit((uap->rval & 0377) << 8); 46836Sbill } 46936Sbill 47036Sbill /* 47136Sbill * Release resources. 47236Sbill * Save u. area for parent to look at. 47336Sbill * Enter zombie state. 47436Sbill * Wake up parent and init processes, 47536Sbill * and dispose of children. 47636Sbill */ 47736Sbill exit(rv) 47836Sbill { 47936Sbill register int i; 48036Sbill register struct proc *p, *q; 48136Sbill register int x; 48236Sbill 48336Sbill #ifdef PGINPROF 48436Sbill vmsizmon(); 48536Sbill #endif 48636Sbill p = u.u_procp; 48736Sbill p->p_flag &= ~(STRC|SULOCK); 48836Sbill p->p_flag |= SWEXIT; 489*8030Sroot timerclear(&p->p_seltimer); 490188Sbill (void) spl6(); 491188Sbill if ((int)SIG_IGN & 1) 492188Sbill p->p_siga0 = ~0; 493188Sbill else 494188Sbill p->p_siga0 = 0; 495188Sbill if ((int)SIG_IGN & 2) 496188Sbill p->p_siga1 = ~0; 497188Sbill else 498206Sbill p->p_siga1 = 0; 499188Sbill (void) spl0(); 5001399Sbill p->p_cpticks = 0; 5011399Sbill p->p_pctcpu = 0; 5024827Swnj for (i=0; i<NSIG; i++) 503173Sbill u.u_signal[i] = SIG_IGN; 50436Sbill /* 50536Sbill * Release virtual memory. If we resulted from 50636Sbill * a vfork(), instead give the resources back to 50736Sbill * the parent. 50836Sbill */ 50936Sbill if ((p->p_flag & SVFORK) == 0) 51036Sbill vrelvm(); 51136Sbill else { 51236Sbill p->p_flag &= ~SVFORK; 51336Sbill wakeup((caddr_t)p); 51436Sbill while ((p->p_flag & SVFDONE) == 0) 51536Sbill sleep((caddr_t)p, PZERO - 1); 51636Sbill p->p_flag &= ~SVFDONE; 51736Sbill } 5187697Ssam for (i = 0; i < NOFILE; i++) { 5197697Ssam #ifdef notdef 5207697Ssam /* why was this like this? */ 52136Sbill f = u.u_ofile[i]; 52236Sbill u.u_ofile[i] = NULL; 5235581Swnj closef(f, 1); 5247697Ssam #else 5257697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 5267697Ssam u.u_ofile[i] = NULL; 5277697Ssam u.u_pofile[i] = 0; 5287697Ssam #endif 52936Sbill } 5304827Swnj ilock(u.u_cdir); 53136Sbill iput(u.u_cdir); 53236Sbill if (u.u_rdir) { 5334827Swnj ilock(u.u_rdir); 53436Sbill iput(u.u_rdir); 53536Sbill } 536*8030Sroot u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 53736Sbill acct(); 5387488Skre #ifdef QUOTA 5397488Skre qclean(); 5407488Skre #endif 54136Sbill vrelpt(u.u_procp); 54236Sbill vrelu(u.u_procp, 0); 5435630Swnj (void) spl5(); /* hack for mem alloc race XXX */ 54436Sbill multprog--; 545931Sbill p->p_stat = SZOMB; 546307Sbill noproc = 1; 54736Sbill i = PIDHASH(p->p_pid); 54836Sbill x = p - proc; 54936Sbill if (pidhash[i] == x) 55036Sbill pidhash[i] = p->p_idhash; 55136Sbill else { 55236Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 55336Sbill if (proc[i].p_idhash == x) { 55436Sbill proc[i].p_idhash = p->p_idhash; 55536Sbill goto done; 55636Sbill } 55736Sbill panic("exit"); 55836Sbill } 5591409Sbill if (p->p_pid == 1) 5601409Sbill panic("init died"); 56136Sbill done: 562*8030Sroot p->p_xstat = rv; 563*8030Sroot { struct mbuf *m = m_getclr(M_DONTWAIT); p->p_ru = mtod(m, struct rusage *); } 564*8030Sroot *p->p_ru = u.u_ru; 565*8030Sroot ruadd(p->p_ru, &u.u_cru); 5664827Swnj for (q = proc; q < procNPROC; q++) 5674827Swnj if (q->p_pptr == p) { 5687488Skre if (q->p_osptr) 5697488Skre q->p_osptr->p_ysptr = q->p_ysptr; 5707488Skre if (q->p_ysptr) 5717488Skre q->p_ysptr->p_osptr = q->p_osptr; 5727488Skre if (proc[1].p_cptr) 5737488Skre proc[1].p_cptr->p_ysptr = q; 5747488Skre q->p_osptr = proc[1].p_cptr; 5757488Skre q->p_ysptr = NULL; 5767488Skre proc[1].p_cptr = q; 5777488Skre 578188Sbill q->p_pptr = &proc[1]; 579188Sbill q->p_ppid = 1; 58036Sbill wakeup((caddr_t)&proc[1]); 581188Sbill /* 582212Sbill * Traced processes are killed 583188Sbill * since their existence means someone is screwing up. 584354Sbill * Stopped processes are sent a hangup and a continue. 585212Sbill * This is designed to be ``safe'' for setuid 586212Sbill * processes since they must be willing to tolerate 587212Sbill * hangups anyways. 588188Sbill */ 589212Sbill if (q->p_flag&STRC) { 590188Sbill q->p_flag &= ~STRC; 591188Sbill psignal(q, SIGKILL); 592212Sbill } else if (q->p_stat == SSTOP) { 593212Sbill psignal(q, SIGHUP); 594212Sbill psignal(q, SIGCONT); 595188Sbill } 596215Sbill /* 597215Sbill * Protect this process from future 5985619Swnj * tty signals, clear TSTP/TTIN/TTOU if pending. 599215Sbill */ 6001788Sbill (void) spgrp(q, -1); 60136Sbill } 6026464Swnj psignal(p->p_pptr, SIGCHLD); 603188Sbill wakeup((caddr_t)p->p_pptr); 60436Sbill swtch(); 60536Sbill } 60636Sbill 60736Sbill wait() 60836Sbill { 609*8030Sroot struct rusage ru, *rup; 61036Sbill 611188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 612*8030Sroot wait1(0, (struct rusage *)0); 613188Sbill return; 614188Sbill } 615*8030Sroot rup = (struct rusage *)u.u_ar0[R1]; 616*8030Sroot wait1(u.u_ar0[R0], &ru); 617188Sbill if (u.u_error) 618188Sbill return; 619*8030Sroot (void) copyout((caddr_t)&ru, (caddr_t)rup, sizeof (struct rusage)); 62036Sbill } 62136Sbill 62236Sbill /* 62336Sbill * Wait system call. 62436Sbill * Search for a terminated (zombie) child, 62536Sbill * finally lay it to rest, and collect its status. 62636Sbill * Look also for stopped (traced) children, 62736Sbill * and pass back status from them. 62836Sbill */ 629*8030Sroot wait1(options, ru) 630*8030Sroot register int options; 631*8030Sroot struct rusage *ru; 63236Sbill { 63336Sbill register f; 6347488Skre register struct proc *p, *q; 63536Sbill 63636Sbill f = 0; 63736Sbill loop: 6384827Swnj for (p = proc; p < procNPROC; p++) 6394827Swnj if (p->p_pptr == u.u_procp) { 64036Sbill f++; 6414827Swnj if (p->p_stat == SZOMB) { 64236Sbill u.u_r.r_val1 = p->p_pid; 643*8030Sroot u.u_r.r_val2 = p->p_xstat; 644*8030Sroot p->p_xstat = 0; 645*8030Sroot if (ru) 646*8030Sroot *ru = *p->p_ru; 647*8030Sroot ruadd(&u.u_cru, p->p_ru); 648*8030Sroot m_free(dtom(p->p_ru)); 649*8030Sroot p->p_ru = 0; 65036Sbill p->p_stat = NULL; 65136Sbill p->p_pid = 0; 65236Sbill p->p_ppid = 0; 6537488Skre if (q = p->p_ysptr) 6547488Skre q->p_osptr = p->p_osptr; 6557488Skre if (q = p->p_osptr) 6567488Skre q->p_ysptr = p->p_ysptr; 6577488Skre if ((q = p->p_pptr)->p_cptr == p) 6587488Skre q->p_cptr = p->p_osptr; 659188Sbill p->p_pptr = 0; 6607488Skre p->p_ysptr = 0; 6617488Skre p->p_osptr = 0; 6627488Skre p->p_cptr = 0; 66336Sbill p->p_sig = 0; 664188Sbill p->p_siga0 = 0; 665188Sbill p->p_siga1 = 0; 66636Sbill p->p_pgrp = 0; 66736Sbill p->p_flag = 0; 66836Sbill p->p_wchan = 0; 669188Sbill p->p_cursig = 0; 67036Sbill return; 67136Sbill } 672188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 673188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 674188Sbill p->p_flag |= SWTED; 675188Sbill u.u_r.r_val1 = p->p_pid; 676188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 677188Sbill return; 67836Sbill } 67936Sbill } 680188Sbill if (f==0) { 681188Sbill u.u_error = ECHILD; 682188Sbill return; 68336Sbill } 684188Sbill if (options&WNOHANG) { 685188Sbill u.u_r.r_val1 = 0; 686188Sbill return; 687188Sbill } 688912Sbill if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 689188Sbill u.u_eosys = RESTARTSYS; 690188Sbill return; 691188Sbill } 692188Sbill sleep((caddr_t)u.u_procp, PWAIT); 693188Sbill goto loop; 69436Sbill } 69536Sbill 69636Sbill /* 69736Sbill * fork system call. 69836Sbill */ 69936Sbill fork() 70036Sbill { 70136Sbill 70236Sbill u.u_cdmap = zdmap; 70336Sbill u.u_csmap = zdmap; 70436Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 70536Sbill u.u_r.r_val2 = 0; 70636Sbill return; 70736Sbill } 70836Sbill fork1(0); 70936Sbill } 71036Sbill 71136Sbill fork1(isvfork) 71236Sbill { 71336Sbill register struct proc *p1, *p2; 7147488Skre #ifndef QUOTA 71536Sbill register a; 71636Sbill 71736Sbill a = 0; 7187488Skre #else 7197488Skre if (u.u_quota != NOQUOT && u.u_quota->q_plim && 7207488Skre u.u_quota->q_cnt >= u.u_quota->q_plim) { 7217488Skre u.u_error = EPROCLIM; 7227488Skre return; 7237488Skre } 7247488Skre #endif 72536Sbill p2 = NULL; 7264827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 7277488Skre #ifdef QUOTA 7287488Skre if (p1->p_stat == NULL) { 7297488Skre p2 = p1; 7307488Skre break; 7317488Skre } 7327488Skre #else 73336Sbill if (p1->p_stat==NULL && p2==NULL) 73436Sbill p2 = p1; 73536Sbill else { 73636Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 73736Sbill a++; 73836Sbill } 7397488Skre #endif 74036Sbill } 74136Sbill /* 74236Sbill * Disallow if 74336Sbill * No processes at all; 74436Sbill * not su and too many procs owned; or 74536Sbill * not su and would take last slot. 74636Sbill */ 7472938Swnj if (p2==NULL) 7482938Swnj tablefull("proc"); 7497488Skre #ifdef QUOTA 7507488Skre if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { 7517488Skre #else 7522741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 7537488Skre #endif 75436Sbill u.u_error = EAGAIN; 75536Sbill if (!isvfork) { 756132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 757132Sbill (void) vsexpand(0, &u.u_csmap, 1); 75836Sbill } 75936Sbill goto out; 76036Sbill } 76136Sbill p1 = u.u_procp; 7624827Swnj if (newproc(isvfork)) { 76336Sbill u.u_r.r_val1 = p1->p_pid; 76436Sbill u.u_r.r_val2 = 1; /* child */ 765*8030Sroot u.u_start = time.tv_sec; 76636Sbill u.u_acflag = AFORK; 7677488Skre #ifdef QUOTA 7687488Skre u.u_qflags &= ~QUF_LOGIN; 7697488Skre #endif 77036Sbill return; 77136Sbill } 77236Sbill u.u_r.r_val1 = p2->p_pid; 77336Sbill 77436Sbill out: 77536Sbill u.u_r.r_val2 = 0; 77636Sbill } 77736Sbill 7787497Sroot spgrp(top, npgrp) 7797497Sroot register struct proc *top; 7807497Sroot { 7817497Sroot register struct proc *pp, *p; 7827497Sroot int f = 0; 7837497Sroot 7847497Sroot for (p = top; npgrp == -1 || u.u_uid == p->p_uid || 7857497Sroot !u.u_uid || inferior(p); p = pp) { 7867497Sroot if (npgrp == -1) { 7877497Sroot #define bit(a) (1<<(a-1)) 7887497Sroot p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 7897497Sroot } else 7907497Sroot p->p_pgrp = npgrp; 7917497Sroot f++; 7927497Sroot /* 7937497Sroot * Search for children. 7947497Sroot */ 7957497Sroot for (pp = proc; pp < procNPROC; pp++) 7967497Sroot if (pp->p_pptr == p) 7977497Sroot goto cont; 7987497Sroot /* 7997497Sroot * Search for siblings. 8007497Sroot */ 8017497Sroot for (; p != top; p = p->p_pptr) 8027497Sroot for (pp = p + 1; pp < procNPROC; pp++) 8037497Sroot if (pp->p_pptr == p->p_pptr) 8047497Sroot goto cont; 8057497Sroot break; 8067497Sroot cont: 8077497Sroot ; 8087497Sroot } 8097497Sroot return (f); 8107497Sroot } 8117497Sroot 81236Sbill /* 8137497Sroot * Is p an inferior of the current process? 81436Sbill */ 8157497Sroot inferior(p) 8167816Sroot register struct proc *p; 81736Sbill { 81836Sbill 8197497Sroot for (; p != u.u_procp; p = p->p_pptr) 8207497Sroot if (p->p_ppid == 0) 8217497Sroot return (0); 8227497Sroot return (1); 82336Sbill } 8247816Sroot 8257816Sroot struct proc * 8267816Sroot pfind(pid) 8277816Sroot int pid; 8287816Sroot { 8297816Sroot register struct proc *p; 8307816Sroot 8317816Sroot for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 8327816Sroot if (p->p_pid == pid) 8337816Sroot return (p); 8347816Sroot return ((struct proc *)0); 8357816Sroot } 836