1*6568Smckusic /* kern_proc.c 4.26 82/04/19 */ 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; 49*6568Smckusic char cfname[MAXNAMLEN + 1]; 502301Skre char cfarg[SHSIZE]; 5136Sbill 525991Swnj if ((ip = namei(uchar, 0, 1)) == NULL) 5336Sbill return; 5436Sbill bno = 0; 5536Sbill bp = 0; 562301Skre indir = 0; 572301Skre uid = u.u_uid; 582301Skre gid = u.u_gid; 592301Skre if (ip->i_mode & ISUID) 602301Skre uid = ip->i_uid; 612301Skre if (ip->i_mode & ISGID) 622301Skre gid = ip->i_gid; 632301Skre 642301Skre again: 654827Swnj if (access(ip, IEXEC)) 6636Sbill goto bad; 674827Swnj if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) 682330Swnj goto bad; 694827Swnj 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; 954827Swnj if (u.u_error) 962301Skre goto bad; 974982Swnj if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && 984982Swnj 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 } 154*6568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, 155*6568Smckusic u.u_dent.d_namlen + 1); 1562301Skre indir = 1; 1572301Skre iput(ip); 1585991Swnj ip = namei(schar, 0, 1); 1592301Skre if (ip == NULL) 1602301Skre return; 1612301Skre goto again; 1622301Skre } 1632301Skre 1642301Skre /* 16536Sbill * Collect arguments on "file" in swap space. 16636Sbill */ 16736Sbill na = 0; 16836Sbill ne = 0; 16936Sbill nc = 0; 17036Sbill uap = (struct execa *)u.u_ap; 1712780Swnj if ((bno = rmalloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 17236Sbill swkill(u.u_procp, "exece"); 17336Sbill goto bad; 17436Sbill } 17536Sbill if (bno % CLSIZE) 1762780Swnj panic("execa rmalloc"); 17736Sbill if (uap->argp) for (;;) { 17836Sbill ap = NULL; 1793621Sroot if (indir && (na == 1 || na == 2 && sharg)) 1802301Skre ap = (int)uap->fname; 1812301Skre else if (uap->argp) { 18236Sbill ap = fuword((caddr_t)uap->argp); 18336Sbill uap->argp++; 18436Sbill } 18536Sbill if (ap==NULL && uap->envp) { 18636Sbill uap->argp = NULL; 18736Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 18836Sbill break; 18936Sbill uap->envp++; 19036Sbill ne++; 19136Sbill } 192*6568Smckusic if (ap == NULL) 19336Sbill break; 19436Sbill na++; 1954827Swnj if (ap == -1) 19636Sbill u.u_error = EFAULT; 19736Sbill do { 19836Sbill if (nc >= NCARGS-1) 19936Sbill u.u_error = E2BIG; 2002301Skre if (indir && na == 2 && sharg != NULL) 2012301Skre c = *sharg++ & 0377; 2022301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 20336Sbill u.u_error = EFAULT; 20483Sbill if (u.u_error) { 20583Sbill if (bp) 20683Sbill brelse(bp); 20783Sbill bp = 0; 20836Sbill goto badarg; 20983Sbill } 210*6568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 21136Sbill if (bp) 21236Sbill bdwrite(bp); 213*6568Smckusic bp = getblk(argdev, bno + nc / NBPG, 214*6568Smckusic CLSIZE*NBPG); 21536Sbill cp = bp->b_un.b_addr; 21636Sbill } 21736Sbill nc++; 21836Sbill *cp++ = c; 219*6568Smckusic } while (c > 0); 22036Sbill } 22136Sbill if (bp) 22236Sbill bdwrite(bp); 22336Sbill bp = 0; 22436Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 225*6568Smckusic if (indir) { 226*6568Smckusic u.u_dent.d_namlen = strlen(cfname); 227*6568Smckusic bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, 228*6568Smckusic u.u_dent.d_namlen + 1); 229*6568Smckusic } 2302301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 231912Sbill if (u.u_error) { 23236Sbill badarg: 233*6568Smckusic for (c = 0; c < nc; c += CLSIZE*NBPG) 234*6568Smckusic if (bp = baddr(argdev, bno + c / NBPG, CLSIZE*NBPG)) { 23536Sbill bp->b_flags |= B_AGE; /* throw away */ 23636Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 23736Sbill brelse(bp); 23836Sbill bp = 0; 23936Sbill } 24036Sbill goto bad; 24136Sbill } 24236Sbill 24336Sbill /* 24436Sbill * copy back arglist 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 { 261*6568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 26236Sbill if (bp) 26336Sbill brelse(bp); 264*6568Smckusic bp = bread(argdev, bno + nc / NBPG, 265*6568Smckusic CLSIZE*NBPG); 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) 2812780Swnj rmfree(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; 2984827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 2994827Swnj ip->i_count!=1) { 300890Sbill register struct file *fp; 301890Sbill 3024827Swnj for (fp = file; fp < fileNFILE; fp++) { 3034827Swnj if (fp->f_flag & FSOCKET) 3044827Swnj continue; 305890Sbill if (fp->f_inode == ip && (fp->f_flag&FWRITE)) { 306890Sbill u.u_error = ETXTBSY; 307890Sbill goto bad; 308890Sbill } 3094827Swnj } 31036Sbill } 31136Sbill 31236Sbill /* 3134827Swnj * Compute text and data sizes and make sure not too large. 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; 3204827Swnj 3214827Swnj /* 3224827Swnj * Make sure enough space to start process. 3234827Swnj */ 324912Sbill u.u_cdmap = zdmap; 325912Sbill u.u_csmap = zdmap; 326912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 327912Sbill goto bad; 32836Sbill 329912Sbill /* 330912Sbill * At this point, committed to the new image! 331912Sbill * Release virtual memory resources of old process, and 332912Sbill * initialize the virtual memory of the new process. 333912Sbill * If we resulted from vfork(), instead wakeup our 334912Sbill * parent who will set SVFDONE when he has taken back 335912Sbill * our resources. 336912Sbill */ 337912Sbill u.u_prof.pr_scale = 0; 338912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 339912Sbill vrelvm(); 340912Sbill else { 341912Sbill u.u_procp->p_flag &= ~SVFORK; 342912Sbill u.u_procp->p_flag |= SKEEP; 343912Sbill wakeup((caddr_t)u.u_procp); 344912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 345912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 346912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 347912Sbill } 3483592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 349912Sbill u.u_procp->p_flag |= pagi; 350912Sbill u.u_dmap = u.u_cdmap; 351912Sbill u.u_smap = u.u_csmap; 352912Sbill vgetvm(ts, ds, ss); 353912Sbill 354912Sbill if (pagi == 0) { 35536Sbill /* 356912Sbill * Read in data segment. 35736Sbill */ 358912Sbill u.u_base = (char *)ctob(ts); 359912Sbill u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; 360912Sbill u.u_count = u.u_exdata.ux_dsize; 361912Sbill readi(ip); 362912Sbill } 363912Sbill xalloc(ip, pagi); 364912Sbill if (pagi && u.u_procp->p_textp) 365912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 366912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 367912Sbill 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 36836Sbill 369912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 370912Sbill mtpr(TBIA, 0); 37136Sbill 372912Sbill /* 373912Sbill * set SUID/SGID protections, if no tracing 374912Sbill */ 375912Sbill if ((u.u_procp->p_flag&STRC)==0) { 3764827Swnj u.u_uid = uid; 3774827Swnj u.u_procp->p_uid = uid; 3782301Skre u.u_gid = gid; 3795856Swnj u.u_grps[gid/(sizeof(int)*8)] |= 1 << (gid%(sizeof(int)*8)); 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; 396188Sbill long sigmask; 39736Sbill 3986464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 399188Sbill sigmask <<= 1, rp++) { 400188Sbill switch (*rp) { 401188Sbill 402188Sbill case SIG_IGN: 403188Sbill case SIG_DFL: 404188Sbill case SIG_HOLD: 405188Sbill continue; 406188Sbill 407188Sbill default: 408188Sbill /* 409206Sbill * Normal or deferring catch; revert to default. 410188Sbill */ 411206Sbill (void) spl6(); 412206Sbill *rp = SIG_DFL; 413188Sbill if ((int)*rp & 1) 414188Sbill u.u_procp->p_siga0 |= sigmask; 415188Sbill else 4166327Swnj u.u_procp->p_siga0 &= ~sigmask; 417188Sbill if ((int)*rp & 2) 418188Sbill u.u_procp->p_siga1 |= sigmask; 419188Sbill else 420188Sbill u.u_procp->p_siga1 &= ~sigmask; 421206Sbill (void) spl0(); 422188Sbill continue; 423188Sbill } 424188Sbill } 42536Sbill /* 4264827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 42736Sbill *rp++ = 0; 42836Sbill */ 42936Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 4304827Swnj for (i=0; i<NOFILE; i++) { 43136Sbill if (u.u_pofile[i]&EXCLOSE) { 4325581Swnj closef(u.u_ofile[i], 1); 43336Sbill u.u_ofile[i] = NULL; 434188Sbill u.u_pofile[i] &= ~EXCLOSE; 43536Sbill } 43636Sbill } 4374827Swnj 43836Sbill /* 43936Sbill * Remember file name for accounting. 44036Sbill */ 44136Sbill u.u_acflag &= ~AFORK; 442*6568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm, 443*6568Smckusic u.u_dent.d_namlen + 1); 44436Sbill } 44536Sbill 44636Sbill /* 4474827Swnj * Exit system call: pass back caller's arg 44836Sbill */ 44936Sbill rexit() 45036Sbill { 45136Sbill register struct a { 45236Sbill int rval; 45336Sbill } *uap; 45436Sbill 45536Sbill uap = (struct a *)u.u_ap; 45636Sbill exit((uap->rval & 0377) << 8); 45736Sbill } 45836Sbill 45936Sbill /* 46036Sbill * Release resources. 46136Sbill * Save u. area for parent to look at. 46236Sbill * Enter zombie state. 46336Sbill * Wake up parent and init processes, 46436Sbill * and dispose of children. 46536Sbill */ 46636Sbill exit(rv) 46736Sbill { 46836Sbill register int i; 46936Sbill register struct proc *p, *q; 47036Sbill register struct file *f; 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 } 5084827Swnj for (i=0; i<NOFILE; i++) { 50936Sbill f = u.u_ofile[i]; 51036Sbill u.u_ofile[i] = NULL; 5115581Swnj closef(f, 1); 51236Sbill } 5134827Swnj ilock(u.u_cdir); 51436Sbill iput(u.u_cdir); 51536Sbill if (u.u_rdir) { 5164827Swnj ilock(u.u_rdir); 51736Sbill iput(u.u_rdir); 51836Sbill } 519363Sbill u.u_limit[LIM_FSIZE] = INFINITY; 52036Sbill acct(); 52136Sbill vrelpt(u.u_procp); 52236Sbill vrelu(u.u_procp, 0); 5235630Swnj (void) spl5(); /* hack for mem alloc race XXX */ 52436Sbill multprog--; 525931Sbill p->p_stat = SZOMB; 526307Sbill noproc = 1; 52736Sbill i = PIDHASH(p->p_pid); 52836Sbill x = p - proc; 52936Sbill if (pidhash[i] == x) 53036Sbill pidhash[i] = p->p_idhash; 53136Sbill else { 53236Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 53336Sbill if (proc[i].p_idhash == x) { 53436Sbill proc[i].p_idhash = p->p_idhash; 53536Sbill goto done; 53636Sbill } 53736Sbill panic("exit"); 53836Sbill } 5391409Sbill if (p->p_pid == 1) 5401409Sbill panic("init died"); 54136Sbill done: 54236Sbill ((struct xproc *)p)->xp_xstat = rv; /* overlay */ 54336Sbill ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ 54436Sbill vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); 5454827Swnj for (q = proc; q < procNPROC; q++) 5464827Swnj if (q->p_pptr == p) { 547188Sbill q->p_pptr = &proc[1]; 548188Sbill q->p_ppid = 1; 54936Sbill wakeup((caddr_t)&proc[1]); 550188Sbill /* 551212Sbill * Traced processes are killed 552188Sbill * since their existence means someone is screwing up. 553354Sbill * Stopped processes are sent a hangup and a continue. 554212Sbill * This is designed to be ``safe'' for setuid 555212Sbill * processes since they must be willing to tolerate 556212Sbill * hangups anyways. 557188Sbill */ 558212Sbill if (q->p_flag&STRC) { 559188Sbill q->p_flag &= ~STRC; 560188Sbill psignal(q, SIGKILL); 561212Sbill } else if (q->p_stat == SSTOP) { 562212Sbill psignal(q, SIGHUP); 563212Sbill psignal(q, SIGCONT); 564188Sbill } 565215Sbill /* 566215Sbill * Protect this process from future 5675619Swnj * tty signals, clear TSTP/TTIN/TTOU if pending. 568215Sbill */ 5691788Sbill (void) spgrp(q, -1); 57036Sbill } 5716464Swnj psignal(p->p_pptr, SIGCHLD); 572188Sbill wakeup((caddr_t)p->p_pptr); 57336Sbill swtch(); 57436Sbill } 57536Sbill 57636Sbill wait() 57736Sbill { 578188Sbill struct vtimes vm; 579188Sbill struct vtimes *vp; 58036Sbill 581188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 582188Sbill wait1(0, (struct vtimes *)0); 583188Sbill return; 584188Sbill } 585188Sbill vp = (struct vtimes *)u.u_ar0[R1]; 586188Sbill wait1(u.u_ar0[R0], &vm); 587188Sbill if (u.u_error) 588188Sbill return; 589188Sbill (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); 59036Sbill } 59136Sbill 59236Sbill /* 59336Sbill * Wait system call. 59436Sbill * Search for a terminated (zombie) child, 59536Sbill * finally lay it to rest, and collect its status. 59636Sbill * Look also for stopped (traced) children, 59736Sbill * and pass back status from them. 59836Sbill */ 599188Sbill wait1(options, vp) 600188Sbill register options; 60136Sbill struct vtimes *vp; 60236Sbill { 60336Sbill register f; 60436Sbill register struct proc *p; 60536Sbill 60636Sbill f = 0; 60736Sbill loop: 6084827Swnj for (p = proc; p < procNPROC; p++) 6094827Swnj if (p->p_pptr == u.u_procp) { 61036Sbill f++; 6114827Swnj if (p->p_stat == SZOMB) { 61236Sbill u.u_r.r_val1 = p->p_pid; 61336Sbill u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 61436Sbill ((struct xproc *)p)->xp_xstat = 0; 61536Sbill if (vp) 61636Sbill *vp = ((struct xproc *)p)->xp_vm; 61736Sbill vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); 61836Sbill ((struct xproc *)p)->xp_vm = zvms; 61936Sbill p->p_stat = NULL; 62036Sbill p->p_pid = 0; 62136Sbill p->p_ppid = 0; 622188Sbill p->p_pptr = 0; 62336Sbill p->p_sig = 0; 624188Sbill p->p_siga0 = 0; 625188Sbill p->p_siga1 = 0; 62636Sbill p->p_pgrp = 0; 62736Sbill p->p_flag = 0; 62836Sbill p->p_wchan = 0; 629188Sbill p->p_cursig = 0; 63036Sbill return; 63136Sbill } 632188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 633188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 634188Sbill p->p_flag |= SWTED; 635188Sbill u.u_r.r_val1 = p->p_pid; 636188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 637188Sbill return; 63836Sbill } 63936Sbill } 640188Sbill if (f==0) { 641188Sbill u.u_error = ECHILD; 642188Sbill return; 64336Sbill } 644188Sbill if (options&WNOHANG) { 645188Sbill u.u_r.r_val1 = 0; 646188Sbill return; 647188Sbill } 648912Sbill if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 649188Sbill u.u_eosys = RESTARTSYS; 650188Sbill return; 651188Sbill } 652188Sbill sleep((caddr_t)u.u_procp, PWAIT); 653188Sbill goto loop; 65436Sbill } 65536Sbill 65636Sbill /* 65736Sbill * fork system call. 65836Sbill */ 65936Sbill fork() 66036Sbill { 66136Sbill 66236Sbill u.u_cdmap = zdmap; 66336Sbill u.u_csmap = zdmap; 66436Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 66536Sbill u.u_r.r_val2 = 0; 66636Sbill return; 66736Sbill } 66836Sbill fork1(0); 66936Sbill } 67036Sbill 67136Sbill fork1(isvfork) 67236Sbill { 67336Sbill register struct proc *p1, *p2; 67436Sbill register a; 67536Sbill 67636Sbill a = 0; 67736Sbill p2 = NULL; 6784827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 67936Sbill if (p1->p_stat==NULL && p2==NULL) 68036Sbill p2 = p1; 68136Sbill else { 68236Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 68336Sbill a++; 68436Sbill } 68536Sbill } 68636Sbill /* 68736Sbill * Disallow if 68836Sbill * No processes at all; 68936Sbill * not su and too many procs owned; or 69036Sbill * not su and would take last slot. 69136Sbill */ 6922938Swnj if (p2==NULL) 6932938Swnj tablefull("proc"); 6942741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 69536Sbill u.u_error = EAGAIN; 69636Sbill if (!isvfork) { 697132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 698132Sbill (void) vsexpand(0, &u.u_csmap, 1); 69936Sbill } 70036Sbill goto out; 70136Sbill } 70236Sbill p1 = u.u_procp; 7034827Swnj if (newproc(isvfork)) { 70436Sbill u.u_r.r_val1 = p1->p_pid; 70536Sbill u.u_r.r_val2 = 1; /* child */ 70636Sbill u.u_start = time; 70736Sbill u.u_acflag = AFORK; 70836Sbill return; 70936Sbill } 71036Sbill u.u_r.r_val1 = p2->p_pid; 71136Sbill 71236Sbill out: 71336Sbill u.u_r.r_val2 = 0; 71436Sbill } 71536Sbill 71636Sbill /* 71736Sbill * break system call. 71836Sbill * -- bad planning: "break" is a dirty word in C. 71936Sbill */ 72036Sbill sbreak() 72136Sbill { 72236Sbill struct a { 72336Sbill char *nsiz; 72436Sbill }; 72536Sbill register int n, d; 72636Sbill 72736Sbill /* 72836Sbill * set n to new data size 72936Sbill * set d to new-old 73036Sbill */ 73136Sbill 73236Sbill n = btoc(((struct a *)u.u_ap)->nsiz); 73336Sbill if (!u.u_sep) 73436Sbill n -= ctos(u.u_tsize) * stoc(1); 73536Sbill if (n < 0) 73636Sbill n = 0; 73736Sbill d = clrnd(n - u.u_dsize); 738368Sbill if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) { 739363Sbill u.u_error = ENOMEM; 740363Sbill return; 741363Sbill } 74236Sbill if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) 74336Sbill return; 74436Sbill if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) 74536Sbill return; 74636Sbill expand(d, P0BR); 74736Sbill } 748