1*7713Sroot /* kern_proc.c 4.31 82/08/11 */ 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" 936Sbill #include "../h/proc.h" 1036Sbill #include "../h/buf.h" 1136Sbill #include "../h/reg.h" 1236Sbill #include "../h/inode.h" 1336Sbill #include "../h/seg.h" 1436Sbill #include "../h/acct.h" 15215Sbill #include "/usr/include/wait.h" 1636Sbill #include "../h/pte.h" 1736Sbill #include "../h/vm.h" 1836Sbill #include "../h/text.h" 19188Sbill #include "../h/psl.h" 20879Sbill #include "../h/vlimit.h" 21890Sbill #include "../h/file.h" 227488Skre #include "../h/quota.h" 237497Sroot #include "../h/descrip.h" 24*7713Sroot #include "../h/uio.h" 2536Sbill 2636Sbill /* 2736Sbill * exec system call, with and without environments. 2836Sbill */ 2936Sbill struct execa { 3036Sbill char *fname; 3136Sbill char **argp; 3236Sbill char **envp; 3336Sbill }; 3436Sbill 3536Sbill exec() 3636Sbill { 3736Sbill ((struct execa *)u.u_ap)->envp = NULL; 3836Sbill exece(); 3936Sbill } 4036Sbill 4136Sbill exece() 4236Sbill { 4336Sbill register nc; 4436Sbill register char *cp; 4536Sbill register struct buf *bp; 4636Sbill register struct execa *uap; 4736Sbill int na, ne, ucp, ap, c; 482301Skre int indir, uid, gid; 492301Skre char *sharg; 5036Sbill struct inode *ip; 5136Sbill swblk_t bno; 526568Smckusic char cfname[MAXNAMLEN + 1]; 532301Skre char cfarg[SHSIZE]; 54*7713Sroot struct uio uio; 55*7713Sroot struct iovec iovec; 5636Sbill 575991Swnj if ((ip = namei(uchar, 0, 1)) == NULL) 5836Sbill return; 5936Sbill bno = 0; 6036Sbill bp = 0; 612301Skre indir = 0; 622301Skre uid = u.u_uid; 632301Skre gid = u.u_gid; 642301Skre if (ip->i_mode & ISUID) 652301Skre uid = ip->i_uid; 662301Skre if (ip->i_mode & ISGID) 672301Skre gid = ip->i_gid; 682301Skre 692301Skre again: 704827Swnj if (access(ip, IEXEC)) 7136Sbill goto bad; 724827Swnj if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) 732330Swnj goto bad; 744827Swnj if ((ip->i_mode & IFMT) != IFREG || 7536Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 7636Sbill u.u_error = EACCES; 7736Sbill goto bad; 7836Sbill } 792301Skre 8036Sbill /* 812301Skre * Read in first few bytes of file for segment sizes, ux_mag: 822301Skre * 407 = plain executable 832301Skre * 410 = RO text 842301Skre * 413 = demand paged RO text 852301Skre * Also an ASCII line beginning with #! is 862301Skre * the file name of a ``shell'' and arguments may be prepended 872301Skre * to the argument list if given here. 882301Skre * 892301Skre * SHELL NAMES ARE LIMITED IN LENGTH. 902301Skre * 912301Skre * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 922301Skre * THE ASCII LINE. 932301Skre */ 94*7713Sroot uio.uio_iov = &iovec; 95*7713Sroot uio.uio_iovcnt = 1; 96*7713Sroot iovec.iov_base = (caddr_t)&u.u_exdata; 97*7713Sroot iovec.iov_len = sizeof (u.u_exdata); 98*7713Sroot uio.uio_offset = 0; 99*7713Sroot uio.uio_segflg = 1; 100*7713Sroot u.u_error = readip(ip, &uio); 1014827Swnj if (u.u_error) 1022301Skre goto bad; 103*7713Sroot u.u_count = uio.uio_resid; 1044982Swnj if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && 1054982Swnj u.u_exdata.ux_shell[0] != '#') { 1062301Skre u.u_error = ENOEXEC; 1072301Skre goto bad; 1082301Skre } 1092301Skre switch (u.u_exdata.ux_mag) { 1102301Skre 1112301Skre case 0407: 1122301Skre u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 1132301Skre u.u_exdata.ux_tsize = 0; 1142301Skre break; 1152301Skre 1162301Skre case 0413: 1172301Skre case 0410: 1182301Skre if (u.u_exdata.ux_tsize == 0) { 1192301Skre u.u_error = ENOEXEC; 1202301Skre goto bad; 1212301Skre } 1222301Skre break; 1232301Skre 1242301Skre default: 1252301Skre if (u.u_exdata.ux_shell[0] != '#' || 1262301Skre u.u_exdata.ux_shell[1] != '!' || 1272301Skre indir) { 1282301Skre u.u_error = ENOEXEC; 1292301Skre goto bad; 1302301Skre } 1312301Skre cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 1322301Skre while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 1332301Skre if (*cp == '\t') 1342301Skre *cp = ' '; 1352301Skre else if (*cp == '\n') { 1362301Skre *cp = '\0'; 1372301Skre break; 1382301Skre } 1392301Skre cp++; 1402301Skre } 1412301Skre if (*cp != '\0') { 1422301Skre u.u_error = ENOEXEC; 1432301Skre goto bad; 1442301Skre } 1452301Skre cp = &u.u_exdata.ux_shell[2]; 1462301Skre while (*cp == ' ') 1472301Skre cp++; 1482301Skre u.u_dirp = cp; 1492301Skre while (*cp && *cp != ' ') 1502301Skre cp++; 1512301Skre sharg = NULL; 1522301Skre if (*cp) { 1532301Skre *cp++ = '\0'; 1542301Skre while (*cp == ' ') 1552301Skre cp++; 1562301Skre if (*cp) { 1572301Skre bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 1582301Skre sharg = cfarg; 1592301Skre } 1602301Skre } 1616568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, 1626568Smckusic u.u_dent.d_namlen + 1); 1632301Skre indir = 1; 1642301Skre iput(ip); 1655991Swnj ip = namei(schar, 0, 1); 1662301Skre if (ip == NULL) 1672301Skre return; 1682301Skre goto again; 1692301Skre } 1702301Skre 1712301Skre /* 17236Sbill * Collect arguments on "file" in swap space. 17336Sbill */ 17436Sbill na = 0; 17536Sbill ne = 0; 17636Sbill nc = 0; 17736Sbill uap = (struct execa *)u.u_ap; 1782780Swnj if ((bno = rmalloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 17936Sbill swkill(u.u_procp, "exece"); 18036Sbill goto bad; 18136Sbill } 18236Sbill if (bno % CLSIZE) 1832780Swnj panic("execa rmalloc"); 18436Sbill if (uap->argp) for (;;) { 18536Sbill ap = NULL; 1863621Sroot if (indir && (na == 1 || na == 2 && sharg)) 1872301Skre ap = (int)uap->fname; 1882301Skre else if (uap->argp) { 18936Sbill ap = fuword((caddr_t)uap->argp); 19036Sbill uap->argp++; 19136Sbill } 19236Sbill if (ap==NULL && uap->envp) { 19336Sbill uap->argp = NULL; 19436Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 19536Sbill break; 19636Sbill uap->envp++; 19736Sbill ne++; 19836Sbill } 1996568Smckusic if (ap == NULL) 20036Sbill break; 20136Sbill na++; 2024827Swnj if (ap == -1) 20336Sbill u.u_error = EFAULT; 20436Sbill do { 20536Sbill if (nc >= NCARGS-1) 20636Sbill u.u_error = E2BIG; 2072301Skre if (indir && na == 2 && sharg != NULL) 2082301Skre c = *sharg++ & 0377; 2092301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 21036Sbill u.u_error = EFAULT; 21183Sbill if (u.u_error) { 21283Sbill if (bp) 21383Sbill brelse(bp); 21483Sbill bp = 0; 21536Sbill goto badarg; 21683Sbill } 2176568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 21836Sbill if (bp) 21936Sbill bdwrite(bp); 2206568Smckusic bp = getblk(argdev, bno + nc / NBPG, 2216568Smckusic CLSIZE*NBPG); 22236Sbill cp = bp->b_un.b_addr; 22336Sbill } 22436Sbill nc++; 22536Sbill *cp++ = c; 2266568Smckusic } while (c > 0); 22736Sbill } 22836Sbill if (bp) 22936Sbill bdwrite(bp); 23036Sbill bp = 0; 23136Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 2326568Smckusic if (indir) { 2336568Smckusic u.u_dent.d_namlen = strlen(cfname); 2346568Smckusic bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, 2356568Smckusic u.u_dent.d_namlen + 1); 2366568Smckusic } 2372301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 238912Sbill if (u.u_error) { 23936Sbill badarg: 2406568Smckusic for (c = 0; c < nc; c += CLSIZE*NBPG) 2416568Smckusic if (bp = baddr(argdev, bno + c / NBPG, CLSIZE*NBPG)) { 24236Sbill bp->b_flags |= B_AGE; /* throw away */ 24336Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 24436Sbill brelse(bp); 24536Sbill bp = 0; 24636Sbill } 24736Sbill goto bad; 24836Sbill } 24936Sbill 25036Sbill /* 25136Sbill * copy back arglist 25236Sbill */ 25336Sbill ucp = USRSTACK - nc - NBPW; 25436Sbill ap = ucp - na*NBPW - 3*NBPW; 25536Sbill u.u_ar0[SP] = ap; 256132Sbill (void) suword((caddr_t)ap, na-ne); 25736Sbill nc = 0; 25836Sbill for (;;) { 25936Sbill ap += NBPW; 26036Sbill if (na==ne) { 261132Sbill (void) suword((caddr_t)ap, 0); 26236Sbill ap += NBPW; 26336Sbill } 26436Sbill if (--na < 0) 26536Sbill break; 266132Sbill (void) suword((caddr_t)ap, ucp); 26736Sbill do { 2686568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 26936Sbill if (bp) 27036Sbill brelse(bp); 2716568Smckusic bp = bread(argdev, bno + nc / NBPG, 2726568Smckusic CLSIZE*NBPG); 27336Sbill bp->b_flags |= B_AGE; /* throw away */ 27436Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 27536Sbill cp = bp->b_un.b_addr; 27636Sbill } 277132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 27836Sbill nc++; 27936Sbill } while(c&0377); 28036Sbill } 281132Sbill (void) suword((caddr_t)ap, 0); 282132Sbill (void) suword((caddr_t)ucp, 0); 28336Sbill setregs(); 28436Sbill bad: 28536Sbill if (bp) 28636Sbill brelse(bp); 28736Sbill if (bno) 2882780Swnj rmfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); 28936Sbill iput(ip); 29036Sbill } 29136Sbill 29236Sbill /* 29336Sbill * Read in and set up memory for executed file. 29436Sbill */ 2952301Skre getxfile(ip, nargc, uid, gid) 29636Sbill register struct inode *ip; 29736Sbill { 29836Sbill register size_t ts, ds, ss; 2992301Skre int pagi; 30036Sbill 3012301Skre if (u.u_exdata.ux_mag == 0413) 30236Sbill pagi = SPAGI; 3032301Skre else 3042301Skre pagi = 0; 3054827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 3064827Swnj ip->i_count!=1) { 307890Sbill register struct file *fp; 308890Sbill 3094827Swnj for (fp = file; fp < fileNFILE; fp++) { 3107497Sroot if (fp->f_type == DTYPE_FILE && 3117497Sroot fp->f_inode == ip && (fp->f_flag&FWRITE)) { 312890Sbill u.u_error = ETXTBSY; 313890Sbill goto bad; 314890Sbill } 3154827Swnj } 31636Sbill } 31736Sbill 31836Sbill /* 3194827Swnj * Compute text and data sizes and make sure not too large. 32036Sbill */ 32136Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 32236Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 32336Sbill ss = clrnd(SSIZE + btoc(nargc)); 324912Sbill if (chksize(ts, ds, ss)) 325912Sbill goto bad; 3264827Swnj 3274827Swnj /* 3284827Swnj * Make sure enough space to start process. 3294827Swnj */ 330912Sbill u.u_cdmap = zdmap; 331912Sbill u.u_csmap = zdmap; 332912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 333912Sbill goto bad; 33436Sbill 335912Sbill /* 336912Sbill * At this point, committed to the new image! 337912Sbill * Release virtual memory resources of old process, and 338912Sbill * initialize the virtual memory of the new process. 339912Sbill * If we resulted from vfork(), instead wakeup our 340912Sbill * parent who will set SVFDONE when he has taken back 341912Sbill * our resources. 342912Sbill */ 343912Sbill u.u_prof.pr_scale = 0; 344912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 345912Sbill vrelvm(); 346912Sbill else { 347912Sbill u.u_procp->p_flag &= ~SVFORK; 348912Sbill u.u_procp->p_flag |= SKEEP; 349912Sbill wakeup((caddr_t)u.u_procp); 350912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 351912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 352912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 353912Sbill } 3543592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 355912Sbill u.u_procp->p_flag |= pagi; 356912Sbill u.u_dmap = u.u_cdmap; 357912Sbill u.u_smap = u.u_csmap; 358912Sbill vgetvm(ts, ds, ss); 359912Sbill 360912Sbill if (pagi == 0) { 36136Sbill /* 362912Sbill * Read in data segment. 36336Sbill */ 364912Sbill u.u_base = (char *)ctob(ts); 365912Sbill u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; 366912Sbill u.u_count = u.u_exdata.ux_dsize; 367912Sbill readi(ip); 368912Sbill } 369912Sbill xalloc(ip, pagi); 370912Sbill if (pagi && u.u_procp->p_textp) 371912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 372912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 373912Sbill 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 37436Sbill 375912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 376912Sbill mtpr(TBIA, 0); 37736Sbill 3787530Sroot if (u.u_error) 3797530Sroot swkill(u.u_procp, "i/o error mapping pages"); 380912Sbill /* 381912Sbill * set SUID/SGID protections, if no tracing 382912Sbill */ 383912Sbill if ((u.u_procp->p_flag&STRC)==0) { 3844827Swnj u.u_uid = uid; 3854827Swnj u.u_procp->p_uid = uid; 3862301Skre u.u_gid = gid; 3875856Swnj u.u_grps[gid/(sizeof(int)*8)] |= 1 << (gid%(sizeof(int)*8)); 388912Sbill } else 389912Sbill psignal(u.u_procp, SIGTRAP); 39036Sbill u.u_tsize = ts; 39136Sbill u.u_dsize = ds; 39236Sbill u.u_ssize = ss; 39336Sbill bad: 394912Sbill return; 39536Sbill } 39636Sbill 39736Sbill /* 39836Sbill * Clear registers on exec 39936Sbill */ 40036Sbill setregs() 40136Sbill { 402173Sbill register int (**rp)(); 40336Sbill register i; 404188Sbill long sigmask; 40536Sbill 4066464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 407188Sbill sigmask <<= 1, rp++) { 408188Sbill switch (*rp) { 409188Sbill 410188Sbill case SIG_IGN: 411188Sbill case SIG_DFL: 412188Sbill case SIG_HOLD: 413188Sbill continue; 414188Sbill 415188Sbill default: 416188Sbill /* 417206Sbill * Normal or deferring catch; revert to default. 418188Sbill */ 419206Sbill (void) spl6(); 420206Sbill *rp = SIG_DFL; 421188Sbill if ((int)*rp & 1) 422188Sbill u.u_procp->p_siga0 |= sigmask; 423188Sbill else 4246327Swnj u.u_procp->p_siga0 &= ~sigmask; 425188Sbill if ((int)*rp & 2) 426188Sbill u.u_procp->p_siga1 |= sigmask; 427188Sbill else 428188Sbill u.u_procp->p_siga1 &= ~sigmask; 429206Sbill (void) spl0(); 430188Sbill continue; 431188Sbill } 432188Sbill } 43336Sbill /* 4344827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 43536Sbill *rp++ = 0; 43636Sbill */ 43736Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 4384827Swnj for (i=0; i<NOFILE; i++) { 43936Sbill if (u.u_pofile[i]&EXCLOSE) { 4407697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 44136Sbill u.u_ofile[i] = NULL; 4427697Ssam u.u_pofile[i] = 0; 44336Sbill } 44436Sbill } 4454827Swnj 44636Sbill /* 44736Sbill * Remember file name for accounting. 44836Sbill */ 44936Sbill u.u_acflag &= ~AFORK; 4506568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm, 4516568Smckusic u.u_dent.d_namlen + 1); 45236Sbill } 45336Sbill 45436Sbill /* 4554827Swnj * Exit system call: pass back caller's arg 45636Sbill */ 45736Sbill rexit() 45836Sbill { 45936Sbill register struct a { 46036Sbill int rval; 46136Sbill } *uap; 46236Sbill 46336Sbill uap = (struct a *)u.u_ap; 46436Sbill exit((uap->rval & 0377) << 8); 46536Sbill } 46636Sbill 46736Sbill /* 46836Sbill * Release resources. 46936Sbill * Save u. area for parent to look at. 47036Sbill * Enter zombie state. 47136Sbill * Wake up parent and init processes, 47236Sbill * and dispose of children. 47336Sbill */ 47436Sbill exit(rv) 47536Sbill { 47636Sbill register int i; 47736Sbill register struct proc *p, *q; 47836Sbill register int x; 47936Sbill 48036Sbill #ifdef PGINPROF 48136Sbill vmsizmon(); 48236Sbill #endif 48336Sbill p = u.u_procp; 48436Sbill p->p_flag &= ~(STRC|SULOCK); 48536Sbill p->p_flag |= SWEXIT; 48636Sbill p->p_clktim = 0; 487188Sbill (void) spl6(); 488188Sbill if ((int)SIG_IGN & 1) 489188Sbill p->p_siga0 = ~0; 490188Sbill else 491188Sbill p->p_siga0 = 0; 492188Sbill if ((int)SIG_IGN & 2) 493188Sbill p->p_siga1 = ~0; 494188Sbill else 495206Sbill p->p_siga1 = 0; 496188Sbill (void) spl0(); 4971399Sbill p->p_cpticks = 0; 4981399Sbill p->p_pctcpu = 0; 4994827Swnj for (i=0; i<NSIG; i++) 500173Sbill u.u_signal[i] = SIG_IGN; 50136Sbill /* 50236Sbill * Release virtual memory. If we resulted from 50336Sbill * a vfork(), instead give the resources back to 50436Sbill * the parent. 50536Sbill */ 50636Sbill if ((p->p_flag & SVFORK) == 0) 50736Sbill vrelvm(); 50836Sbill else { 50936Sbill p->p_flag &= ~SVFORK; 51036Sbill wakeup((caddr_t)p); 51136Sbill while ((p->p_flag & SVFDONE) == 0) 51236Sbill sleep((caddr_t)p, PZERO - 1); 51336Sbill p->p_flag &= ~SVFDONE; 51436Sbill } 5157697Ssam for (i = 0; i < NOFILE; i++) { 5167697Ssam #ifdef notdef 5177697Ssam /* why was this like this? */ 51836Sbill f = u.u_ofile[i]; 51936Sbill u.u_ofile[i] = NULL; 5205581Swnj closef(f, 1); 5217697Ssam #else 5227697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 5237697Ssam u.u_ofile[i] = NULL; 5247697Ssam u.u_pofile[i] = 0; 5257697Ssam #endif 52636Sbill } 5274827Swnj ilock(u.u_cdir); 52836Sbill iput(u.u_cdir); 52936Sbill if (u.u_rdir) { 5304827Swnj ilock(u.u_rdir); 53136Sbill iput(u.u_rdir); 53236Sbill } 533363Sbill u.u_limit[LIM_FSIZE] = INFINITY; 53436Sbill acct(); 5357488Skre #ifdef QUOTA 5367488Skre qclean(); 5377488Skre #endif 53836Sbill vrelpt(u.u_procp); 53936Sbill vrelu(u.u_procp, 0); 5405630Swnj (void) spl5(); /* hack for mem alloc race XXX */ 54136Sbill multprog--; 542931Sbill p->p_stat = SZOMB; 543307Sbill noproc = 1; 54436Sbill i = PIDHASH(p->p_pid); 54536Sbill x = p - proc; 54636Sbill if (pidhash[i] == x) 54736Sbill pidhash[i] = p->p_idhash; 54836Sbill else { 54936Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 55036Sbill if (proc[i].p_idhash == x) { 55136Sbill proc[i].p_idhash = p->p_idhash; 55236Sbill goto done; 55336Sbill } 55436Sbill panic("exit"); 55536Sbill } 5561409Sbill if (p->p_pid == 1) 5571409Sbill panic("init died"); 55836Sbill done: 55936Sbill ((struct xproc *)p)->xp_xstat = rv; /* overlay */ 56036Sbill ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ 56136Sbill vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); 5624827Swnj for (q = proc; q < procNPROC; q++) 5634827Swnj if (q->p_pptr == p) { 5647488Skre if (q->p_osptr) 5657488Skre q->p_osptr->p_ysptr = q->p_ysptr; 5667488Skre if (q->p_ysptr) 5677488Skre q->p_ysptr->p_osptr = q->p_osptr; 5687488Skre if (proc[1].p_cptr) 5697488Skre proc[1].p_cptr->p_ysptr = q; 5707488Skre q->p_osptr = proc[1].p_cptr; 5717488Skre q->p_ysptr = NULL; 5727488Skre proc[1].p_cptr = q; 5737488Skre 574188Sbill q->p_pptr = &proc[1]; 575188Sbill q->p_ppid = 1; 57636Sbill wakeup((caddr_t)&proc[1]); 577188Sbill /* 578212Sbill * Traced processes are killed 579188Sbill * since their existence means someone is screwing up. 580354Sbill * Stopped processes are sent a hangup and a continue. 581212Sbill * This is designed to be ``safe'' for setuid 582212Sbill * processes since they must be willing to tolerate 583212Sbill * hangups anyways. 584188Sbill */ 585212Sbill if (q->p_flag&STRC) { 586188Sbill q->p_flag &= ~STRC; 587188Sbill psignal(q, SIGKILL); 588212Sbill } else if (q->p_stat == SSTOP) { 589212Sbill psignal(q, SIGHUP); 590212Sbill psignal(q, SIGCONT); 591188Sbill } 592215Sbill /* 593215Sbill * Protect this process from future 5945619Swnj * tty signals, clear TSTP/TTIN/TTOU if pending. 595215Sbill */ 5961788Sbill (void) spgrp(q, -1); 59736Sbill } 5986464Swnj psignal(p->p_pptr, SIGCHLD); 599188Sbill wakeup((caddr_t)p->p_pptr); 60036Sbill swtch(); 60136Sbill } 60236Sbill 60336Sbill wait() 60436Sbill { 605188Sbill struct vtimes vm; 606188Sbill struct vtimes *vp; 60736Sbill 608188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 609188Sbill wait1(0, (struct vtimes *)0); 610188Sbill return; 611188Sbill } 612188Sbill vp = (struct vtimes *)u.u_ar0[R1]; 613188Sbill wait1(u.u_ar0[R0], &vm); 614188Sbill if (u.u_error) 615188Sbill return; 616188Sbill (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); 61736Sbill } 61836Sbill 61936Sbill /* 62036Sbill * Wait system call. 62136Sbill * Search for a terminated (zombie) child, 62236Sbill * finally lay it to rest, and collect its status. 62336Sbill * Look also for stopped (traced) children, 62436Sbill * and pass back status from them. 62536Sbill */ 626188Sbill wait1(options, vp) 627188Sbill register options; 62836Sbill struct vtimes *vp; 62936Sbill { 63036Sbill register f; 6317488Skre register struct proc *p, *q; 63236Sbill 63336Sbill f = 0; 63436Sbill loop: 6354827Swnj for (p = proc; p < procNPROC; p++) 6364827Swnj if (p->p_pptr == u.u_procp) { 63736Sbill f++; 6384827Swnj if (p->p_stat == SZOMB) { 63936Sbill u.u_r.r_val1 = p->p_pid; 64036Sbill u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 64136Sbill ((struct xproc *)p)->xp_xstat = 0; 64236Sbill if (vp) 64336Sbill *vp = ((struct xproc *)p)->xp_vm; 64436Sbill vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); 64536Sbill ((struct xproc *)p)->xp_vm = zvms; 64636Sbill p->p_stat = NULL; 64736Sbill p->p_pid = 0; 64836Sbill p->p_ppid = 0; 6497488Skre if (q = p->p_ysptr) 6507488Skre q->p_osptr = p->p_osptr; 6517488Skre if (q = p->p_osptr) 6527488Skre q->p_ysptr = p->p_ysptr; 6537488Skre if ((q = p->p_pptr)->p_cptr == p) 6547488Skre q->p_cptr = p->p_osptr; 655188Sbill p->p_pptr = 0; 6567488Skre p->p_ysptr = 0; 6577488Skre p->p_osptr = 0; 6587488Skre p->p_cptr = 0; 65936Sbill p->p_sig = 0; 660188Sbill p->p_siga0 = 0; 661188Sbill p->p_siga1 = 0; 66236Sbill p->p_pgrp = 0; 66336Sbill p->p_flag = 0; 66436Sbill p->p_wchan = 0; 665188Sbill p->p_cursig = 0; 66636Sbill return; 66736Sbill } 668188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 669188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 670188Sbill p->p_flag |= SWTED; 671188Sbill u.u_r.r_val1 = p->p_pid; 672188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 673188Sbill return; 67436Sbill } 67536Sbill } 676188Sbill if (f==0) { 677188Sbill u.u_error = ECHILD; 678188Sbill return; 67936Sbill } 680188Sbill if (options&WNOHANG) { 681188Sbill u.u_r.r_val1 = 0; 682188Sbill return; 683188Sbill } 684912Sbill if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 685188Sbill u.u_eosys = RESTARTSYS; 686188Sbill return; 687188Sbill } 688188Sbill sleep((caddr_t)u.u_procp, PWAIT); 689188Sbill goto loop; 69036Sbill } 69136Sbill 69236Sbill /* 69336Sbill * fork system call. 69436Sbill */ 69536Sbill fork() 69636Sbill { 69736Sbill 69836Sbill u.u_cdmap = zdmap; 69936Sbill u.u_csmap = zdmap; 70036Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 70136Sbill u.u_r.r_val2 = 0; 70236Sbill return; 70336Sbill } 70436Sbill fork1(0); 70536Sbill } 70636Sbill 70736Sbill fork1(isvfork) 70836Sbill { 70936Sbill register struct proc *p1, *p2; 7107488Skre #ifndef QUOTA 71136Sbill register a; 71236Sbill 71336Sbill a = 0; 7147488Skre #else 7157488Skre if (u.u_quota != NOQUOT && u.u_quota->q_plim && 7167488Skre u.u_quota->q_cnt >= u.u_quota->q_plim) { 7177488Skre u.u_error = EPROCLIM; 7187488Skre return; 7197488Skre } 7207488Skre #endif 72136Sbill p2 = NULL; 7224827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 7237488Skre #ifdef QUOTA 7247488Skre if (p1->p_stat == NULL) { 7257488Skre p2 = p1; 7267488Skre break; 7277488Skre } 7287488Skre #else 72936Sbill if (p1->p_stat==NULL && p2==NULL) 73036Sbill p2 = p1; 73136Sbill else { 73236Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 73336Sbill a++; 73436Sbill } 7357488Skre #endif 73636Sbill } 73736Sbill /* 73836Sbill * Disallow if 73936Sbill * No processes at all; 74036Sbill * not su and too many procs owned; or 74136Sbill * not su and would take last slot. 74236Sbill */ 7432938Swnj if (p2==NULL) 7442938Swnj tablefull("proc"); 7457488Skre #ifdef QUOTA 7467488Skre if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { 7477488Skre #else 7482741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 7497488Skre #endif 75036Sbill u.u_error = EAGAIN; 75136Sbill if (!isvfork) { 752132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 753132Sbill (void) vsexpand(0, &u.u_csmap, 1); 75436Sbill } 75536Sbill goto out; 75636Sbill } 75736Sbill p1 = u.u_procp; 7584827Swnj if (newproc(isvfork)) { 75936Sbill u.u_r.r_val1 = p1->p_pid; 76036Sbill u.u_r.r_val2 = 1; /* child */ 76136Sbill u.u_start = time; 76236Sbill u.u_acflag = AFORK; 7637488Skre #ifdef QUOTA 7647488Skre u.u_qflags &= ~QUF_LOGIN; 7657488Skre #endif 76636Sbill return; 76736Sbill } 76836Sbill u.u_r.r_val1 = p2->p_pid; 76936Sbill 77036Sbill out: 77136Sbill u.u_r.r_val2 = 0; 77236Sbill } 77336Sbill 7747497Sroot spgrp(top, npgrp) 7757497Sroot register struct proc *top; 7767497Sroot { 7777497Sroot register struct proc *pp, *p; 7787497Sroot int f = 0; 7797497Sroot 7807497Sroot for (p = top; npgrp == -1 || u.u_uid == p->p_uid || 7817497Sroot !u.u_uid || inferior(p); p = pp) { 7827497Sroot if (npgrp == -1) { 7837497Sroot #define bit(a) (1<<(a-1)) 7847497Sroot p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 7857497Sroot } else 7867497Sroot p->p_pgrp = npgrp; 7877497Sroot f++; 7887497Sroot /* 7897497Sroot * Search for children. 7907497Sroot */ 7917497Sroot for (pp = proc; pp < procNPROC; pp++) 7927497Sroot if (pp->p_pptr == p) 7937497Sroot goto cont; 7947497Sroot /* 7957497Sroot * Search for siblings. 7967497Sroot */ 7977497Sroot for (; p != top; p = p->p_pptr) 7987497Sroot for (pp = p + 1; pp < procNPROC; pp++) 7997497Sroot if (pp->p_pptr == p->p_pptr) 8007497Sroot goto cont; 8017497Sroot break; 8027497Sroot cont: 8037497Sroot ; 8047497Sroot } 8057497Sroot return (f); 8067497Sroot } 8077497Sroot 80836Sbill /* 8097497Sroot * Is p an inferior of the current process? 81036Sbill */ 8117497Sroot inferior(p) 8127497Sroot register struct proc *p; 81336Sbill { 81436Sbill 8157497Sroot for (; p != u.u_procp; p = p->p_pptr) 8167497Sroot if (p->p_ppid == 0) 8177497Sroot return (0); 8187497Sroot return (1); 81936Sbill } 820