1*2329Swnj /* kern_proc.c 4.4 02/01/81 */ 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" 2236Sbill 2336Sbill /* 2436Sbill * exec system call, with and without environments. 2536Sbill */ 2636Sbill struct execa { 2736Sbill char *fname; 2836Sbill char **argp; 2936Sbill char **envp; 3036Sbill }; 3136Sbill 3236Sbill exec() 3336Sbill { 3436Sbill ((struct execa *)u.u_ap)->envp = NULL; 3536Sbill exece(); 3636Sbill } 3736Sbill 3836Sbill exece() 3936Sbill { 4036Sbill register nc; 4136Sbill register char *cp; 4236Sbill register struct buf *bp; 4336Sbill register struct execa *uap; 4436Sbill int na, ne, ucp, ap, c; 452301Skre int indir, uid, gid; 462301Skre char *sharg; 4736Sbill struct inode *ip; 4836Sbill swblk_t bno; 492301Skre char cfname[DIRSIZ]; 502301Skre char cfarg[SHSIZE]; 5136Sbill 5236Sbill if ((ip = namei(uchar, 0)) == NULL) 5336Sbill return; 542301Skre 5536Sbill bno = 0; 5636Sbill bp = 0; 572301Skre indir = 0; 582301Skre uid = u.u_uid; 592301Skre gid = u.u_gid; 602301Skre 612301Skre if (ip->i_mode & ISUID) 622301Skre uid = ip->i_uid; 632301Skre if (ip->i_mode & ISGID) 642301Skre gid = ip->i_gid; 652301Skre 662301Skre again: 6736Sbill if(access(ip, IEXEC)) 6836Sbill goto bad; 6936Sbill if((ip->i_mode & IFMT) != IFREG || 7036Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 7136Sbill u.u_error = EACCES; 7236Sbill goto bad; 7336Sbill } 742301Skre 7536Sbill /* 762301Skre * Read in first few bytes of file for segment sizes, ux_mag: 772301Skre * 407 = plain executable 782301Skre * 410 = RO text 792301Skre * 413 = demand paged RO text 802301Skre * Also an ASCII line beginning with #! is 812301Skre * the file name of a ``shell'' and arguments may be prepended 822301Skre * to the argument list if given here. 832301Skre * 842301Skre * SHELL NAMES ARE LIMITED IN LENGTH. 852301Skre * 862301Skre * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 872301Skre * THE ASCII LINE. 882301Skre */ 892301Skre u.u_base = (caddr_t)&u.u_exdata; 902301Skre u.u_count = sizeof(u.u_exdata); 912301Skre u.u_offset = 0; 922301Skre u.u_segflg = 1; 932301Skre readi(ip); 942301Skre u.u_segflg = 0; 952301Skre if(u.u_error) 962301Skre goto bad; 972301Skre if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) 982301Skre && u.u_exdata.ux_shell[0] != '#') { 992301Skre u.u_error = ENOEXEC; 1002301Skre goto bad; 1012301Skre } 1022301Skre switch (u.u_exdata.ux_mag) { 1032301Skre 1042301Skre case 0407: 1052301Skre u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 1062301Skre u.u_exdata.ux_tsize = 0; 1072301Skre break; 1082301Skre 1092301Skre case 0413: 1102301Skre case 0410: 1112301Skre if (u.u_exdata.ux_tsize == 0) { 1122301Skre u.u_error = ENOEXEC; 1132301Skre goto bad; 1142301Skre } 1152301Skre break; 1162301Skre 1172301Skre default: 1182301Skre if (u.u_exdata.ux_shell[0] != '#' || 1192301Skre u.u_exdata.ux_shell[1] != '!' || 1202301Skre indir) { 1212301Skre u.u_error = ENOEXEC; 1222301Skre goto bad; 1232301Skre } 1242301Skre cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 1252301Skre while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 1262301Skre if (*cp == '\t') 1272301Skre *cp = ' '; 1282301Skre else if (*cp == '\n') { 1292301Skre *cp = '\0'; 1302301Skre break; 1312301Skre } 1322301Skre cp++; 1332301Skre } 1342301Skre if (*cp != '\0') { 1352301Skre u.u_error = ENOEXEC; 1362301Skre goto bad; 1372301Skre } 1382301Skre cp = &u.u_exdata.ux_shell[2]; 1392301Skre while (*cp == ' ') 1402301Skre cp++; 1412301Skre u.u_dirp = cp; 1422301Skre while (*cp && *cp != ' ') 1432301Skre cp++; 1442301Skre sharg = NULL; 1452301Skre if (*cp) { 1462301Skre *cp++ = '\0'; 1472301Skre while (*cp == ' ') 1482301Skre cp++; 1492301Skre if (*cp) { 1502301Skre bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 1512301Skre sharg = cfarg; 1522301Skre } 1532301Skre } 1542301Skre bcopy((caddr_t)u.u_dbuf, (caddr_t)cfname, DIRSIZ); 1552301Skre indir = 1; 1562301Skre iput(ip); 1572301Skre ip = namei(schar, 0); 1582301Skre if (ip == NULL) 1592301Skre return; 1602301Skre goto again; 1612301Skre } 1622301Skre 1632301Skre /* 16436Sbill * Collect arguments on "file" in swap space. 16536Sbill */ 16636Sbill na = 0; 16736Sbill ne = 0; 16836Sbill nc = 0; 16936Sbill uap = (struct execa *)u.u_ap; 170307Sbill if ((bno = malloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 17136Sbill swkill(u.u_procp, "exece"); 17236Sbill goto bad; 17336Sbill } 17436Sbill if (bno % CLSIZE) 17536Sbill panic("execa malloc"); 17636Sbill if (uap->argp) for (;;) { 17736Sbill ap = NULL; 1782301Skre if (na == 1 && indir) { 1792301Skre if (sharg == NULL) 1802301Skre ap = (int)uap->fname; 1812301Skre } else if (na == 2 && indir && sharg != NULL) 1822301Skre ap = (int)uap->fname; 1832301Skre else if (uap->argp) { 18436Sbill ap = fuword((caddr_t)uap->argp); 18536Sbill uap->argp++; 18636Sbill } 18736Sbill if (ap==NULL && uap->envp) { 18836Sbill uap->argp = NULL; 18936Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 19036Sbill break; 19136Sbill uap->envp++; 19236Sbill ne++; 19336Sbill } 19436Sbill if (ap==NULL) 19536Sbill break; 19636Sbill na++; 19736Sbill if(ap == -1) 19836Sbill u.u_error = EFAULT; 19936Sbill do { 20036Sbill if (nc >= NCARGS-1) 20136Sbill u.u_error = E2BIG; 2022301Skre if (indir && na == 2 && sharg != NULL) 2032301Skre c = *sharg++ & 0377; 2042301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 20536Sbill u.u_error = EFAULT; 20683Sbill if (u.u_error) { 20783Sbill if (bp) 20883Sbill brelse(bp); 20983Sbill bp = 0; 21036Sbill goto badarg; 21183Sbill } 21236Sbill if ((nc&BMASK) == 0) { 21336Sbill if (bp) 21436Sbill bdwrite(bp); 215307Sbill bp = getblk(argdev, 216307Sbill (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); 21736Sbill cp = bp->b_un.b_addr; 21836Sbill } 21936Sbill nc++; 22036Sbill *cp++ = c; 22136Sbill } while (c>0); 22236Sbill } 22336Sbill if (bp) 22436Sbill bdwrite(bp); 22536Sbill bp = 0; 22636Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 2272301Skre if (indir) 2282301Skre bcopy((caddr_t)cfname, (caddr_t)u.u_dbuf, DIRSIZ); 2292301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 230912Sbill if (u.u_error) { 23136Sbill badarg: 23236Sbill for (c = 0; c < nc; c += BSIZE) 233307Sbill if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) { 23436Sbill bp->b_flags |= B_AGE; /* throw away */ 23536Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 23636Sbill brelse(bp); 23736Sbill bp = 0; 23836Sbill } 23936Sbill goto bad; 24036Sbill } 24136Sbill 24236Sbill /* 24336Sbill * copy back arglist 24436Sbill */ 24536Sbill 24636Sbill ucp = USRSTACK - nc - NBPW; 24736Sbill ap = ucp - na*NBPW - 3*NBPW; 24836Sbill u.u_ar0[SP] = ap; 249132Sbill (void) suword((caddr_t)ap, na-ne); 25036Sbill nc = 0; 25136Sbill for (;;) { 25236Sbill ap += NBPW; 25336Sbill if (na==ne) { 254132Sbill (void) suword((caddr_t)ap, 0); 25536Sbill ap += NBPW; 25636Sbill } 25736Sbill if (--na < 0) 25836Sbill break; 259132Sbill (void) suword((caddr_t)ap, ucp); 26036Sbill do { 26136Sbill if ((nc&BMASK) == 0) { 26236Sbill if (bp) 26336Sbill brelse(bp); 264307Sbill bp = bread(argdev, 265307Sbill (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); 26636Sbill bp->b_flags |= B_AGE; /* throw away */ 26736Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 26836Sbill cp = bp->b_un.b_addr; 26936Sbill } 270132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 27136Sbill nc++; 27236Sbill } while(c&0377); 27336Sbill } 274132Sbill (void) suword((caddr_t)ap, 0); 275132Sbill (void) suword((caddr_t)ucp, 0); 27636Sbill setregs(); 27736Sbill bad: 27836Sbill if (bp) 27936Sbill brelse(bp); 28036Sbill if (bno) 281307Sbill mfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); 28236Sbill iput(ip); 28336Sbill } 28436Sbill 28536Sbill /* 28636Sbill * Read in and set up memory for executed file. 28736Sbill */ 2882301Skre getxfile(ip, nargc, uid, gid) 28936Sbill register struct inode *ip; 29036Sbill { 29136Sbill register size_t ts, ds, ss; 2922301Skre int pagi; 29336Sbill 2942301Skre if (u.u_exdata.ux_mag == 0413) 29536Sbill pagi = SPAGI; 2962301Skre else 2972301Skre pagi = 0; 29836Sbill 29936Sbill if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { 300890Sbill register struct file *fp; 301890Sbill 302890Sbill for (fp = file; fp < &file[NFILE]; fp++) 303890Sbill if (fp->f_inode == ip && (fp->f_flag&FWRITE)) { 304890Sbill u.u_error = ETXTBSY; 305890Sbill goto bad; 306890Sbill } 30736Sbill } 30836Sbill 30936Sbill /* 31036Sbill * find text and data sizes 31136Sbill * try them out for possible 31236Sbill * exceed of max sizes 31336Sbill */ 31436Sbill 31536Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 31636Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 31736Sbill ss = clrnd(SSIZE + btoc(nargc)); 318912Sbill if (chksize(ts, ds, ss)) 319912Sbill goto bad; 320912Sbill u.u_cdmap = zdmap; 321912Sbill u.u_csmap = zdmap; 322912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 323912Sbill goto bad; 32436Sbill 325912Sbill /* 326912Sbill * At this point, committed to the new image! 327912Sbill * Release virtual memory resources of old process, and 328912Sbill * initialize the virtual memory of the new process. 329912Sbill * If we resulted from vfork(), instead wakeup our 330912Sbill * parent who will set SVFDONE when he has taken back 331912Sbill * our resources. 332912Sbill */ 333912Sbill u.u_prof.pr_scale = 0; 334912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 335912Sbill vrelvm(); 336912Sbill else { 337912Sbill u.u_procp->p_flag &= ~SVFORK; 338912Sbill u.u_procp->p_flag |= SKEEP; 339912Sbill wakeup((caddr_t)u.u_procp); 340912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 341912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 342912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 343912Sbill } 344912Sbill u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM|SNUSIG); 345912Sbill u.u_procp->p_flag |= pagi; 346912Sbill u.u_dmap = u.u_cdmap; 347912Sbill u.u_smap = u.u_csmap; 348912Sbill vgetvm(ts, ds, ss); 349912Sbill 350912Sbill if (pagi == 0) { 35136Sbill /* 352912Sbill * Read in data segment. 35336Sbill */ 354912Sbill u.u_base = (char *)ctob(ts); 355912Sbill u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; 356912Sbill u.u_count = u.u_exdata.ux_dsize; 357912Sbill readi(ip); 358912Sbill } 359912Sbill xalloc(ip, pagi); 360912Sbill if (pagi && u.u_procp->p_textp) 361912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 362912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 363912Sbill 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 36436Sbill 365912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 366912Sbill mtpr(TBIA, 0); 36736Sbill 368912Sbill /* 369912Sbill * set SUID/SGID protections, if no tracing 370912Sbill */ 371912Sbill if ((u.u_procp->p_flag&STRC)==0) { 3722301Skre #ifndef MELB 3732301Skre if(u.u_uid != 0) 3742301Skre #endif 3752301Skre { 3762301Skre u.u_uid = uid; 3772301Skre u.u_procp->p_uid = uid; 3782301Skre } 3792301Skre u.u_gid = gid; 380912Sbill } else 381912Sbill psignal(u.u_procp, SIGTRAP); 38236Sbill u.u_tsize = ts; 38336Sbill u.u_dsize = ds; 38436Sbill u.u_ssize = ss; 38536Sbill bad: 386912Sbill return; 38736Sbill } 38836Sbill 38936Sbill /* 39036Sbill * Clear registers on exec 39136Sbill */ 39236Sbill setregs() 39336Sbill { 394173Sbill register int (**rp)(); 39536Sbill register i; 396*2329Swnj #ifdef UCBIPC 397*2329Swnj register struct port *pt; 398*2329Swnj #endif UCBIPC 399188Sbill long sigmask; 40036Sbill 401188Sbill for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG]; 402188Sbill sigmask <<= 1, rp++) { 403188Sbill switch (*rp) { 404188Sbill 405188Sbill case SIG_IGN: 406188Sbill case SIG_DFL: 407188Sbill case SIG_HOLD: 408188Sbill continue; 409188Sbill 410188Sbill default: 411188Sbill /* 412206Sbill * Normal or deferring catch; revert to default. 413188Sbill */ 414206Sbill (void) spl6(); 415206Sbill *rp = SIG_DFL; 416188Sbill if ((int)*rp & 1) 417188Sbill u.u_procp->p_siga0 |= sigmask; 418188Sbill else 419188Sbill u.u_procp->p_siga1 &= ~sigmask; 420188Sbill if ((int)*rp & 2) 421188Sbill u.u_procp->p_siga1 |= sigmask; 422188Sbill else 423188Sbill u.u_procp->p_siga1 &= ~sigmask; 424206Sbill (void) spl0(); 425188Sbill continue; 426188Sbill } 427188Sbill } 42836Sbill /* 42936Sbill for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 43036Sbill *rp++ = 0; 43136Sbill */ 43236Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 43336Sbill for(i=0; i<NOFILE; i++) { 43436Sbill if (u.u_pofile[i]&EXCLOSE) { 435*2329Swnj #ifndef UCBIPC 43636Sbill closef(u.u_ofile[i]); 43736Sbill u.u_ofile[i] = NULL; 438*2329Swnj #else UCBIPC 439*2329Swnj if (u.u_pofile[i]&ISPORT) { 440*2329Swnj pt = u.u_oport[i]; 441*2329Swnj if (--pt->pt_count == 0) 442*2329Swnj ptclose(pt); 443*2329Swnj u.u_pofile[i] &= ~ISPORT; 444*2329Swnj u.u_oport[i] = NULL; 445*2329Swnj } else { 446*2329Swnj closef(u.u_ofile[i]); 447*2329Swnj u.u_ofile[i] = NULL; 448*2329Swnj } 449*2329Swnj #endif UCBIPC 450188Sbill u.u_pofile[i] &= ~EXCLOSE; 45136Sbill } 45236Sbill } 45336Sbill /* 45436Sbill * Remember file name for accounting. 45536Sbill */ 45636Sbill u.u_acflag &= ~AFORK; 45736Sbill bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ); 45836Sbill } 45936Sbill 46036Sbill /* 46136Sbill * exit system call: 46236Sbill * pass back caller's arg 46336Sbill */ 46436Sbill rexit() 46536Sbill { 46636Sbill register struct a { 46736Sbill int rval; 46836Sbill } *uap; 46936Sbill 47036Sbill uap = (struct a *)u.u_ap; 47136Sbill exit((uap->rval & 0377) << 8); 47236Sbill } 47336Sbill 47436Sbill /* 47536Sbill * Release resources. 47636Sbill * Save u. area for parent to look at. 47736Sbill * Enter zombie state. 47836Sbill * Wake up parent and init processes, 47936Sbill * and dispose of children. 48036Sbill */ 48136Sbill exit(rv) 48236Sbill { 48336Sbill register int i; 48436Sbill register struct proc *p, *q; 48536Sbill register struct file *f; 486*2329Swnj #ifdef UCBIPC 487*2329Swnj register struct port *pt; 488*2329Swnj #endif UCBIPC 48936Sbill register int x; 49036Sbill 49136Sbill #ifdef PGINPROF 49236Sbill vmsizmon(); 49336Sbill #endif 49436Sbill p = u.u_procp; 49536Sbill p->p_flag &= ~(STRC|SULOCK); 49636Sbill p->p_flag |= SWEXIT; 49736Sbill p->p_clktim = 0; 498188Sbill (void) spl6(); 499188Sbill if ((int)SIG_IGN & 1) 500188Sbill p->p_siga0 = ~0; 501188Sbill else 502188Sbill p->p_siga0 = 0; 503188Sbill if ((int)SIG_IGN & 2) 504188Sbill p->p_siga1 = ~0; 505188Sbill else 506206Sbill p->p_siga1 = 0; 507188Sbill (void) spl0(); 5081399Sbill p->p_cpticks = 0; 5091399Sbill p->p_pctcpu = 0; 51036Sbill for(i=0; i<NSIG; i++) 511173Sbill u.u_signal[i] = SIG_IGN; 51236Sbill /* 51336Sbill * Release virtual memory. If we resulted from 51436Sbill * a vfork(), instead give the resources back to 51536Sbill * the parent. 51636Sbill */ 51736Sbill if ((p->p_flag & SVFORK) == 0) 51836Sbill vrelvm(); 51936Sbill else { 52036Sbill p->p_flag &= ~SVFORK; 52136Sbill wakeup((caddr_t)p); 52236Sbill while ((p->p_flag & SVFDONE) == 0) 52336Sbill sleep((caddr_t)p, PZERO - 1); 52436Sbill p->p_flag &= ~SVFDONE; 52536Sbill } 52636Sbill for(i=0; i<NOFILE; i++) { 527*2329Swnj #ifndef UCBIPC 52836Sbill f = u.u_ofile[i]; 52936Sbill u.u_ofile[i] = NULL; 53036Sbill closef(f); 531*2329Swnj #else UCBIPC 532*2329Swnj if (u.u_pofile[i]&ISPORT) { 533*2329Swnj pt = u.u_oport[i]; 534*2329Swnj if (--pt->pt_count == 0) 535*2329Swnj ptclose(pt); 536*2329Swnj u.u_oport[i] = NULL; 537*2329Swnj } else { 538*2329Swnj f = u.u_ofile[i]; 539*2329Swnj u.u_ofile[i] = NULL; 540*2329Swnj closef(f); 541*2329Swnj } 542*2329Swnj #endif UCBIPC 54336Sbill } 54436Sbill plock(u.u_cdir); 54536Sbill iput(u.u_cdir); 54636Sbill if (u.u_rdir) { 54736Sbill plock(u.u_rdir); 54836Sbill iput(u.u_rdir); 54936Sbill } 550363Sbill u.u_limit[LIM_FSIZE] = INFINITY; 55136Sbill acct(); 55236Sbill vrelpt(u.u_procp); 55336Sbill vrelu(u.u_procp, 0); 55436Sbill multprog--; 555307Sbill /* spl7(); /* clock will get mad because of overlaying */ 556931Sbill p->p_stat = SZOMB; 557307Sbill noproc = 1; 55836Sbill i = PIDHASH(p->p_pid); 55936Sbill x = p - proc; 56036Sbill if (pidhash[i] == x) 56136Sbill pidhash[i] = p->p_idhash; 56236Sbill else { 56336Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 56436Sbill if (proc[i].p_idhash == x) { 56536Sbill proc[i].p_idhash = p->p_idhash; 56636Sbill goto done; 56736Sbill } 56836Sbill panic("exit"); 56936Sbill } 5701409Sbill if (p->p_pid == 1) 5711409Sbill panic("init died"); 57236Sbill done: 57336Sbill ((struct xproc *)p)->xp_xstat = rv; /* overlay */ 57436Sbill ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ 57536Sbill vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); 57636Sbill for(q = &proc[0]; q < &proc[NPROC]; q++) 577188Sbill if(q->p_pptr == p) { 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 598354Sbill * tty signals, clear TSTP/TTIN/TTOU if pending, 599354Sbill * and set SDETACH bit on procs. 600215Sbill */ 6011788Sbill (void) spgrp(q, -1); 60236Sbill } 603188Sbill wakeup((caddr_t)p->p_pptr); 604188Sbill psignal(p->p_pptr, SIGCHLD); 60536Sbill swtch(); 60636Sbill } 60736Sbill 60836Sbill wait() 60936Sbill { 610188Sbill struct vtimes vm; 611188Sbill struct vtimes *vp; 61236Sbill 613188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 614188Sbill wait1(0, (struct vtimes *)0); 615188Sbill return; 616188Sbill } 617188Sbill vp = (struct vtimes *)u.u_ar0[R1]; 618188Sbill wait1(u.u_ar0[R0], &vm); 619188Sbill if (u.u_error) 620188Sbill return; 621188Sbill (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); 62236Sbill } 62336Sbill 62436Sbill /* 62536Sbill * Wait system call. 62636Sbill * Search for a terminated (zombie) child, 62736Sbill * finally lay it to rest, and collect its status. 62836Sbill * Look also for stopped (traced) children, 62936Sbill * and pass back status from them. 63036Sbill */ 631188Sbill wait1(options, vp) 632188Sbill register options; 63336Sbill struct vtimes *vp; 63436Sbill { 63536Sbill register f; 63636Sbill register struct proc *p; 63736Sbill 63836Sbill f = 0; 63936Sbill loop: 64036Sbill for(p = &proc[0]; p < &proc[NPROC]; p++) 641188Sbill if(p->p_pptr == u.u_procp) { 64236Sbill f++; 64336Sbill if(p->p_stat == SZOMB) { 64436Sbill u.u_r.r_val1 = p->p_pid; 64536Sbill u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 64636Sbill ((struct xproc *)p)->xp_xstat = 0; 64736Sbill if (vp) 64836Sbill *vp = ((struct xproc *)p)->xp_vm; 64936Sbill vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); 65036Sbill ((struct xproc *)p)->xp_vm = zvms; 65136Sbill p->p_stat = NULL; 65236Sbill p->p_pid = 0; 65336Sbill p->p_ppid = 0; 654188Sbill p->p_pptr = 0; 65536Sbill p->p_sig = 0; 656188Sbill p->p_siga0 = 0; 657188Sbill p->p_siga1 = 0; 65836Sbill p->p_pgrp = 0; 65936Sbill p->p_flag = 0; 66036Sbill p->p_wchan = 0; 661188Sbill p->p_cursig = 0; 66236Sbill return; 66336Sbill } 664188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 665188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 666188Sbill p->p_flag |= SWTED; 667188Sbill u.u_r.r_val1 = p->p_pid; 668188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 669188Sbill return; 67036Sbill } 67136Sbill } 672188Sbill if (f==0) { 673188Sbill u.u_error = ECHILD; 674188Sbill return; 67536Sbill } 676188Sbill if (options&WNOHANG) { 677188Sbill u.u_r.r_val1 = 0; 678188Sbill return; 679188Sbill } 680912Sbill if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 681188Sbill u.u_eosys = RESTARTSYS; 682188Sbill return; 683188Sbill } 684188Sbill sleep((caddr_t)u.u_procp, PWAIT); 685188Sbill goto loop; 68636Sbill } 68736Sbill 68836Sbill /* 68936Sbill * fork system call. 69036Sbill */ 69136Sbill fork() 69236Sbill { 69336Sbill 69436Sbill u.u_cdmap = zdmap; 69536Sbill u.u_csmap = zdmap; 69636Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 69736Sbill u.u_r.r_val2 = 0; 69836Sbill return; 69936Sbill } 70036Sbill fork1(0); 70136Sbill } 70236Sbill 70336Sbill fork1(isvfork) 70436Sbill { 70536Sbill register struct proc *p1, *p2; 70636Sbill register a; 70736Sbill 70836Sbill a = 0; 70936Sbill p2 = NULL; 71036Sbill for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { 71136Sbill if (p1->p_stat==NULL && p2==NULL) 71236Sbill p2 = p1; 71336Sbill else { 71436Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 71536Sbill a++; 71636Sbill } 71736Sbill } 71836Sbill /* 71936Sbill * Disallow if 72036Sbill * No processes at all; 72136Sbill * not su and too many procs owned; or 72236Sbill * not su and would take last slot. 72336Sbill */ 724*2329Swnj if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { 72536Sbill u.u_error = EAGAIN; 72636Sbill if (!isvfork) { 727132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 728132Sbill (void) vsexpand(0, &u.u_csmap, 1); 72936Sbill } 73036Sbill goto out; 73136Sbill } 73236Sbill p1 = u.u_procp; 73336Sbill if(newproc(isvfork)) { 73436Sbill u.u_r.r_val1 = p1->p_pid; 73536Sbill u.u_r.r_val2 = 1; /* child */ 73636Sbill u.u_start = time; 73736Sbill u.u_acflag = AFORK; 73836Sbill return; 73936Sbill } 74036Sbill u.u_r.r_val1 = p2->p_pid; 74136Sbill 74236Sbill out: 74336Sbill u.u_r.r_val2 = 0; 74436Sbill } 74536Sbill 74636Sbill /* 74736Sbill * break system call. 74836Sbill * -- bad planning: "break" is a dirty word in C. 74936Sbill */ 75036Sbill sbreak() 75136Sbill { 75236Sbill struct a { 75336Sbill char *nsiz; 75436Sbill }; 75536Sbill register int n, d; 75636Sbill 75736Sbill /* 75836Sbill * set n to new data size 75936Sbill * set d to new-old 76036Sbill */ 76136Sbill 76236Sbill n = btoc(((struct a *)u.u_ap)->nsiz); 76336Sbill if (!u.u_sep) 76436Sbill n -= ctos(u.u_tsize) * stoc(1); 76536Sbill if (n < 0) 76636Sbill n = 0; 76736Sbill d = clrnd(n - u.u_dsize); 768368Sbill if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) { 769363Sbill u.u_error = ENOMEM; 770363Sbill return; 771363Sbill } 77236Sbill if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) 77336Sbill return; 77436Sbill if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) 77536Sbill return; 77636Sbill expand(d, P0BR); 77736Sbill } 778