1*7865Sroot /* kern_proc.c 4.35 82/08/24 */ 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" 247713Sroot #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]; 547748Sroot int resid; 5536Sbill 565991Swnj if ((ip = namei(uchar, 0, 1)) == NULL) 5736Sbill return; 5836Sbill bno = 0; 5936Sbill bp = 0; 602301Skre indir = 0; 612301Skre uid = u.u_uid; 622301Skre gid = u.u_gid; 632301Skre if (ip->i_mode & ISUID) 642301Skre uid = ip->i_uid; 652301Skre if (ip->i_mode & ISGID) 662301Skre gid = ip->i_gid; 672301Skre 682301Skre again: 694827Swnj if (access(ip, IEXEC)) 7036Sbill goto bad; 714827Swnj if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) 722330Swnj goto bad; 734827Swnj if ((ip->i_mode & IFMT) != IFREG || 7436Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 7536Sbill u.u_error = EACCES; 7636Sbill goto bad; 7736Sbill } 782301Skre 7936Sbill /* 802301Skre * Read in first few bytes of file for segment sizes, ux_mag: 812301Skre * 407 = plain executable 822301Skre * 410 = RO text 832301Skre * 413 = demand paged RO text 842301Skre * Also an ASCII line beginning with #! is 852301Skre * the file name of a ``shell'' and arguments may be prepended 862301Skre * to the argument list if given here. 872301Skre * 882301Skre * SHELL NAMES ARE LIMITED IN LENGTH. 892301Skre * 902301Skre * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 912301Skre * THE ASCII LINE. 922301Skre */ 937816Sroot u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata), 947748Sroot 0, 1, &resid); 954827Swnj if (u.u_error) 962301Skre goto bad; 977748Sroot u.u_count = resid; 987816Sroot #ifndef lint 994982Swnj if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && 1004982Swnj u.u_exdata.ux_shell[0] != '#') { 1012301Skre u.u_error = ENOEXEC; 1022301Skre goto bad; 1032301Skre } 1047816Sroot #endif 1052301Skre switch (u.u_exdata.ux_mag) { 1062301Skre 1072301Skre case 0407: 1082301Skre u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 1092301Skre u.u_exdata.ux_tsize = 0; 1102301Skre break; 1112301Skre 1122301Skre case 0413: 1132301Skre case 0410: 1142301Skre if (u.u_exdata.ux_tsize == 0) { 1152301Skre u.u_error = ENOEXEC; 1162301Skre goto bad; 1172301Skre } 1182301Skre break; 1192301Skre 1202301Skre default: 1212301Skre if (u.u_exdata.ux_shell[0] != '#' || 1222301Skre u.u_exdata.ux_shell[1] != '!' || 1232301Skre indir) { 1242301Skre u.u_error = ENOEXEC; 1252301Skre goto bad; 1262301Skre } 1272301Skre cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 1282301Skre while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 1292301Skre if (*cp == '\t') 1302301Skre *cp = ' '; 1312301Skre else if (*cp == '\n') { 1322301Skre *cp = '\0'; 1332301Skre break; 1342301Skre } 1352301Skre cp++; 1362301Skre } 1372301Skre if (*cp != '\0') { 1382301Skre u.u_error = ENOEXEC; 1392301Skre goto bad; 1402301Skre } 1412301Skre cp = &u.u_exdata.ux_shell[2]; 1422301Skre while (*cp == ' ') 1432301Skre cp++; 1442301Skre u.u_dirp = cp; 1452301Skre while (*cp && *cp != ' ') 1462301Skre cp++; 1472301Skre sharg = NULL; 1482301Skre if (*cp) { 1492301Skre *cp++ = '\0'; 1502301Skre while (*cp == ' ') 1512301Skre cp++; 1522301Skre if (*cp) { 1532301Skre bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 1542301Skre sharg = cfarg; 1552301Skre } 1562301Skre } 1576568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, 1587816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 1592301Skre indir = 1; 1602301Skre iput(ip); 1615991Swnj ip = namei(schar, 0, 1); 1622301Skre if (ip == NULL) 1632301Skre return; 1642301Skre goto again; 1652301Skre } 1662301Skre 1672301Skre /* 16836Sbill * Collect arguments on "file" in swap space. 16936Sbill */ 17036Sbill na = 0; 17136Sbill ne = 0; 17236Sbill nc = 0; 17336Sbill uap = (struct execa *)u.u_ap; 1742780Swnj if ((bno = rmalloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 17536Sbill swkill(u.u_procp, "exece"); 17636Sbill goto bad; 17736Sbill } 17836Sbill if (bno % CLSIZE) 1792780Swnj panic("execa rmalloc"); 18036Sbill if (uap->argp) for (;;) { 18136Sbill ap = NULL; 1823621Sroot if (indir && (na == 1 || na == 2 && sharg)) 1832301Skre ap = (int)uap->fname; 1842301Skre else if (uap->argp) { 18536Sbill ap = fuword((caddr_t)uap->argp); 18636Sbill uap->argp++; 18736Sbill } 18836Sbill if (ap==NULL && uap->envp) { 18936Sbill uap->argp = NULL; 19036Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 19136Sbill break; 19236Sbill uap->envp++; 19336Sbill ne++; 19436Sbill } 1956568Smckusic if (ap == NULL) 19636Sbill break; 19736Sbill na++; 1984827Swnj if (ap == -1) 19936Sbill u.u_error = EFAULT; 20036Sbill do { 20136Sbill if (nc >= NCARGS-1) 20236Sbill u.u_error = E2BIG; 2032301Skre if (indir && na == 2 && sharg != NULL) 2042301Skre c = *sharg++ & 0377; 2052301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 20636Sbill u.u_error = EFAULT; 20783Sbill if (u.u_error) { 20883Sbill if (bp) 20983Sbill brelse(bp); 21083Sbill bp = 0; 21136Sbill goto badarg; 21283Sbill } 2136568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 21436Sbill if (bp) 21536Sbill bdwrite(bp); 2166568Smckusic bp = getblk(argdev, bno + nc / NBPG, 2176568Smckusic CLSIZE*NBPG); 21836Sbill cp = bp->b_un.b_addr; 21936Sbill } 22036Sbill nc++; 22136Sbill *cp++ = c; 2226568Smckusic } while (c > 0); 22336Sbill } 22436Sbill if (bp) 22536Sbill bdwrite(bp); 22636Sbill bp = 0; 22736Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 2286568Smckusic if (indir) { 2296568Smckusic u.u_dent.d_namlen = strlen(cfname); 2306568Smckusic bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, 2317816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2326568Smckusic } 2332301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 234912Sbill if (u.u_error) { 23536Sbill badarg: 2366568Smckusic for (c = 0; c < nc; c += CLSIZE*NBPG) 2376568Smckusic if (bp = baddr(argdev, bno + c / NBPG, CLSIZE*NBPG)) { 23836Sbill bp->b_flags |= B_AGE; /* throw away */ 23936Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 24036Sbill brelse(bp); 24136Sbill bp = 0; 24236Sbill } 24336Sbill goto bad; 24436Sbill } 24536Sbill 24636Sbill /* 24736Sbill * copy back arglist 24836Sbill */ 24936Sbill ucp = USRSTACK - nc - NBPW; 25036Sbill ap = ucp - na*NBPW - 3*NBPW; 25136Sbill u.u_ar0[SP] = ap; 252132Sbill (void) suword((caddr_t)ap, na-ne); 25336Sbill nc = 0; 25436Sbill for (;;) { 25536Sbill ap += NBPW; 25636Sbill if (na==ne) { 257132Sbill (void) suword((caddr_t)ap, 0); 25836Sbill ap += NBPW; 25936Sbill } 26036Sbill if (--na < 0) 26136Sbill break; 262132Sbill (void) suword((caddr_t)ap, ucp); 26336Sbill do { 2646568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 26536Sbill if (bp) 26636Sbill brelse(bp); 2676568Smckusic bp = bread(argdev, bno + nc / NBPG, 2686568Smckusic CLSIZE*NBPG); 26936Sbill bp->b_flags |= B_AGE; /* throw away */ 27036Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 27136Sbill cp = bp->b_un.b_addr; 27236Sbill } 273132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 27436Sbill nc++; 27536Sbill } while(c&0377); 27636Sbill } 277132Sbill (void) suword((caddr_t)ap, 0); 278132Sbill (void) suword((caddr_t)ucp, 0); 27936Sbill setregs(); 28036Sbill bad: 28136Sbill if (bp) 28236Sbill brelse(bp); 28336Sbill if (bno) 2842780Swnj rmfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); 28536Sbill iput(ip); 28636Sbill } 28736Sbill 28836Sbill /* 28936Sbill * Read in and set up memory for executed file. 29036Sbill */ 2912301Skre getxfile(ip, nargc, uid, gid) 29236Sbill register struct inode *ip; 29336Sbill { 29436Sbill register size_t ts, ds, ss; 2952301Skre int pagi; 29636Sbill 2972301Skre if (u.u_exdata.ux_mag == 0413) 29836Sbill pagi = SPAGI; 2992301Skre else 3002301Skre pagi = 0; 3014827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 3024827Swnj ip->i_count!=1) { 303890Sbill register struct file *fp; 304890Sbill 3054827Swnj for (fp = file; fp < fileNFILE; fp++) { 3067497Sroot if (fp->f_type == DTYPE_FILE && 3077497Sroot fp->f_inode == ip && (fp->f_flag&FWRITE)) { 308890Sbill u.u_error = ETXTBSY; 309890Sbill goto bad; 310890Sbill } 3114827Swnj } 31236Sbill } 31336Sbill 31436Sbill /* 3154827Swnj * Compute text and data sizes and make sure not too large. 31636Sbill */ 31736Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 31836Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 31936Sbill ss = clrnd(SSIZE + btoc(nargc)); 320912Sbill if (chksize(ts, ds, ss)) 321912Sbill goto bad; 3224827Swnj 3234827Swnj /* 3244827Swnj * Make sure enough space to start process. 3254827Swnj */ 326912Sbill u.u_cdmap = zdmap; 327912Sbill u.u_csmap = zdmap; 328912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 329912Sbill goto bad; 33036Sbill 331912Sbill /* 332912Sbill * At this point, committed to the new image! 333912Sbill * Release virtual memory resources of old process, and 334912Sbill * initialize the virtual memory of the new process. 335912Sbill * If we resulted from vfork(), instead wakeup our 336912Sbill * parent who will set SVFDONE when he has taken back 337912Sbill * our resources. 338912Sbill */ 339912Sbill u.u_prof.pr_scale = 0; 340912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 341912Sbill vrelvm(); 342912Sbill else { 343912Sbill u.u_procp->p_flag &= ~SVFORK; 344912Sbill u.u_procp->p_flag |= SKEEP; 345912Sbill wakeup((caddr_t)u.u_procp); 346912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 347912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 348912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 349912Sbill } 3503592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 351912Sbill u.u_procp->p_flag |= pagi; 352912Sbill u.u_dmap = u.u_cdmap; 353912Sbill u.u_smap = u.u_csmap; 354912Sbill vgetvm(ts, ds, ss); 355912Sbill 3567748Sroot if (pagi == 0) 3577816Sroot u.u_error = 3587816Sroot rdwri(UIO_READ, ip, 3597816Sroot (char*)ctob(ts), (int)u.u_exdata.ux_dsize, 3607816Sroot (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), 3617816Sroot 0, (int *)0); 362912Sbill xalloc(ip, pagi); 363912Sbill if (pagi && u.u_procp->p_textp) 364912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 365912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 366912Sbill 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 36736Sbill 368912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 369912Sbill mtpr(TBIA, 0); 37036Sbill 3717530Sroot if (u.u_error) 3727530Sroot swkill(u.u_procp, "i/o error mapping pages"); 373912Sbill /* 374912Sbill * set SUID/SGID protections, if no tracing 375912Sbill */ 376912Sbill if ((u.u_procp->p_flag&STRC)==0) { 3774827Swnj u.u_uid = uid; 3784827Swnj u.u_procp->p_uid = uid; 3792301Skre u.u_gid = gid; 380*7865Sroot entergroup(gid); 381912Sbill } else 382912Sbill psignal(u.u_procp, SIGTRAP); 38336Sbill u.u_tsize = ts; 38436Sbill u.u_dsize = ds; 38536Sbill u.u_ssize = ss; 38636Sbill bad: 387912Sbill return; 38836Sbill } 38936Sbill 39036Sbill /* 39136Sbill * Clear registers on exec 39236Sbill */ 39336Sbill setregs() 39436Sbill { 395173Sbill register int (**rp)(); 39636Sbill register i; 397188Sbill long sigmask; 39836Sbill 3996464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 400188Sbill sigmask <<= 1, rp++) { 401188Sbill switch (*rp) { 402188Sbill 403188Sbill case SIG_IGN: 404188Sbill case SIG_DFL: 405188Sbill case SIG_HOLD: 406188Sbill continue; 407188Sbill 408188Sbill default: 409188Sbill /* 410206Sbill * Normal or deferring catch; revert to default. 411188Sbill */ 412206Sbill (void) spl6(); 413206Sbill *rp = SIG_DFL; 414188Sbill if ((int)*rp & 1) 415188Sbill u.u_procp->p_siga0 |= sigmask; 416188Sbill else 4176327Swnj u.u_procp->p_siga0 &= ~sigmask; 418188Sbill if ((int)*rp & 2) 419188Sbill u.u_procp->p_siga1 |= sigmask; 420188Sbill else 421188Sbill u.u_procp->p_siga1 &= ~sigmask; 422206Sbill (void) spl0(); 423188Sbill continue; 424188Sbill } 425188Sbill } 42636Sbill /* 4274827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 42836Sbill *rp++ = 0; 42936Sbill */ 43036Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 4314827Swnj for (i=0; i<NOFILE; i++) { 43236Sbill if (u.u_pofile[i]&EXCLOSE) { 4337697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 43436Sbill u.u_ofile[i] = NULL; 4357697Ssam u.u_pofile[i] = 0; 43636Sbill } 43736Sbill } 4384827Swnj 43936Sbill /* 44036Sbill * Remember file name for accounting. 44136Sbill */ 44236Sbill u.u_acflag &= ~AFORK; 4436568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm, 4447816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 44536Sbill } 44636Sbill 44736Sbill /* 4484827Swnj * Exit system call: pass back caller's arg 44936Sbill */ 45036Sbill rexit() 45136Sbill { 45236Sbill register struct a { 45336Sbill int rval; 45436Sbill } *uap; 45536Sbill 45636Sbill uap = (struct a *)u.u_ap; 45736Sbill exit((uap->rval & 0377) << 8); 45836Sbill } 45936Sbill 46036Sbill /* 46136Sbill * Release resources. 46236Sbill * Save u. area for parent to look at. 46336Sbill * Enter zombie state. 46436Sbill * Wake up parent and init processes, 46536Sbill * and dispose of children. 46636Sbill */ 46736Sbill exit(rv) 46836Sbill { 46936Sbill register int i; 47036Sbill register struct proc *p, *q; 47136Sbill register int x; 47236Sbill 47336Sbill #ifdef PGINPROF 47436Sbill vmsizmon(); 47536Sbill #endif 47636Sbill p = u.u_procp; 47736Sbill p->p_flag &= ~(STRC|SULOCK); 47836Sbill p->p_flag |= SWEXIT; 47936Sbill p->p_clktim = 0; 480188Sbill (void) spl6(); 481188Sbill if ((int)SIG_IGN & 1) 482188Sbill p->p_siga0 = ~0; 483188Sbill else 484188Sbill p->p_siga0 = 0; 485188Sbill if ((int)SIG_IGN & 2) 486188Sbill p->p_siga1 = ~0; 487188Sbill else 488206Sbill p->p_siga1 = 0; 489188Sbill (void) spl0(); 4901399Sbill p->p_cpticks = 0; 4911399Sbill p->p_pctcpu = 0; 4924827Swnj for (i=0; i<NSIG; i++) 493173Sbill u.u_signal[i] = SIG_IGN; 49436Sbill /* 49536Sbill * Release virtual memory. If we resulted from 49636Sbill * a vfork(), instead give the resources back to 49736Sbill * the parent. 49836Sbill */ 49936Sbill if ((p->p_flag & SVFORK) == 0) 50036Sbill vrelvm(); 50136Sbill else { 50236Sbill p->p_flag &= ~SVFORK; 50336Sbill wakeup((caddr_t)p); 50436Sbill while ((p->p_flag & SVFDONE) == 0) 50536Sbill sleep((caddr_t)p, PZERO - 1); 50636Sbill p->p_flag &= ~SVFDONE; 50736Sbill } 5087697Ssam for (i = 0; i < NOFILE; i++) { 5097697Ssam #ifdef notdef 5107697Ssam /* why was this like this? */ 51136Sbill f = u.u_ofile[i]; 51236Sbill u.u_ofile[i] = NULL; 5135581Swnj closef(f, 1); 5147697Ssam #else 5157697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 5167697Ssam u.u_ofile[i] = NULL; 5177697Ssam u.u_pofile[i] = 0; 5187697Ssam #endif 51936Sbill } 5204827Swnj ilock(u.u_cdir); 52136Sbill iput(u.u_cdir); 52236Sbill if (u.u_rdir) { 5234827Swnj ilock(u.u_rdir); 52436Sbill iput(u.u_rdir); 52536Sbill } 526363Sbill u.u_limit[LIM_FSIZE] = INFINITY; 52736Sbill acct(); 5287488Skre #ifdef QUOTA 5297488Skre qclean(); 5307488Skre #endif 53136Sbill vrelpt(u.u_procp); 53236Sbill vrelu(u.u_procp, 0); 5335630Swnj (void) spl5(); /* hack for mem alloc race XXX */ 53436Sbill multprog--; 535931Sbill p->p_stat = SZOMB; 536307Sbill noproc = 1; 53736Sbill i = PIDHASH(p->p_pid); 53836Sbill x = p - proc; 53936Sbill if (pidhash[i] == x) 54036Sbill pidhash[i] = p->p_idhash; 54136Sbill else { 54236Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 54336Sbill if (proc[i].p_idhash == x) { 54436Sbill proc[i].p_idhash = p->p_idhash; 54536Sbill goto done; 54636Sbill } 54736Sbill panic("exit"); 54836Sbill } 5491409Sbill if (p->p_pid == 1) 5501409Sbill panic("init died"); 55136Sbill done: 55236Sbill ((struct xproc *)p)->xp_xstat = rv; /* overlay */ 55336Sbill ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ 55436Sbill vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); 5554827Swnj for (q = proc; q < procNPROC; q++) 5564827Swnj if (q->p_pptr == p) { 5577488Skre if (q->p_osptr) 5587488Skre q->p_osptr->p_ysptr = q->p_ysptr; 5597488Skre if (q->p_ysptr) 5607488Skre q->p_ysptr->p_osptr = q->p_osptr; 5617488Skre if (proc[1].p_cptr) 5627488Skre proc[1].p_cptr->p_ysptr = q; 5637488Skre q->p_osptr = proc[1].p_cptr; 5647488Skre q->p_ysptr = NULL; 5657488Skre proc[1].p_cptr = q; 5667488Skre 567188Sbill q->p_pptr = &proc[1]; 568188Sbill q->p_ppid = 1; 56936Sbill wakeup((caddr_t)&proc[1]); 570188Sbill /* 571212Sbill * Traced processes are killed 572188Sbill * since their existence means someone is screwing up. 573354Sbill * Stopped processes are sent a hangup and a continue. 574212Sbill * This is designed to be ``safe'' for setuid 575212Sbill * processes since they must be willing to tolerate 576212Sbill * hangups anyways. 577188Sbill */ 578212Sbill if (q->p_flag&STRC) { 579188Sbill q->p_flag &= ~STRC; 580188Sbill psignal(q, SIGKILL); 581212Sbill } else if (q->p_stat == SSTOP) { 582212Sbill psignal(q, SIGHUP); 583212Sbill psignal(q, SIGCONT); 584188Sbill } 585215Sbill /* 586215Sbill * Protect this process from future 5875619Swnj * tty signals, clear TSTP/TTIN/TTOU if pending. 588215Sbill */ 5891788Sbill (void) spgrp(q, -1); 59036Sbill } 5916464Swnj psignal(p->p_pptr, SIGCHLD); 592188Sbill wakeup((caddr_t)p->p_pptr); 59336Sbill swtch(); 59436Sbill } 59536Sbill 59636Sbill wait() 59736Sbill { 598188Sbill struct vtimes vm; 599188Sbill struct vtimes *vp; 60036Sbill 601188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 602188Sbill wait1(0, (struct vtimes *)0); 603188Sbill return; 604188Sbill } 605188Sbill vp = (struct vtimes *)u.u_ar0[R1]; 606188Sbill wait1(u.u_ar0[R0], &vm); 607188Sbill if (u.u_error) 608188Sbill return; 609188Sbill (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); 61036Sbill } 61136Sbill 61236Sbill /* 61336Sbill * Wait system call. 61436Sbill * Search for a terminated (zombie) child, 61536Sbill * finally lay it to rest, and collect its status. 61636Sbill * Look also for stopped (traced) children, 61736Sbill * and pass back status from them. 61836Sbill */ 619188Sbill wait1(options, vp) 620188Sbill register options; 62136Sbill struct vtimes *vp; 62236Sbill { 62336Sbill register f; 6247488Skre register struct proc *p, *q; 62536Sbill 62636Sbill f = 0; 62736Sbill loop: 6284827Swnj for (p = proc; p < procNPROC; p++) 6294827Swnj if (p->p_pptr == u.u_procp) { 63036Sbill f++; 6314827Swnj if (p->p_stat == SZOMB) { 63236Sbill u.u_r.r_val1 = p->p_pid; 63336Sbill u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 63436Sbill ((struct xproc *)p)->xp_xstat = 0; 63536Sbill if (vp) 63636Sbill *vp = ((struct xproc *)p)->xp_vm; 63736Sbill vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); 63836Sbill ((struct xproc *)p)->xp_vm = zvms; 63936Sbill p->p_stat = NULL; 64036Sbill p->p_pid = 0; 64136Sbill p->p_ppid = 0; 6427488Skre if (q = p->p_ysptr) 6437488Skre q->p_osptr = p->p_osptr; 6447488Skre if (q = p->p_osptr) 6457488Skre q->p_ysptr = p->p_ysptr; 6467488Skre if ((q = p->p_pptr)->p_cptr == p) 6477488Skre q->p_cptr = p->p_osptr; 648188Sbill p->p_pptr = 0; 6497488Skre p->p_ysptr = 0; 6507488Skre p->p_osptr = 0; 6517488Skre p->p_cptr = 0; 65236Sbill p->p_sig = 0; 653188Sbill p->p_siga0 = 0; 654188Sbill p->p_siga1 = 0; 65536Sbill p->p_pgrp = 0; 65636Sbill p->p_flag = 0; 65736Sbill p->p_wchan = 0; 658188Sbill p->p_cursig = 0; 65936Sbill return; 66036Sbill } 661188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 662188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 663188Sbill p->p_flag |= SWTED; 664188Sbill u.u_r.r_val1 = p->p_pid; 665188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 666188Sbill return; 66736Sbill } 66836Sbill } 669188Sbill if (f==0) { 670188Sbill u.u_error = ECHILD; 671188Sbill return; 67236Sbill } 673188Sbill if (options&WNOHANG) { 674188Sbill u.u_r.r_val1 = 0; 675188Sbill return; 676188Sbill } 677912Sbill if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 678188Sbill u.u_eosys = RESTARTSYS; 679188Sbill return; 680188Sbill } 681188Sbill sleep((caddr_t)u.u_procp, PWAIT); 682188Sbill goto loop; 68336Sbill } 68436Sbill 68536Sbill /* 68636Sbill * fork system call. 68736Sbill */ 68836Sbill fork() 68936Sbill { 69036Sbill 69136Sbill u.u_cdmap = zdmap; 69236Sbill u.u_csmap = zdmap; 69336Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 69436Sbill u.u_r.r_val2 = 0; 69536Sbill return; 69636Sbill } 69736Sbill fork1(0); 69836Sbill } 69936Sbill 70036Sbill fork1(isvfork) 70136Sbill { 70236Sbill register struct proc *p1, *p2; 7037488Skre #ifndef QUOTA 70436Sbill register a; 70536Sbill 70636Sbill a = 0; 7077488Skre #else 7087488Skre if (u.u_quota != NOQUOT && u.u_quota->q_plim && 7097488Skre u.u_quota->q_cnt >= u.u_quota->q_plim) { 7107488Skre u.u_error = EPROCLIM; 7117488Skre return; 7127488Skre } 7137488Skre #endif 71436Sbill p2 = NULL; 7154827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 7167488Skre #ifdef QUOTA 7177488Skre if (p1->p_stat == NULL) { 7187488Skre p2 = p1; 7197488Skre break; 7207488Skre } 7217488Skre #else 72236Sbill if (p1->p_stat==NULL && p2==NULL) 72336Sbill p2 = p1; 72436Sbill else { 72536Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 72636Sbill a++; 72736Sbill } 7287488Skre #endif 72936Sbill } 73036Sbill /* 73136Sbill * Disallow if 73236Sbill * No processes at all; 73336Sbill * not su and too many procs owned; or 73436Sbill * not su and would take last slot. 73536Sbill */ 7362938Swnj if (p2==NULL) 7372938Swnj tablefull("proc"); 7387488Skre #ifdef QUOTA 7397488Skre if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { 7407488Skre #else 7412741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 7427488Skre #endif 74336Sbill u.u_error = EAGAIN; 74436Sbill if (!isvfork) { 745132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 746132Sbill (void) vsexpand(0, &u.u_csmap, 1); 74736Sbill } 74836Sbill goto out; 74936Sbill } 75036Sbill p1 = u.u_procp; 7514827Swnj if (newproc(isvfork)) { 75236Sbill u.u_r.r_val1 = p1->p_pid; 75336Sbill u.u_r.r_val2 = 1; /* child */ 75436Sbill u.u_start = time; 75536Sbill u.u_acflag = AFORK; 7567488Skre #ifdef QUOTA 7577488Skre u.u_qflags &= ~QUF_LOGIN; 7587488Skre #endif 75936Sbill return; 76036Sbill } 76136Sbill u.u_r.r_val1 = p2->p_pid; 76236Sbill 76336Sbill out: 76436Sbill u.u_r.r_val2 = 0; 76536Sbill } 76636Sbill 7677497Sroot spgrp(top, npgrp) 7687497Sroot register struct proc *top; 7697497Sroot { 7707497Sroot register struct proc *pp, *p; 7717497Sroot int f = 0; 7727497Sroot 7737497Sroot for (p = top; npgrp == -1 || u.u_uid == p->p_uid || 7747497Sroot !u.u_uid || inferior(p); p = pp) { 7757497Sroot if (npgrp == -1) { 7767497Sroot #define bit(a) (1<<(a-1)) 7777497Sroot p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 7787497Sroot } else 7797497Sroot p->p_pgrp = npgrp; 7807497Sroot f++; 7817497Sroot /* 7827497Sroot * Search for children. 7837497Sroot */ 7847497Sroot for (pp = proc; pp < procNPROC; pp++) 7857497Sroot if (pp->p_pptr == p) 7867497Sroot goto cont; 7877497Sroot /* 7887497Sroot * Search for siblings. 7897497Sroot */ 7907497Sroot for (; p != top; p = p->p_pptr) 7917497Sroot for (pp = p + 1; pp < procNPROC; pp++) 7927497Sroot if (pp->p_pptr == p->p_pptr) 7937497Sroot goto cont; 7947497Sroot break; 7957497Sroot cont: 7967497Sroot ; 7977497Sroot } 7987497Sroot return (f); 7997497Sroot } 8007497Sroot 80136Sbill /* 8027497Sroot * Is p an inferior of the current process? 80336Sbill */ 8047497Sroot inferior(p) 8057816Sroot register struct proc *p; 80636Sbill { 80736Sbill 8087497Sroot for (; p != u.u_procp; p = p->p_pptr) 8097497Sroot if (p->p_ppid == 0) 8107497Sroot return (0); 8117497Sroot return (1); 81236Sbill } 8137816Sroot 8147816Sroot struct proc * 8157816Sroot pfind(pid) 8167816Sroot int pid; 8177816Sroot { 8187816Sroot register struct proc *p; 8197816Sroot 8207816Sroot for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 8217816Sroot if (p->p_pid == pid) 8227816Sroot return (p); 8237816Sroot return ((struct proc *)0); 8247816Sroot } 825