1*9996Ssam /* kern_proc.c 4.56 82/12/28 */ 236Sbill 39753Ssam #include "../machine/reg.h" 49753Ssam #include "../machine/pte.h" 59753Ssam #include "../machine/psl.h" 69753Ssam 736Sbill #include "../h/param.h" 836Sbill #include "../h/systm.h" 936Sbill #include "../h/map.h" 1036Sbill #include "../h/dir.h" 1136Sbill #include "../h/user.h" 128030Sroot #include "../h/kernel.h" 1336Sbill #include "../h/proc.h" 1436Sbill #include "../h/buf.h" 1536Sbill #include "../h/inode.h" 1636Sbill #include "../h/seg.h" 1736Sbill #include "../h/acct.h" 188968Sroot #include <wait.h> 1936Sbill #include "../h/vm.h" 2036Sbill #include "../h/text.h" 21890Sbill #include "../h/file.h" 227488Skre #include "../h/quota.h" 237497Sroot #include "../h/descrip.h" 247713Sroot #include "../h/uio.h" 258030Sroot #include "../h/mbuf.h" 269159Ssam #include "../h/nami.h" 2736Sbill 288030Sroot gethostid() 298030Sroot { 308030Sroot 318099Sroot u.u_r.r_val1 = hostid; 328030Sroot } 338030Sroot 348030Sroot sethostid() 358030Sroot { 368099Sroot struct a { 378099Sroot int hostid; 388099Sroot } *uap = (struct a *)u.u_ap; 398030Sroot 408099Sroot if (suser()) 418099Sroot hostid = uap->hostid; 428030Sroot } 438030Sroot 448099Sroot gethostname() 458099Sroot { 468099Sroot register struct a { 478099Sroot char *hostname; 488099Sroot int len; 498099Sroot } *uap = (struct a *)u.u_ap; 508099Sroot register u_int len; 518099Sroot 528099Sroot len = uap->len; 538099Sroot if (len > hostnamelen) 548099Sroot len = hostnamelen; 55*9996Ssam u.u_error = copyout((caddr_t)hostname, (caddr_t)uap->hostname, len); 568099Sroot } 578099Sroot 588099Sroot sethostname() 598099Sroot { 608099Sroot register struct a { 618099Sroot char *hostname; 628099Sroot u_int len; 638099Sroot } *uap = (struct a *)u.u_ap; 648099Sroot 658099Sroot if (!suser()) 668099Sroot return; 678099Sroot if (uap->len > sizeof (hostname) - 1) { 688099Sroot u.u_error = EINVAL; 698099Sroot return; 708099Sroot } 718099Sroot hostnamelen = uap->len; 72*9996Ssam u.u_error = copyin((caddr_t)uap->hostname, hostname, uap->len); 738099Sroot hostname[hostnamelen] = 0; 748099Sroot } 758099Sroot 7636Sbill /* 7736Sbill * exec system call, with and without environments. 7836Sbill */ 7936Sbill struct execa { 8036Sbill char *fname; 8136Sbill char **argp; 8236Sbill char **envp; 8336Sbill }; 8436Sbill 858030Sroot execv() 8636Sbill { 8736Sbill ((struct execa *)u.u_ap)->envp = NULL; 888030Sroot execve(); 8936Sbill } 9036Sbill 918030Sroot execve() 9236Sbill { 9336Sbill register nc; 9436Sbill register char *cp; 9536Sbill register struct buf *bp; 9636Sbill register struct execa *uap; 9736Sbill int na, ne, ucp, ap, c; 982301Skre int indir, uid, gid; 992301Skre char *sharg; 10036Sbill struct inode *ip; 10136Sbill swblk_t bno; 1026568Smckusic char cfname[MAXNAMLEN + 1]; 1032301Skre char cfarg[SHSIZE]; 1047748Sroot int resid; 10536Sbill 1069159Ssam if ((ip = namei(uchar, LOOKUP, 1)) == NULL) 10736Sbill return; 10836Sbill bno = 0; 10936Sbill bp = 0; 1102301Skre indir = 0; 1112301Skre uid = u.u_uid; 1122301Skre gid = u.u_gid; 1132301Skre if (ip->i_mode & ISUID) 1142301Skre uid = ip->i_uid; 1152301Skre if (ip->i_mode & ISGID) 1162301Skre gid = ip->i_gid; 1172301Skre 1182301Skre again: 1194827Swnj if (access(ip, IEXEC)) 12036Sbill goto bad; 1214827Swnj if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) 1222330Swnj goto bad; 1234827Swnj if ((ip->i_mode & IFMT) != IFREG || 12436Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 12536Sbill u.u_error = EACCES; 12636Sbill goto bad; 12736Sbill } 1282301Skre 12936Sbill /* 1302301Skre * Read in first few bytes of file for segment sizes, ux_mag: 1312301Skre * 407 = plain executable 1322301Skre * 410 = RO text 1332301Skre * 413 = demand paged RO text 1342301Skre * Also an ASCII line beginning with #! is 1352301Skre * the file name of a ``shell'' and arguments may be prepended 1362301Skre * to the argument list if given here. 1372301Skre * 1382301Skre * SHELL NAMES ARE LIMITED IN LENGTH. 1392301Skre * 1402301Skre * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 1412301Skre * THE ASCII LINE. 1422301Skre */ 1439753Ssam u.u_exdata.ux_shell[0] = 0; /* for zero length files */ 1447816Sroot u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata), 1457748Sroot 0, 1, &resid); 1464827Swnj if (u.u_error) 1472301Skre goto bad; 1487748Sroot u.u_count = resid; 1497816Sroot #ifndef lint 1504982Swnj if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && 1514982Swnj u.u_exdata.ux_shell[0] != '#') { 1522301Skre u.u_error = ENOEXEC; 1532301Skre goto bad; 1542301Skre } 1557816Sroot #endif 1562301Skre switch (u.u_exdata.ux_mag) { 1572301Skre 1582301Skre case 0407: 1592301Skre u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 1602301Skre u.u_exdata.ux_tsize = 0; 1612301Skre break; 1622301Skre 1632301Skre case 0413: 1642301Skre case 0410: 1652301Skre if (u.u_exdata.ux_tsize == 0) { 1662301Skre u.u_error = ENOEXEC; 1672301Skre goto bad; 1682301Skre } 1692301Skre break; 1702301Skre 1712301Skre default: 1722301Skre if (u.u_exdata.ux_shell[0] != '#' || 1732301Skre u.u_exdata.ux_shell[1] != '!' || 1742301Skre indir) { 1752301Skre u.u_error = ENOEXEC; 1762301Skre goto bad; 1772301Skre } 1782301Skre cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 1792301Skre while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 1802301Skre if (*cp == '\t') 1812301Skre *cp = ' '; 1822301Skre else if (*cp == '\n') { 1832301Skre *cp = '\0'; 1842301Skre break; 1852301Skre } 1862301Skre cp++; 1872301Skre } 1882301Skre if (*cp != '\0') { 1892301Skre u.u_error = ENOEXEC; 1902301Skre goto bad; 1912301Skre } 1922301Skre cp = &u.u_exdata.ux_shell[2]; 1932301Skre while (*cp == ' ') 1942301Skre cp++; 1952301Skre u.u_dirp = cp; 1962301Skre while (*cp && *cp != ' ') 1972301Skre cp++; 1982301Skre sharg = NULL; 1992301Skre if (*cp) { 2002301Skre *cp++ = '\0'; 2012301Skre while (*cp == ' ') 2022301Skre cp++; 2032301Skre if (*cp) { 2042301Skre bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 2052301Skre sharg = cfarg; 2062301Skre } 2072301Skre } 2086568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, 2097816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2102301Skre indir = 1; 2112301Skre iput(ip); 2129159Ssam ip = namei(schar, LOOKUP, 1); 2132301Skre if (ip == NULL) 2142301Skre return; 2152301Skre goto again; 2162301Skre } 2172301Skre 2182301Skre /* 21936Sbill * Collect arguments on "file" in swap space. 22036Sbill */ 22136Sbill na = 0; 22236Sbill ne = 0; 22336Sbill nc = 0; 22436Sbill uap = (struct execa *)u.u_ap; 2258665S if ((bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))))) == 0) { 22636Sbill swkill(u.u_procp, "exece"); 22736Sbill goto bad; 22836Sbill } 22936Sbill if (bno % CLSIZE) 2302780Swnj panic("execa rmalloc"); 23136Sbill if (uap->argp) for (;;) { 23236Sbill ap = NULL; 2333621Sroot if (indir && (na == 1 || na == 2 && sharg)) 2342301Skre ap = (int)uap->fname; 2352301Skre else if (uap->argp) { 23636Sbill ap = fuword((caddr_t)uap->argp); 23736Sbill uap->argp++; 23836Sbill } 23936Sbill if (ap==NULL && uap->envp) { 24036Sbill uap->argp = NULL; 24136Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 24236Sbill break; 24336Sbill uap->envp++; 24436Sbill ne++; 24536Sbill } 2466568Smckusic if (ap == NULL) 24736Sbill break; 24836Sbill na++; 2494827Swnj if (ap == -1) 25036Sbill u.u_error = EFAULT; 25136Sbill do { 25236Sbill if (nc >= NCARGS-1) 25336Sbill u.u_error = E2BIG; 2542301Skre if (indir && na == 2 && sharg != NULL) 2552301Skre c = *sharg++ & 0377; 2562301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 25736Sbill u.u_error = EFAULT; 25883Sbill if (u.u_error) { 25983Sbill if (bp) 26083Sbill brelse(bp); 26183Sbill bp = 0; 26236Sbill goto badarg; 26383Sbill } 2646568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 26536Sbill if (bp) 26636Sbill bdwrite(bp); 2678968Sroot bp = getblk(argdev, bno + ctod(nc / NBPG), 2686568Smckusic CLSIZE*NBPG); 26936Sbill cp = bp->b_un.b_addr; 27036Sbill } 27136Sbill nc++; 27236Sbill *cp++ = c; 2736568Smckusic } while (c > 0); 27436Sbill } 27536Sbill if (bp) 27636Sbill bdwrite(bp); 27736Sbill bp = 0; 27836Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 2796568Smckusic if (indir) { 2806568Smckusic u.u_dent.d_namlen = strlen(cfname); 2816568Smckusic bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, 2827816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2836568Smckusic } 2842301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 285912Sbill if (u.u_error) { 28636Sbill badarg: 2879006Sroot for (c = 0; c < nc; c += CLSIZE*NBPG) { 2889006Sroot bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG); 2898968Sroot if (bp) { 29036Sbill bp->b_flags |= B_AGE; /* throw away */ 29136Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 29236Sbill brelse(bp); 29336Sbill bp = 0; 29436Sbill } 2959006Sroot } 29636Sbill goto bad; 29736Sbill } 29836Sbill 29936Sbill /* 30036Sbill * copy back arglist 30136Sbill */ 30236Sbill ucp = USRSTACK - nc - NBPW; 30336Sbill ap = ucp - na*NBPW - 3*NBPW; 30436Sbill u.u_ar0[SP] = ap; 305132Sbill (void) suword((caddr_t)ap, na-ne); 30636Sbill nc = 0; 30736Sbill for (;;) { 30836Sbill ap += NBPW; 30936Sbill if (na==ne) { 310132Sbill (void) suword((caddr_t)ap, 0); 31136Sbill ap += NBPW; 31236Sbill } 31336Sbill if (--na < 0) 31436Sbill break; 315132Sbill (void) suword((caddr_t)ap, ucp); 31636Sbill do { 3176568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 31836Sbill if (bp) 31936Sbill brelse(bp); 3209866Ssam bp = bread(argdev, bno + ctod(nc / NBPG), 3216568Smckusic CLSIZE*NBPG); 32236Sbill bp->b_flags |= B_AGE; /* throw away */ 32336Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 32436Sbill cp = bp->b_un.b_addr; 32536Sbill } 326132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 32736Sbill nc++; 32836Sbill } while(c&0377); 32936Sbill } 330132Sbill (void) suword((caddr_t)ap, 0); 331132Sbill (void) suword((caddr_t)ucp, 0); 33236Sbill setregs(); 33336Sbill bad: 33436Sbill if (bp) 33536Sbill brelse(bp); 33636Sbill if (bno) 3378816Sroot rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); 33836Sbill iput(ip); 33936Sbill } 34036Sbill 34136Sbill /* 34236Sbill * Read in and set up memory for executed file. 34336Sbill */ 3442301Skre getxfile(ip, nargc, uid, gid) 34536Sbill register struct inode *ip; 34636Sbill { 34736Sbill register size_t ts, ds, ss; 3482301Skre int pagi; 34936Sbill 3502301Skre if (u.u_exdata.ux_mag == 0413) 35136Sbill pagi = SPAGI; 3522301Skre else 3532301Skre pagi = 0; 3544827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 3554827Swnj ip->i_count!=1) { 356890Sbill register struct file *fp; 357890Sbill 3584827Swnj for (fp = file; fp < fileNFILE; fp++) { 3597497Sroot if (fp->f_type == DTYPE_FILE && 3609743Ssam fp->f_count > 0 && 3617497Sroot fp->f_inode == ip && (fp->f_flag&FWRITE)) { 362890Sbill u.u_error = ETXTBSY; 363890Sbill goto bad; 364890Sbill } 3654827Swnj } 36636Sbill } 36736Sbill 36836Sbill /* 3694827Swnj * Compute text and data sizes and make sure not too large. 37036Sbill */ 37136Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 37236Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 37336Sbill ss = clrnd(SSIZE + btoc(nargc)); 374912Sbill if (chksize(ts, ds, ss)) 375912Sbill goto bad; 3764827Swnj 3774827Swnj /* 3784827Swnj * Make sure enough space to start process. 3794827Swnj */ 380912Sbill u.u_cdmap = zdmap; 381912Sbill u.u_csmap = zdmap; 382912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 383912Sbill goto bad; 38436Sbill 385912Sbill /* 386912Sbill * At this point, committed to the new image! 387912Sbill * Release virtual memory resources of old process, and 388912Sbill * initialize the virtual memory of the new process. 389912Sbill * If we resulted from vfork(), instead wakeup our 390912Sbill * parent who will set SVFDONE when he has taken back 391912Sbill * our resources. 392912Sbill */ 393912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 394912Sbill vrelvm(); 395912Sbill else { 396912Sbill u.u_procp->p_flag &= ~SVFORK; 397912Sbill u.u_procp->p_flag |= SKEEP; 398912Sbill wakeup((caddr_t)u.u_procp); 399912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 400912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 401912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 402912Sbill } 4033592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 404912Sbill u.u_procp->p_flag |= pagi; 405912Sbill u.u_dmap = u.u_cdmap; 406912Sbill u.u_smap = u.u_csmap; 407912Sbill vgetvm(ts, ds, ss); 408912Sbill 4097748Sroot if (pagi == 0) 4107816Sroot u.u_error = 4117816Sroot rdwri(UIO_READ, ip, 4128968Sroot (char *)ctob(dptov(u.u_procp, 0)), 4138968Sroot (int)u.u_exdata.ux_dsize, 4147816Sroot (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), 4157816Sroot 0, (int *)0); 416912Sbill xalloc(ip, pagi); 417912Sbill if (pagi && u.u_procp->p_textp) 418912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 419912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 4208665S (long)(1 + ts/CLSIZE), (int)btoc(u.u_exdata.ux_dsize)); 42136Sbill 4228968Sroot #ifdef vax 423912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 4248443Sroot #include "../vax/mtpr.h" /* XXX */ 425912Sbill mtpr(TBIA, 0); 4268968Sroot #endif 42736Sbill 4287530Sroot if (u.u_error) 4297530Sroot swkill(u.u_procp, "i/o error mapping pages"); 430912Sbill /* 431912Sbill * set SUID/SGID protections, if no tracing 432912Sbill */ 433912Sbill if ((u.u_procp->p_flag&STRC)==0) { 4344827Swnj u.u_uid = uid; 4354827Swnj u.u_procp->p_uid = uid; 4362301Skre u.u_gid = gid; 4378665S (void) entergroup(gid); 438912Sbill } else 439912Sbill psignal(u.u_procp, SIGTRAP); 44036Sbill u.u_tsize = ts; 44136Sbill u.u_dsize = ds; 44236Sbill u.u_ssize = ss; 44336Sbill bad: 444912Sbill return; 44536Sbill } 44636Sbill 44736Sbill /* 44836Sbill * Clear registers on exec 44936Sbill */ 45036Sbill setregs() 45136Sbill { 452173Sbill register int (**rp)(); 45336Sbill register i; 454188Sbill long sigmask; 45536Sbill 4566464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 457188Sbill sigmask <<= 1, rp++) { 458188Sbill switch (*rp) { 459188Sbill 460188Sbill case SIG_IGN: 461188Sbill case SIG_DFL: 462188Sbill case SIG_HOLD: 463188Sbill continue; 464188Sbill 465188Sbill default: 466188Sbill /* 467206Sbill * Normal or deferring catch; revert to default. 468188Sbill */ 469206Sbill (void) spl6(); 470206Sbill *rp = SIG_DFL; 471188Sbill if ((int)*rp & 1) 472188Sbill u.u_procp->p_siga0 |= sigmask; 473188Sbill else 4746327Swnj u.u_procp->p_siga0 &= ~sigmask; 475188Sbill if ((int)*rp & 2) 476188Sbill u.u_procp->p_siga1 |= sigmask; 477188Sbill else 478188Sbill u.u_procp->p_siga1 &= ~sigmask; 479206Sbill (void) spl0(); 480188Sbill continue; 481188Sbill } 482188Sbill } 4838968Sroot #ifdef vax 48436Sbill /* 4854827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 48636Sbill *rp++ = 0; 48736Sbill */ 4888968Sroot u.u_ar0[PC] = u.u_exdata.ux_entloc+2; 4898968Sroot #endif 4908968Sroot #ifdef sun 4918968Sroot { register struct regs *r = (struct regs *)u.u_ar0; 4928968Sroot for (i = 0; i < 8; i++) { 4938968Sroot r->r_dreg[i] = 0; 4948968Sroot if (&r->r_areg[i] != &r->r_sp) 4958968Sroot r->r_areg[i] = 0; 4968968Sroot } 4978968Sroot r->r_sr = PSL_USERSET; 4988968Sroot r->r_pc = u.u_exdata.ux_entloc; 4998968Sroot } 5008968Sroot #endif 5014827Swnj for (i=0; i<NOFILE; i++) { 5029591Ssam if (u.u_pofile[i]&UF_EXCLOSE) { 5037697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 50436Sbill u.u_ofile[i] = NULL; 5057697Ssam u.u_pofile[i] = 0; 50636Sbill } 5078968Sroot u.u_pofile[i] &= ~UF_MAPPED; 50836Sbill } 5094827Swnj 51036Sbill /* 51136Sbill * Remember file name for accounting. 51236Sbill */ 51336Sbill u.u_acflag &= ~AFORK; 5146568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm, 5157816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 5168968Sroot #ifdef sun 5178968Sroot u.u_eosys = REALLYRETURN; 5188968Sroot #endif 51936Sbill } 52036Sbill 52136Sbill /* 5224827Swnj * Exit system call: pass back caller's arg 52336Sbill */ 52436Sbill rexit() 52536Sbill { 52636Sbill register struct a { 52736Sbill int rval; 52836Sbill } *uap; 52936Sbill 53036Sbill uap = (struct a *)u.u_ap; 53136Sbill exit((uap->rval & 0377) << 8); 53236Sbill } 53336Sbill 53436Sbill /* 53536Sbill * Release resources. 53636Sbill * Save u. area for parent to look at. 53736Sbill * Enter zombie state. 53836Sbill * Wake up parent and init processes, 53936Sbill * and dispose of children. 54036Sbill */ 54136Sbill exit(rv) 54236Sbill { 54336Sbill register int i; 54436Sbill register struct proc *p, *q; 54536Sbill register int x; 5469632Ssam struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE); 54736Sbill 54836Sbill #ifdef PGINPROF 54936Sbill vmsizmon(); 55036Sbill #endif 55136Sbill p = u.u_procp; 55236Sbill p->p_flag &= ~(STRC|SULOCK); 55336Sbill p->p_flag |= SWEXIT; 554188Sbill (void) spl6(); 555188Sbill if ((int)SIG_IGN & 1) 556188Sbill p->p_siga0 = ~0; 557188Sbill else 558188Sbill p->p_siga0 = 0; 559188Sbill if ((int)SIG_IGN & 2) 560188Sbill p->p_siga1 = ~0; 561188Sbill else 562206Sbill p->p_siga1 = 0; 563188Sbill (void) spl0(); 5641399Sbill p->p_cpticks = 0; 5651399Sbill p->p_pctcpu = 0; 5664827Swnj for (i=0; i<NSIG; i++) 567173Sbill u.u_signal[i] = SIG_IGN; 5688623Sroot untimeout(realitexpire, (caddr_t)p); 56936Sbill /* 57036Sbill * Release virtual memory. If we resulted from 57136Sbill * a vfork(), instead give the resources back to 57236Sbill * the parent. 57336Sbill */ 57436Sbill if ((p->p_flag & SVFORK) == 0) 57536Sbill vrelvm(); 57636Sbill else { 57736Sbill p->p_flag &= ~SVFORK; 57836Sbill wakeup((caddr_t)p); 57936Sbill while ((p->p_flag & SVFDONE) == 0) 58036Sbill sleep((caddr_t)p, PZERO - 1); 58136Sbill p->p_flag &= ~SVFDONE; 58236Sbill } 5837697Ssam for (i = 0; i < NOFILE; i++) { 5849558Ssam struct file *f; 5859558Ssam int p; 5869558Ssam 58736Sbill f = u.u_ofile[i]; 58836Sbill u.u_ofile[i] = NULL; 5899558Ssam p = u.u_pofile[i]; 5907697Ssam u.u_pofile[i] = 0; 5919558Ssam closef(f, 1, p); 59236Sbill } 5934827Swnj ilock(u.u_cdir); 59436Sbill iput(u.u_cdir); 59536Sbill if (u.u_rdir) { 5964827Swnj ilock(u.u_rdir); 59736Sbill iput(u.u_rdir); 59836Sbill } 5998030Sroot u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 60036Sbill acct(); 6017488Skre #ifdef QUOTA 6027488Skre qclean(); 6037488Skre #endif 6048968Sroot #ifdef sun 6058968Sroot ctxfree(&u); 6068968Sroot #endif 60736Sbill vrelpt(u.u_procp); 60836Sbill vrelu(u.u_procp, 0); 6095630Swnj (void) spl5(); /* hack for mem alloc race XXX */ 61036Sbill multprog--; 611931Sbill p->p_stat = SZOMB; 612307Sbill noproc = 1; 61336Sbill i = PIDHASH(p->p_pid); 61436Sbill x = p - proc; 61536Sbill if (pidhash[i] == x) 61636Sbill pidhash[i] = p->p_idhash; 61736Sbill else { 61836Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 61936Sbill if (proc[i].p_idhash == x) { 62036Sbill proc[i].p_idhash = p->p_idhash; 62136Sbill goto done; 62236Sbill } 62336Sbill panic("exit"); 62436Sbill } 6251409Sbill if (p->p_pid == 1) 6261409Sbill panic("init died"); 62736Sbill done: 6288030Sroot p->p_xstat = rv; 6299558Ssam if (m == 0) 6309558Ssam panic("exit: m_getclr"); 6318827Sroot p->p_ru = mtod(m, struct rusage *); 6328030Sroot *p->p_ru = u.u_ru; 6338030Sroot ruadd(p->p_ru, &u.u_cru); 6344827Swnj for (q = proc; q < procNPROC; q++) 6354827Swnj if (q->p_pptr == p) { 6367488Skre if (q->p_osptr) 6377488Skre q->p_osptr->p_ysptr = q->p_ysptr; 6387488Skre if (q->p_ysptr) 6397488Skre q->p_ysptr->p_osptr = q->p_osptr; 6407488Skre if (proc[1].p_cptr) 6417488Skre proc[1].p_cptr->p_ysptr = q; 6427488Skre q->p_osptr = proc[1].p_cptr; 6437488Skre q->p_ysptr = NULL; 6447488Skre proc[1].p_cptr = q; 6457488Skre 646188Sbill q->p_pptr = &proc[1]; 647188Sbill q->p_ppid = 1; 64836Sbill wakeup((caddr_t)&proc[1]); 649188Sbill /* 650212Sbill * Traced processes are killed 651188Sbill * since their existence means someone is screwing up. 652354Sbill * Stopped processes are sent a hangup and a continue. 653212Sbill * This is designed to be ``safe'' for setuid 654212Sbill * processes since they must be willing to tolerate 655212Sbill * hangups anyways. 656188Sbill */ 657212Sbill if (q->p_flag&STRC) { 658188Sbill q->p_flag &= ~STRC; 659188Sbill psignal(q, SIGKILL); 660212Sbill } else if (q->p_stat == SSTOP) { 661212Sbill psignal(q, SIGHUP); 662212Sbill psignal(q, SIGCONT); 663188Sbill } 664215Sbill /* 665215Sbill * Protect this process from future 6665619Swnj * tty signals, clear TSTP/TTIN/TTOU if pending. 667215Sbill */ 6681788Sbill (void) spgrp(q, -1); 66936Sbill } 6706464Swnj psignal(p->p_pptr, SIGCHLD); 671188Sbill wakeup((caddr_t)p->p_pptr); 67236Sbill swtch(); 67336Sbill } 67436Sbill 6759990Ssam wait() 6769990Ssam { 6779990Ssam struct rusage ru, *rup; 6789990Ssam 6799990Ssam if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 6809990Ssam u.u_error = wait1(0, (struct rusage *)0); 6819990Ssam return; 6829990Ssam } 6839990Ssam rup = (struct rusage *)u.u_ar0[R1]; 6849990Ssam u.u_error = wait1(u.u_ar0[R0], &ru); 6859990Ssam if (u.u_error) 6869990Ssam return; 6879990Ssam (void) copyout((caddr_t)&ru, (caddr_t)rup, sizeof (struct rusage)); 6889990Ssam } 6899990Ssam 6909990Ssam #ifndef NOCOMPAT 6919753Ssam #include "../h/vtimes.h" 6928151Sroot 6938099Sroot owait() 69436Sbill { 6958151Sroot struct rusage ru; 6968151Sroot struct vtimes *vtp, avt; 69736Sbill 698188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 6999990Ssam u.u_error = wait1(0, (struct rusage *)0); 700188Sbill return; 701188Sbill } 7028151Sroot vtp = (struct vtimes *)u.u_ar0[R1]; 7039990Ssam u.u_error = wait1(u.u_ar0[R0], &ru); 704188Sbill if (u.u_error) 705188Sbill return; 7068151Sroot getvtimes(&ru, &avt); 7078151Sroot (void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes)); 70836Sbill } 7099990Ssam #endif 71036Sbill 71136Sbill /* 71236Sbill * Wait system call. 71336Sbill * Search for a terminated (zombie) child, 71436Sbill * finally lay it to rest, and collect its status. 71536Sbill * Look also for stopped (traced) children, 71636Sbill * and pass back status from them. 71736Sbill */ 7188030Sroot wait1(options, ru) 7198030Sroot register int options; 7208030Sroot struct rusage *ru; 72136Sbill { 72236Sbill register f; 7237488Skre register struct proc *p, *q; 72436Sbill 72536Sbill f = 0; 72636Sbill loop: 7274827Swnj for (p = proc; p < procNPROC; p++) 7284827Swnj if (p->p_pptr == u.u_procp) { 72936Sbill f++; 7304827Swnj if (p->p_stat == SZOMB) { 73136Sbill u.u_r.r_val1 = p->p_pid; 7328030Sroot u.u_r.r_val2 = p->p_xstat; 7338030Sroot p->p_xstat = 0; 7348030Sroot if (ru) 7358030Sroot *ru = *p->p_ru; 7368030Sroot ruadd(&u.u_cru, p->p_ru); 7378665S (void) m_free(dtom(p->p_ru)); 7388030Sroot p->p_ru = 0; 73936Sbill p->p_stat = NULL; 74036Sbill p->p_pid = 0; 74136Sbill p->p_ppid = 0; 7427488Skre if (q = p->p_ysptr) 7437488Skre q->p_osptr = p->p_osptr; 7447488Skre if (q = p->p_osptr) 7457488Skre q->p_ysptr = p->p_ysptr; 7467488Skre if ((q = p->p_pptr)->p_cptr == p) 7477488Skre q->p_cptr = p->p_osptr; 748188Sbill p->p_pptr = 0; 7497488Skre p->p_ysptr = 0; 7507488Skre p->p_osptr = 0; 7517488Skre p->p_cptr = 0; 75236Sbill p->p_sig = 0; 753188Sbill p->p_siga0 = 0; 754188Sbill p->p_siga1 = 0; 75536Sbill p->p_pgrp = 0; 75636Sbill p->p_flag = 0; 75736Sbill p->p_wchan = 0; 758188Sbill p->p_cursig = 0; 7599990Ssam return (0); 76036Sbill } 761188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 762188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 763188Sbill p->p_flag |= SWTED; 764188Sbill u.u_r.r_val1 = p->p_pid; 765188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 7669990Ssam return (0); 76736Sbill } 76836Sbill } 7699990Ssam if (f == 0) { 7709990Ssam return (ECHILD); 77136Sbill } 772188Sbill if (options&WNOHANG) { 773188Sbill u.u_r.r_val1 = 0; 7749990Ssam return (0); 775188Sbill } 7768116Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 777188Sbill u.u_eosys = RESTARTSYS; 7789990Ssam return (0); 779188Sbill } 780188Sbill sleep((caddr_t)u.u_procp, PWAIT); 781188Sbill goto loop; 78236Sbill } 78336Sbill 78436Sbill /* 78536Sbill * fork system call. 78636Sbill */ 78736Sbill fork() 78836Sbill { 78936Sbill 79036Sbill u.u_cdmap = zdmap; 79136Sbill u.u_csmap = zdmap; 79236Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 79336Sbill u.u_r.r_val2 = 0; 79436Sbill return; 79536Sbill } 79636Sbill fork1(0); 79736Sbill } 79836Sbill 79936Sbill fork1(isvfork) 80036Sbill { 80136Sbill register struct proc *p1, *p2; 8027488Skre #ifndef QUOTA 80336Sbill register a; 80436Sbill 80536Sbill a = 0; 8067488Skre #else 8077488Skre if (u.u_quota != NOQUOT && u.u_quota->q_plim && 8087488Skre u.u_quota->q_cnt >= u.u_quota->q_plim) { 8097488Skre u.u_error = EPROCLIM; 8107488Skre return; 8117488Skre } 8127488Skre #endif 81336Sbill p2 = NULL; 8144827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 8157488Skre #ifdef QUOTA 8167488Skre if (p1->p_stat == NULL) { 8177488Skre p2 = p1; 8187488Skre break; 8197488Skre } 8207488Skre #else 82136Sbill if (p1->p_stat==NULL && p2==NULL) 82236Sbill p2 = p1; 82336Sbill else { 82436Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 82536Sbill a++; 82636Sbill } 8277488Skre #endif 82836Sbill } 82936Sbill /* 83036Sbill * Disallow if 83136Sbill * No processes at all; 83236Sbill * not su and too many procs owned; or 83336Sbill * not su and would take last slot. 83436Sbill */ 8352938Swnj if (p2==NULL) 8362938Swnj tablefull("proc"); 8377488Skre #ifdef QUOTA 8387488Skre if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { 8397488Skre #else 8402741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 8417488Skre #endif 84236Sbill u.u_error = EAGAIN; 84336Sbill if (!isvfork) { 844132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 845132Sbill (void) vsexpand(0, &u.u_csmap, 1); 84636Sbill } 84736Sbill goto out; 84836Sbill } 84936Sbill p1 = u.u_procp; 8504827Swnj if (newproc(isvfork)) { 85136Sbill u.u_r.r_val1 = p1->p_pid; 85236Sbill u.u_r.r_val2 = 1; /* child */ 8538030Sroot u.u_start = time.tv_sec; 85436Sbill u.u_acflag = AFORK; 8557488Skre #ifdef QUOTA 8567488Skre u.u_qflags &= ~QUF_LOGIN; 8577488Skre #endif 85836Sbill return; 85936Sbill } 86036Sbill u.u_r.r_val1 = p2->p_pid; 86136Sbill 86236Sbill out: 86336Sbill u.u_r.r_val2 = 0; 86436Sbill } 86536Sbill 8667497Sroot spgrp(top, npgrp) 8677497Sroot register struct proc *top; 8687497Sroot { 8697497Sroot register struct proc *pp, *p; 8707497Sroot int f = 0; 8717497Sroot 8727497Sroot for (p = top; npgrp == -1 || u.u_uid == p->p_uid || 8737497Sroot !u.u_uid || inferior(p); p = pp) { 8747497Sroot if (npgrp == -1) { 8757497Sroot #define bit(a) (1<<(a-1)) 8767497Sroot p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 8777497Sroot } else 8787497Sroot p->p_pgrp = npgrp; 8797497Sroot f++; 8807497Sroot /* 8817497Sroot * Search for children. 8827497Sroot */ 8837497Sroot for (pp = proc; pp < procNPROC; pp++) 8847497Sroot if (pp->p_pptr == p) 8857497Sroot goto cont; 8867497Sroot /* 8877497Sroot * Search for siblings. 8887497Sroot */ 8897497Sroot for (; p != top; p = p->p_pptr) 8907497Sroot for (pp = p + 1; pp < procNPROC; pp++) 8917497Sroot if (pp->p_pptr == p->p_pptr) 8927497Sroot goto cont; 8937497Sroot break; 8947497Sroot cont: 8957497Sroot ; 8967497Sroot } 8977497Sroot return (f); 8987497Sroot } 8997497Sroot 90036Sbill /* 9017497Sroot * Is p an inferior of the current process? 90236Sbill */ 9037497Sroot inferior(p) 9047816Sroot register struct proc *p; 90536Sbill { 90636Sbill 9077497Sroot for (; p != u.u_procp; p = p->p_pptr) 9087497Sroot if (p->p_ppid == 0) 9097497Sroot return (0); 9107497Sroot return (1); 91136Sbill } 9127816Sroot 9137816Sroot struct proc * 9147816Sroot pfind(pid) 9157816Sroot int pid; 9167816Sroot { 9177816Sroot register struct proc *p; 9187816Sroot 9197816Sroot for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 9207816Sroot if (p->p_pid == pid) 9217816Sroot return (p); 9227816Sroot return ((struct proc *)0); 9237816Sroot } 9248099Sroot 9258099Sroot /* 9268099Sroot * Create a new process-- the internal version of 9278099Sroot * sys fork. 9288099Sroot * It returns 1 in the new process, 0 in the old. 9298099Sroot */ 9308099Sroot newproc(isvfork) 9318099Sroot int isvfork; 9328099Sroot { 9338099Sroot register struct proc *p; 9348099Sroot register struct proc *rpp, *rip; 9358099Sroot register int n; 9368099Sroot register struct file *fp; 9378099Sroot 9388099Sroot p = NULL; 9398099Sroot /* 9408099Sroot * First, just locate a slot for a process 9418099Sroot * and copy the useful info from this process into it. 9428099Sroot * The panic "cannot happen" because fork has already 9438099Sroot * checked for the existence of a slot. 9448099Sroot */ 9458099Sroot retry: 9468099Sroot mpid++; 9478099Sroot if (mpid >= 30000) { 9488099Sroot mpid = 0; 9498099Sroot goto retry; 9508099Sroot } 9518099Sroot for (rpp = proc; rpp < procNPROC; rpp++) { 9528099Sroot if (rpp->p_stat == NULL && p==NULL) 9538099Sroot p = rpp; 9548099Sroot if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) 9558099Sroot goto retry; 9568099Sroot } 9578099Sroot if ((rpp = p) == NULL) 9588099Sroot panic("no procs"); 9598099Sroot 9608099Sroot /* 9618099Sroot * Make a proc table entry for the new process. 9628099Sroot */ 9638099Sroot rip = u.u_procp; 9648099Sroot #ifdef QUOTA 9658099Sroot (rpp->p_quota = rip->p_quota)->q_cnt++; 9668099Sroot #endif 9678099Sroot rpp->p_stat = SIDL; 9688099Sroot timerclear(&rpp->p_realtimer.it_value); 9698099Sroot rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG)); 9708099Sroot if (isvfork) { 9718099Sroot rpp->p_flag |= SVFORK; 9728099Sroot rpp->p_ndx = rip->p_ndx; 9738099Sroot } else 9748099Sroot rpp->p_ndx = rpp - proc; 9758099Sroot rpp->p_uid = rip->p_uid; 9768099Sroot rpp->p_pgrp = rip->p_pgrp; 9778099Sroot rpp->p_nice = rip->p_nice; 9788099Sroot rpp->p_textp = isvfork ? 0 : rip->p_textp; 9798099Sroot rpp->p_pid = mpid; 9808099Sroot rpp->p_ppid = rip->p_pid; 9818099Sroot rpp->p_pptr = rip; 9828099Sroot rpp->p_osptr = rip->p_cptr; 9838099Sroot if (rip->p_cptr) 9848099Sroot rip->p_cptr->p_ysptr = rpp; 9858099Sroot rpp->p_ysptr = NULL; 9868099Sroot rpp->p_cptr = NULL; 9878099Sroot rip->p_cptr = rpp; 9888099Sroot rpp->p_time = 0; 9898099Sroot rpp->p_cpu = 0; 9908099Sroot rpp->p_siga0 = rip->p_siga0; 9918099Sroot rpp->p_siga1 = rip->p_siga1; 9928099Sroot /* take along any pending signals, like stops? */ 9938099Sroot if (isvfork) { 9948099Sroot rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; 9958099Sroot rpp->p_szpt = clrnd(ctopt(UPAGES)); 9968099Sroot forkstat.cntvfork++; 9978099Sroot forkstat.sizvfork += rip->p_dsize + rip->p_ssize; 9988099Sroot } else { 9998099Sroot rpp->p_tsize = rip->p_tsize; 10008099Sroot rpp->p_dsize = rip->p_dsize; 10018099Sroot rpp->p_ssize = rip->p_ssize; 10028099Sroot rpp->p_szpt = rip->p_szpt; 10038099Sroot forkstat.cntfork++; 10048099Sroot forkstat.sizfork += rip->p_dsize + rip->p_ssize; 10058099Sroot } 10068099Sroot rpp->p_rssize = 0; 10078099Sroot rpp->p_maxrss = rip->p_maxrss; 10088099Sroot rpp->p_wchan = 0; 10098099Sroot rpp->p_slptime = 0; 10108099Sroot rpp->p_pctcpu = 0; 10118099Sroot rpp->p_cpticks = 0; 10128099Sroot n = PIDHASH(rpp->p_pid); 10138099Sroot p->p_idhash = pidhash[n]; 10148099Sroot pidhash[n] = rpp - proc; 10158099Sroot multprog++; 10168099Sroot 10178099Sroot /* 10188099Sroot * Increase reference counts on shared objects. 10198099Sroot */ 10208099Sroot for (n = 0; n < NOFILE; n++) { 10218099Sroot fp = u.u_ofile[n]; 10228099Sroot if (fp == NULL) 10238099Sroot continue; 10248099Sroot fp->f_count++; 10259591Ssam if (u.u_pofile[n]&UF_SHLOCK) 10269159Ssam fp->f_inode->i_shlockc++; 10279591Ssam if (u.u_pofile[n]&UF_EXLOCK) 10289159Ssam fp->f_inode->i_exlockc++; 10298099Sroot } 10308099Sroot u.u_cdir->i_count++; 10318099Sroot if (u.u_rdir) 10328099Sroot u.u_rdir->i_count++; 10338099Sroot 10348099Sroot /* 10358099Sroot * Partially simulate the environment 10368099Sroot * of the new process so that when it is actually 10378099Sroot * created (by copying) it will look right. 10388099Sroot * This begins the section where we must prevent the parent 10398099Sroot * from being swapped. 10408099Sroot */ 10418099Sroot rip->p_flag |= SKEEP; 10428099Sroot if (procdup(rpp, isvfork)) 10438099Sroot return (1); 10448099Sroot 10458099Sroot /* 10468099Sroot * Make child runnable and add to run queue. 10478099Sroot */ 10488099Sroot (void) spl6(); 10498099Sroot rpp->p_stat = SRUN; 10508099Sroot setrq(rpp); 10518099Sroot (void) spl0(); 10528099Sroot 10538099Sroot /* 10548099Sroot * Cause child to take a non-local goto as soon as it runs. 10558099Sroot * On older systems this was done with SSWAP bit in proc 10568099Sroot * table; on VAX we use u.u_pcb.pcb_sswap so don't need 10578099Sroot * to do rpp->p_flag |= SSWAP. Actually do nothing here. 10588099Sroot */ 10598099Sroot /* rpp->p_flag |= SSWAP; */ 10608099Sroot 10618099Sroot /* 10628099Sroot * Now can be swapped. 10638099Sroot */ 10648099Sroot rip->p_flag &= ~SKEEP; 10658099Sroot 10668099Sroot /* 10678099Sroot * If vfork make chain from parent process to child 10688099Sroot * (where virtal memory is temporarily). Wait for 10698099Sroot * child to finish, steal virtual memory back, 10708099Sroot * and wakeup child to let it die. 10718099Sroot */ 10728099Sroot if (isvfork) { 10738099Sroot u.u_procp->p_xlink = rpp; 10748099Sroot u.u_procp->p_flag |= SNOVM; 10758099Sroot while (rpp->p_flag & SVFORK) 10768099Sroot sleep((caddr_t)rpp, PZERO - 1); 10778099Sroot if ((rpp->p_flag & SLOAD) == 0) 10788099Sroot panic("newproc vfork"); 10798099Sroot uaccess(rpp, Vfmap, &vfutl); 10808099Sroot u.u_procp->p_xlink = 0; 10818099Sroot vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 10828099Sroot u.u_procp->p_flag &= ~SNOVM; 10838099Sroot rpp->p_ndx = rpp - proc; 10848099Sroot rpp->p_flag |= SVFDONE; 10858099Sroot wakeup((caddr_t)rpp); 10868099Sroot } 10878099Sroot 10888099Sroot /* 10898099Sroot * 0 return means parent. 10908099Sroot */ 10918099Sroot return (0); 10928099Sroot } 1093