1*9866Ssam /* kern_proc.c 4.54 82/12/21 */ 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; 558099Sroot if (copyout((caddr_t)hostname, (caddr_t)uap->hostname, len)) 568099Sroot u.u_error = EFAULT; 578099Sroot } 588099Sroot 598099Sroot sethostname() 608099Sroot { 618099Sroot register struct a { 628099Sroot char *hostname; 638099Sroot u_int len; 648099Sroot } *uap = (struct a *)u.u_ap; 658099Sroot 668099Sroot if (!suser()) 678099Sroot return; 688099Sroot if (uap->len > sizeof (hostname) - 1) { 698099Sroot u.u_error = EINVAL; 708099Sroot return; 718099Sroot } 728099Sroot hostnamelen = uap->len; 738099Sroot if (copyin((caddr_t)uap->hostname, hostname, uap->len)) 748099Sroot u.u_error = EFAULT; 758099Sroot hostname[hostnamelen] = 0; 768099Sroot } 778099Sroot 7836Sbill /* 7936Sbill * exec system call, with and without environments. 8036Sbill */ 8136Sbill struct execa { 8236Sbill char *fname; 8336Sbill char **argp; 8436Sbill char **envp; 8536Sbill }; 8636Sbill 878030Sroot execv() 8836Sbill { 8936Sbill ((struct execa *)u.u_ap)->envp = NULL; 908030Sroot execve(); 9136Sbill } 9236Sbill 938030Sroot execve() 9436Sbill { 9536Sbill register nc; 9636Sbill register char *cp; 9736Sbill register struct buf *bp; 9836Sbill register struct execa *uap; 9936Sbill int na, ne, ucp, ap, c; 1002301Skre int indir, uid, gid; 1012301Skre char *sharg; 10236Sbill struct inode *ip; 10336Sbill swblk_t bno; 1046568Smckusic char cfname[MAXNAMLEN + 1]; 1052301Skre char cfarg[SHSIZE]; 1067748Sroot int resid; 10736Sbill 1089159Ssam if ((ip = namei(uchar, LOOKUP, 1)) == NULL) 10936Sbill return; 11036Sbill bno = 0; 11136Sbill bp = 0; 1122301Skre indir = 0; 1132301Skre uid = u.u_uid; 1142301Skre gid = u.u_gid; 1152301Skre if (ip->i_mode & ISUID) 1162301Skre uid = ip->i_uid; 1172301Skre if (ip->i_mode & ISGID) 1182301Skre gid = ip->i_gid; 1192301Skre 1202301Skre again: 1214827Swnj if (access(ip, IEXEC)) 12236Sbill goto bad; 1234827Swnj if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) 1242330Swnj goto bad; 1254827Swnj if ((ip->i_mode & IFMT) != IFREG || 12636Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 12736Sbill u.u_error = EACCES; 12836Sbill goto bad; 12936Sbill } 1302301Skre 13136Sbill /* 1322301Skre * Read in first few bytes of file for segment sizes, ux_mag: 1332301Skre * 407 = plain executable 1342301Skre * 410 = RO text 1352301Skre * 413 = demand paged RO text 1362301Skre * Also an ASCII line beginning with #! is 1372301Skre * the file name of a ``shell'' and arguments may be prepended 1382301Skre * to the argument list if given here. 1392301Skre * 1402301Skre * SHELL NAMES ARE LIMITED IN LENGTH. 1412301Skre * 1422301Skre * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 1432301Skre * THE ASCII LINE. 1442301Skre */ 1459753Ssam u.u_exdata.ux_shell[0] = 0; /* for zero length files */ 1467816Sroot u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata), 1477748Sroot 0, 1, &resid); 1484827Swnj if (u.u_error) 1492301Skre goto bad; 1507748Sroot u.u_count = resid; 1517816Sroot #ifndef lint 1524982Swnj if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && 1534982Swnj u.u_exdata.ux_shell[0] != '#') { 1542301Skre u.u_error = ENOEXEC; 1552301Skre goto bad; 1562301Skre } 1577816Sroot #endif 1582301Skre switch (u.u_exdata.ux_mag) { 1592301Skre 1602301Skre case 0407: 1612301Skre u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 1622301Skre u.u_exdata.ux_tsize = 0; 1632301Skre break; 1642301Skre 1652301Skre case 0413: 1662301Skre case 0410: 1672301Skre if (u.u_exdata.ux_tsize == 0) { 1682301Skre u.u_error = ENOEXEC; 1692301Skre goto bad; 1702301Skre } 1712301Skre break; 1722301Skre 1732301Skre default: 1742301Skre if (u.u_exdata.ux_shell[0] != '#' || 1752301Skre u.u_exdata.ux_shell[1] != '!' || 1762301Skre indir) { 1772301Skre u.u_error = ENOEXEC; 1782301Skre goto bad; 1792301Skre } 1802301Skre cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 1812301Skre while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 1822301Skre if (*cp == '\t') 1832301Skre *cp = ' '; 1842301Skre else if (*cp == '\n') { 1852301Skre *cp = '\0'; 1862301Skre break; 1872301Skre } 1882301Skre cp++; 1892301Skre } 1902301Skre if (*cp != '\0') { 1912301Skre u.u_error = ENOEXEC; 1922301Skre goto bad; 1932301Skre } 1942301Skre cp = &u.u_exdata.ux_shell[2]; 1952301Skre while (*cp == ' ') 1962301Skre cp++; 1972301Skre u.u_dirp = cp; 1982301Skre while (*cp && *cp != ' ') 1992301Skre cp++; 2002301Skre sharg = NULL; 2012301Skre if (*cp) { 2022301Skre *cp++ = '\0'; 2032301Skre while (*cp == ' ') 2042301Skre cp++; 2052301Skre if (*cp) { 2062301Skre bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 2072301Skre sharg = cfarg; 2082301Skre } 2092301Skre } 2106568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, 2117816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2122301Skre indir = 1; 2132301Skre iput(ip); 2149159Ssam ip = namei(schar, LOOKUP, 1); 2152301Skre if (ip == NULL) 2162301Skre return; 2172301Skre goto again; 2182301Skre } 2192301Skre 2202301Skre /* 22136Sbill * Collect arguments on "file" in swap space. 22236Sbill */ 22336Sbill na = 0; 22436Sbill ne = 0; 22536Sbill nc = 0; 22636Sbill uap = (struct execa *)u.u_ap; 2278665S if ((bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))))) == 0) { 22836Sbill swkill(u.u_procp, "exece"); 22936Sbill goto bad; 23036Sbill } 23136Sbill if (bno % CLSIZE) 2322780Swnj panic("execa rmalloc"); 23336Sbill if (uap->argp) for (;;) { 23436Sbill ap = NULL; 2353621Sroot if (indir && (na == 1 || na == 2 && sharg)) 2362301Skre ap = (int)uap->fname; 2372301Skre else if (uap->argp) { 23836Sbill ap = fuword((caddr_t)uap->argp); 23936Sbill uap->argp++; 24036Sbill } 24136Sbill if (ap==NULL && uap->envp) { 24236Sbill uap->argp = NULL; 24336Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 24436Sbill break; 24536Sbill uap->envp++; 24636Sbill ne++; 24736Sbill } 2486568Smckusic if (ap == NULL) 24936Sbill break; 25036Sbill na++; 2514827Swnj if (ap == -1) 25236Sbill u.u_error = EFAULT; 25336Sbill do { 25436Sbill if (nc >= NCARGS-1) 25536Sbill u.u_error = E2BIG; 2562301Skre if (indir && na == 2 && sharg != NULL) 2572301Skre c = *sharg++ & 0377; 2582301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 25936Sbill u.u_error = EFAULT; 26083Sbill if (u.u_error) { 26183Sbill if (bp) 26283Sbill brelse(bp); 26383Sbill bp = 0; 26436Sbill goto badarg; 26583Sbill } 2666568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 26736Sbill if (bp) 26836Sbill bdwrite(bp); 2698968Sroot bp = getblk(argdev, bno + ctod(nc / NBPG), 2706568Smckusic CLSIZE*NBPG); 27136Sbill cp = bp->b_un.b_addr; 27236Sbill } 27336Sbill nc++; 27436Sbill *cp++ = c; 2756568Smckusic } while (c > 0); 27636Sbill } 27736Sbill if (bp) 27836Sbill bdwrite(bp); 27936Sbill bp = 0; 28036Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 2816568Smckusic if (indir) { 2826568Smckusic u.u_dent.d_namlen = strlen(cfname); 2836568Smckusic bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, 2847816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2856568Smckusic } 2862301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 287912Sbill if (u.u_error) { 28836Sbill badarg: 2899006Sroot for (c = 0; c < nc; c += CLSIZE*NBPG) { 2909006Sroot bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG); 2918968Sroot if (bp) { 29236Sbill bp->b_flags |= B_AGE; /* throw away */ 29336Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 29436Sbill brelse(bp); 29536Sbill bp = 0; 29636Sbill } 2979006Sroot } 29836Sbill goto bad; 29936Sbill } 30036Sbill 30136Sbill /* 30236Sbill * copy back arglist 30336Sbill */ 30436Sbill ucp = USRSTACK - nc - NBPW; 30536Sbill ap = ucp - na*NBPW - 3*NBPW; 30636Sbill u.u_ar0[SP] = ap; 307132Sbill (void) suword((caddr_t)ap, na-ne); 30836Sbill nc = 0; 30936Sbill for (;;) { 31036Sbill ap += NBPW; 31136Sbill if (na==ne) { 312132Sbill (void) suword((caddr_t)ap, 0); 31336Sbill ap += NBPW; 31436Sbill } 31536Sbill if (--na < 0) 31636Sbill break; 317132Sbill (void) suword((caddr_t)ap, ucp); 31836Sbill do { 3196568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 32036Sbill if (bp) 32136Sbill brelse(bp); 322*9866Ssam bp = bread(argdev, bno + ctod(nc / NBPG), 3236568Smckusic CLSIZE*NBPG); 32436Sbill bp->b_flags |= B_AGE; /* throw away */ 32536Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 32636Sbill cp = bp->b_un.b_addr; 32736Sbill } 328132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 32936Sbill nc++; 33036Sbill } while(c&0377); 33136Sbill } 332132Sbill (void) suword((caddr_t)ap, 0); 333132Sbill (void) suword((caddr_t)ucp, 0); 33436Sbill setregs(); 33536Sbill bad: 33636Sbill if (bp) 33736Sbill brelse(bp); 33836Sbill if (bno) 3398816Sroot rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); 34036Sbill iput(ip); 34136Sbill } 34236Sbill 34336Sbill /* 34436Sbill * Read in and set up memory for executed file. 34536Sbill */ 3462301Skre getxfile(ip, nargc, uid, gid) 34736Sbill register struct inode *ip; 34836Sbill { 34936Sbill register size_t ts, ds, ss; 3502301Skre int pagi; 35136Sbill 3522301Skre if (u.u_exdata.ux_mag == 0413) 35336Sbill pagi = SPAGI; 3542301Skre else 3552301Skre pagi = 0; 3564827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 3574827Swnj ip->i_count!=1) { 358890Sbill register struct file *fp; 359890Sbill 3604827Swnj for (fp = file; fp < fileNFILE; fp++) { 3617497Sroot if (fp->f_type == DTYPE_FILE && 3629743Ssam fp->f_count > 0 && 3637497Sroot fp->f_inode == ip && (fp->f_flag&FWRITE)) { 364890Sbill u.u_error = ETXTBSY; 365890Sbill goto bad; 366890Sbill } 3674827Swnj } 36836Sbill } 36936Sbill 37036Sbill /* 3714827Swnj * Compute text and data sizes and make sure not too large. 37236Sbill */ 37336Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 37436Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 37536Sbill ss = clrnd(SSIZE + btoc(nargc)); 376912Sbill if (chksize(ts, ds, ss)) 377912Sbill goto bad; 3784827Swnj 3794827Swnj /* 3804827Swnj * Make sure enough space to start process. 3814827Swnj */ 382912Sbill u.u_cdmap = zdmap; 383912Sbill u.u_csmap = zdmap; 384912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 385912Sbill goto bad; 38636Sbill 387912Sbill /* 388912Sbill * At this point, committed to the new image! 389912Sbill * Release virtual memory resources of old process, and 390912Sbill * initialize the virtual memory of the new process. 391912Sbill * If we resulted from vfork(), instead wakeup our 392912Sbill * parent who will set SVFDONE when he has taken back 393912Sbill * our resources. 394912Sbill */ 395912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 396912Sbill vrelvm(); 397912Sbill else { 398912Sbill u.u_procp->p_flag &= ~SVFORK; 399912Sbill u.u_procp->p_flag |= SKEEP; 400912Sbill wakeup((caddr_t)u.u_procp); 401912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 402912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 403912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 404912Sbill } 4053592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 406912Sbill u.u_procp->p_flag |= pagi; 407912Sbill u.u_dmap = u.u_cdmap; 408912Sbill u.u_smap = u.u_csmap; 409912Sbill vgetvm(ts, ds, ss); 410912Sbill 4117748Sroot if (pagi == 0) 4127816Sroot u.u_error = 4137816Sroot rdwri(UIO_READ, ip, 4148968Sroot (char *)ctob(dptov(u.u_procp, 0)), 4158968Sroot (int)u.u_exdata.ux_dsize, 4167816Sroot (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), 4177816Sroot 0, (int *)0); 418912Sbill xalloc(ip, pagi); 419912Sbill if (pagi && u.u_procp->p_textp) 420912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 421912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 4228665S (long)(1 + ts/CLSIZE), (int)btoc(u.u_exdata.ux_dsize)); 42336Sbill 4248968Sroot #ifdef vax 425912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 4268443Sroot #include "../vax/mtpr.h" /* XXX */ 427912Sbill mtpr(TBIA, 0); 4288968Sroot #endif 42936Sbill 4307530Sroot if (u.u_error) 4317530Sroot swkill(u.u_procp, "i/o error mapping pages"); 432912Sbill /* 433912Sbill * set SUID/SGID protections, if no tracing 434912Sbill */ 435912Sbill if ((u.u_procp->p_flag&STRC)==0) { 4364827Swnj u.u_uid = uid; 4374827Swnj u.u_procp->p_uid = uid; 4382301Skre u.u_gid = gid; 4398665S (void) entergroup(gid); 440912Sbill } else 441912Sbill psignal(u.u_procp, SIGTRAP); 44236Sbill u.u_tsize = ts; 44336Sbill u.u_dsize = ds; 44436Sbill u.u_ssize = ss; 44536Sbill bad: 446912Sbill return; 44736Sbill } 44836Sbill 44936Sbill /* 45036Sbill * Clear registers on exec 45136Sbill */ 45236Sbill setregs() 45336Sbill { 454173Sbill register int (**rp)(); 45536Sbill register i; 456188Sbill long sigmask; 45736Sbill 4586464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 459188Sbill sigmask <<= 1, rp++) { 460188Sbill switch (*rp) { 461188Sbill 462188Sbill case SIG_IGN: 463188Sbill case SIG_DFL: 464188Sbill case SIG_HOLD: 465188Sbill continue; 466188Sbill 467188Sbill default: 468188Sbill /* 469206Sbill * Normal or deferring catch; revert to default. 470188Sbill */ 471206Sbill (void) spl6(); 472206Sbill *rp = SIG_DFL; 473188Sbill if ((int)*rp & 1) 474188Sbill u.u_procp->p_siga0 |= sigmask; 475188Sbill else 4766327Swnj u.u_procp->p_siga0 &= ~sigmask; 477188Sbill if ((int)*rp & 2) 478188Sbill u.u_procp->p_siga1 |= sigmask; 479188Sbill else 480188Sbill u.u_procp->p_siga1 &= ~sigmask; 481206Sbill (void) spl0(); 482188Sbill continue; 483188Sbill } 484188Sbill } 4858968Sroot #ifdef vax 48636Sbill /* 4874827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 48836Sbill *rp++ = 0; 48936Sbill */ 4908968Sroot u.u_ar0[PC] = u.u_exdata.ux_entloc+2; 4918968Sroot #endif 4928968Sroot #ifdef sun 4938968Sroot { register struct regs *r = (struct regs *)u.u_ar0; 4948968Sroot for (i = 0; i < 8; i++) { 4958968Sroot r->r_dreg[i] = 0; 4968968Sroot if (&r->r_areg[i] != &r->r_sp) 4978968Sroot r->r_areg[i] = 0; 4988968Sroot } 4998968Sroot r->r_sr = PSL_USERSET; 5008968Sroot r->r_pc = u.u_exdata.ux_entloc; 5018968Sroot } 5028968Sroot #endif 5034827Swnj for (i=0; i<NOFILE; i++) { 5049591Ssam if (u.u_pofile[i]&UF_EXCLOSE) { 5057697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 50636Sbill u.u_ofile[i] = NULL; 5077697Ssam u.u_pofile[i] = 0; 50836Sbill } 5098968Sroot u.u_pofile[i] &= ~UF_MAPPED; 51036Sbill } 5114827Swnj 51236Sbill /* 51336Sbill * Remember file name for accounting. 51436Sbill */ 51536Sbill u.u_acflag &= ~AFORK; 5166568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm, 5177816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 5188968Sroot #ifdef sun 5198968Sroot u.u_eosys = REALLYRETURN; 5208968Sroot #endif 52136Sbill } 52236Sbill 52336Sbill /* 5244827Swnj * Exit system call: pass back caller's arg 52536Sbill */ 52636Sbill rexit() 52736Sbill { 52836Sbill register struct a { 52936Sbill int rval; 53036Sbill } *uap; 53136Sbill 53236Sbill uap = (struct a *)u.u_ap; 53336Sbill exit((uap->rval & 0377) << 8); 53436Sbill } 53536Sbill 53636Sbill /* 53736Sbill * Release resources. 53836Sbill * Save u. area for parent to look at. 53936Sbill * Enter zombie state. 54036Sbill * Wake up parent and init processes, 54136Sbill * and dispose of children. 54236Sbill */ 54336Sbill exit(rv) 54436Sbill { 54536Sbill register int i; 54636Sbill register struct proc *p, *q; 54736Sbill register int x; 5489632Ssam struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE); 54936Sbill 55036Sbill #ifdef PGINPROF 55136Sbill vmsizmon(); 55236Sbill #endif 55336Sbill p = u.u_procp; 55436Sbill p->p_flag &= ~(STRC|SULOCK); 55536Sbill p->p_flag |= SWEXIT; 556188Sbill (void) spl6(); 557188Sbill if ((int)SIG_IGN & 1) 558188Sbill p->p_siga0 = ~0; 559188Sbill else 560188Sbill p->p_siga0 = 0; 561188Sbill if ((int)SIG_IGN & 2) 562188Sbill p->p_siga1 = ~0; 563188Sbill else 564206Sbill p->p_siga1 = 0; 565188Sbill (void) spl0(); 5661399Sbill p->p_cpticks = 0; 5671399Sbill p->p_pctcpu = 0; 5684827Swnj for (i=0; i<NSIG; i++) 569173Sbill u.u_signal[i] = SIG_IGN; 5708623Sroot untimeout(realitexpire, (caddr_t)p); 57136Sbill /* 57236Sbill * Release virtual memory. If we resulted from 57336Sbill * a vfork(), instead give the resources back to 57436Sbill * the parent. 57536Sbill */ 57636Sbill if ((p->p_flag & SVFORK) == 0) 57736Sbill vrelvm(); 57836Sbill else { 57936Sbill p->p_flag &= ~SVFORK; 58036Sbill wakeup((caddr_t)p); 58136Sbill while ((p->p_flag & SVFDONE) == 0) 58236Sbill sleep((caddr_t)p, PZERO - 1); 58336Sbill p->p_flag &= ~SVFDONE; 58436Sbill } 5857697Ssam for (i = 0; i < NOFILE; i++) { 5869558Ssam struct file *f; 5879558Ssam int p; 5889558Ssam 58936Sbill f = u.u_ofile[i]; 59036Sbill u.u_ofile[i] = NULL; 5919558Ssam p = u.u_pofile[i]; 5927697Ssam u.u_pofile[i] = 0; 5939558Ssam closef(f, 1, p); 59436Sbill } 5954827Swnj ilock(u.u_cdir); 59636Sbill iput(u.u_cdir); 59736Sbill if (u.u_rdir) { 5984827Swnj ilock(u.u_rdir); 59936Sbill iput(u.u_rdir); 60036Sbill } 6018030Sroot u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 60236Sbill acct(); 6037488Skre #ifdef QUOTA 6047488Skre qclean(); 6057488Skre #endif 6068968Sroot #ifdef sun 6078968Sroot ctxfree(&u); 6088968Sroot #endif 60936Sbill vrelpt(u.u_procp); 61036Sbill vrelu(u.u_procp, 0); 6115630Swnj (void) spl5(); /* hack for mem alloc race XXX */ 61236Sbill multprog--; 613931Sbill p->p_stat = SZOMB; 614307Sbill noproc = 1; 61536Sbill i = PIDHASH(p->p_pid); 61636Sbill x = p - proc; 61736Sbill if (pidhash[i] == x) 61836Sbill pidhash[i] = p->p_idhash; 61936Sbill else { 62036Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 62136Sbill if (proc[i].p_idhash == x) { 62236Sbill proc[i].p_idhash = p->p_idhash; 62336Sbill goto done; 62436Sbill } 62536Sbill panic("exit"); 62636Sbill } 6271409Sbill if (p->p_pid == 1) 6281409Sbill panic("init died"); 62936Sbill done: 6308030Sroot p->p_xstat = rv; 6319558Ssam if (m == 0) 6329558Ssam panic("exit: m_getclr"); 6338827Sroot p->p_ru = mtod(m, struct rusage *); 6348030Sroot *p->p_ru = u.u_ru; 6358030Sroot ruadd(p->p_ru, &u.u_cru); 6364827Swnj for (q = proc; q < procNPROC; q++) 6374827Swnj if (q->p_pptr == p) { 6387488Skre if (q->p_osptr) 6397488Skre q->p_osptr->p_ysptr = q->p_ysptr; 6407488Skre if (q->p_ysptr) 6417488Skre q->p_ysptr->p_osptr = q->p_osptr; 6427488Skre if (proc[1].p_cptr) 6437488Skre proc[1].p_cptr->p_ysptr = q; 6447488Skre q->p_osptr = proc[1].p_cptr; 6457488Skre q->p_ysptr = NULL; 6467488Skre proc[1].p_cptr = q; 6477488Skre 648188Sbill q->p_pptr = &proc[1]; 649188Sbill q->p_ppid = 1; 65036Sbill wakeup((caddr_t)&proc[1]); 651188Sbill /* 652212Sbill * Traced processes are killed 653188Sbill * since their existence means someone is screwing up. 654354Sbill * Stopped processes are sent a hangup and a continue. 655212Sbill * This is designed to be ``safe'' for setuid 656212Sbill * processes since they must be willing to tolerate 657212Sbill * hangups anyways. 658188Sbill */ 659212Sbill if (q->p_flag&STRC) { 660188Sbill q->p_flag &= ~STRC; 661188Sbill psignal(q, SIGKILL); 662212Sbill } else if (q->p_stat == SSTOP) { 663212Sbill psignal(q, SIGHUP); 664212Sbill psignal(q, SIGCONT); 665188Sbill } 666215Sbill /* 667215Sbill * Protect this process from future 6685619Swnj * tty signals, clear TSTP/TTIN/TTOU if pending. 669215Sbill */ 6701788Sbill (void) spgrp(q, -1); 67136Sbill } 6726464Swnj psignal(p->p_pptr, SIGCHLD); 673188Sbill wakeup((caddr_t)p->p_pptr); 67436Sbill swtch(); 67536Sbill } 67636Sbill 6779753Ssam #include "../h/vtimes.h" 6788151Sroot 6798099Sroot owait() 68036Sbill { 6818151Sroot struct rusage ru; 6828151Sroot struct vtimes *vtp, avt; 68336Sbill 684188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 6858030Sroot wait1(0, (struct rusage *)0); 686188Sbill return; 687188Sbill } 6888151Sroot vtp = (struct vtimes *)u.u_ar0[R1]; 6898030Sroot wait1(u.u_ar0[R0], &ru); 690188Sbill if (u.u_error) 691188Sbill return; 6928151Sroot getvtimes(&ru, &avt); 6938151Sroot (void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes)); 69436Sbill } 69536Sbill 69636Sbill /* 69736Sbill * Wait system call. 69836Sbill * Search for a terminated (zombie) child, 69936Sbill * finally lay it to rest, and collect its status. 70036Sbill * Look also for stopped (traced) children, 70136Sbill * and pass back status from them. 70236Sbill */ 7038030Sroot wait1(options, ru) 7048030Sroot register int options; 7058030Sroot struct rusage *ru; 70636Sbill { 70736Sbill register f; 7087488Skre register struct proc *p, *q; 70936Sbill 71036Sbill f = 0; 71136Sbill loop: 7124827Swnj for (p = proc; p < procNPROC; p++) 7134827Swnj if (p->p_pptr == u.u_procp) { 71436Sbill f++; 7154827Swnj if (p->p_stat == SZOMB) { 71636Sbill u.u_r.r_val1 = p->p_pid; 7178030Sroot u.u_r.r_val2 = p->p_xstat; 7188030Sroot p->p_xstat = 0; 7198030Sroot if (ru) 7208030Sroot *ru = *p->p_ru; 7218030Sroot ruadd(&u.u_cru, p->p_ru); 7228665S (void) m_free(dtom(p->p_ru)); 7238030Sroot p->p_ru = 0; 72436Sbill p->p_stat = NULL; 72536Sbill p->p_pid = 0; 72636Sbill p->p_ppid = 0; 7277488Skre if (q = p->p_ysptr) 7287488Skre q->p_osptr = p->p_osptr; 7297488Skre if (q = p->p_osptr) 7307488Skre q->p_ysptr = p->p_ysptr; 7317488Skre if ((q = p->p_pptr)->p_cptr == p) 7327488Skre q->p_cptr = p->p_osptr; 733188Sbill p->p_pptr = 0; 7347488Skre p->p_ysptr = 0; 7357488Skre p->p_osptr = 0; 7367488Skre p->p_cptr = 0; 73736Sbill p->p_sig = 0; 738188Sbill p->p_siga0 = 0; 739188Sbill p->p_siga1 = 0; 74036Sbill p->p_pgrp = 0; 74136Sbill p->p_flag = 0; 74236Sbill p->p_wchan = 0; 743188Sbill p->p_cursig = 0; 74436Sbill return; 74536Sbill } 746188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 747188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 748188Sbill p->p_flag |= SWTED; 749188Sbill u.u_r.r_val1 = p->p_pid; 750188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 751188Sbill return; 75236Sbill } 75336Sbill } 754188Sbill if (f==0) { 755188Sbill u.u_error = ECHILD; 756188Sbill return; 75736Sbill } 758188Sbill if (options&WNOHANG) { 759188Sbill u.u_r.r_val1 = 0; 760188Sbill return; 761188Sbill } 7628116Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 763188Sbill u.u_eosys = RESTARTSYS; 764188Sbill return; 765188Sbill } 766188Sbill sleep((caddr_t)u.u_procp, PWAIT); 767188Sbill goto loop; 76836Sbill } 76936Sbill 77036Sbill /* 77136Sbill * fork system call. 77236Sbill */ 77336Sbill fork() 77436Sbill { 77536Sbill 77636Sbill u.u_cdmap = zdmap; 77736Sbill u.u_csmap = zdmap; 77836Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 77936Sbill u.u_r.r_val2 = 0; 78036Sbill return; 78136Sbill } 78236Sbill fork1(0); 78336Sbill } 78436Sbill 78536Sbill fork1(isvfork) 78636Sbill { 78736Sbill register struct proc *p1, *p2; 7887488Skre #ifndef QUOTA 78936Sbill register a; 79036Sbill 79136Sbill a = 0; 7927488Skre #else 7937488Skre if (u.u_quota != NOQUOT && u.u_quota->q_plim && 7947488Skre u.u_quota->q_cnt >= u.u_quota->q_plim) { 7957488Skre u.u_error = EPROCLIM; 7967488Skre return; 7977488Skre } 7987488Skre #endif 79936Sbill p2 = NULL; 8004827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 8017488Skre #ifdef QUOTA 8027488Skre if (p1->p_stat == NULL) { 8037488Skre p2 = p1; 8047488Skre break; 8057488Skre } 8067488Skre #else 80736Sbill if (p1->p_stat==NULL && p2==NULL) 80836Sbill p2 = p1; 80936Sbill else { 81036Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 81136Sbill a++; 81236Sbill } 8137488Skre #endif 81436Sbill } 81536Sbill /* 81636Sbill * Disallow if 81736Sbill * No processes at all; 81836Sbill * not su and too many procs owned; or 81936Sbill * not su and would take last slot. 82036Sbill */ 8212938Swnj if (p2==NULL) 8222938Swnj tablefull("proc"); 8237488Skre #ifdef QUOTA 8247488Skre if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { 8257488Skre #else 8262741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 8277488Skre #endif 82836Sbill u.u_error = EAGAIN; 82936Sbill if (!isvfork) { 830132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 831132Sbill (void) vsexpand(0, &u.u_csmap, 1); 83236Sbill } 83336Sbill goto out; 83436Sbill } 83536Sbill p1 = u.u_procp; 8364827Swnj if (newproc(isvfork)) { 83736Sbill u.u_r.r_val1 = p1->p_pid; 83836Sbill u.u_r.r_val2 = 1; /* child */ 8398030Sroot u.u_start = time.tv_sec; 84036Sbill u.u_acflag = AFORK; 8417488Skre #ifdef QUOTA 8427488Skre u.u_qflags &= ~QUF_LOGIN; 8437488Skre #endif 84436Sbill return; 84536Sbill } 84636Sbill u.u_r.r_val1 = p2->p_pid; 84736Sbill 84836Sbill out: 84936Sbill u.u_r.r_val2 = 0; 85036Sbill } 85136Sbill 8527497Sroot spgrp(top, npgrp) 8537497Sroot register struct proc *top; 8547497Sroot { 8557497Sroot register struct proc *pp, *p; 8567497Sroot int f = 0; 8577497Sroot 8587497Sroot for (p = top; npgrp == -1 || u.u_uid == p->p_uid || 8597497Sroot !u.u_uid || inferior(p); p = pp) { 8607497Sroot if (npgrp == -1) { 8617497Sroot #define bit(a) (1<<(a-1)) 8627497Sroot p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 8637497Sroot } else 8647497Sroot p->p_pgrp = npgrp; 8657497Sroot f++; 8667497Sroot /* 8677497Sroot * Search for children. 8687497Sroot */ 8697497Sroot for (pp = proc; pp < procNPROC; pp++) 8707497Sroot if (pp->p_pptr == p) 8717497Sroot goto cont; 8727497Sroot /* 8737497Sroot * Search for siblings. 8747497Sroot */ 8757497Sroot for (; p != top; p = p->p_pptr) 8767497Sroot for (pp = p + 1; pp < procNPROC; pp++) 8777497Sroot if (pp->p_pptr == p->p_pptr) 8787497Sroot goto cont; 8797497Sroot break; 8807497Sroot cont: 8817497Sroot ; 8827497Sroot } 8837497Sroot return (f); 8847497Sroot } 8857497Sroot 88636Sbill /* 8877497Sroot * Is p an inferior of the current process? 88836Sbill */ 8897497Sroot inferior(p) 8907816Sroot register struct proc *p; 89136Sbill { 89236Sbill 8937497Sroot for (; p != u.u_procp; p = p->p_pptr) 8947497Sroot if (p->p_ppid == 0) 8957497Sroot return (0); 8967497Sroot return (1); 89736Sbill } 8987816Sroot 8997816Sroot struct proc * 9007816Sroot pfind(pid) 9017816Sroot int pid; 9027816Sroot { 9037816Sroot register struct proc *p; 9047816Sroot 9057816Sroot for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 9067816Sroot if (p->p_pid == pid) 9077816Sroot return (p); 9087816Sroot return ((struct proc *)0); 9097816Sroot } 9108099Sroot 9118099Sroot /* 9128099Sroot * Create a new process-- the internal version of 9138099Sroot * sys fork. 9148099Sroot * It returns 1 in the new process, 0 in the old. 9158099Sroot */ 9168099Sroot newproc(isvfork) 9178099Sroot int isvfork; 9188099Sroot { 9198099Sroot register struct proc *p; 9208099Sroot register struct proc *rpp, *rip; 9218099Sroot register int n; 9228099Sroot register struct file *fp; 9238099Sroot 9248099Sroot p = NULL; 9258099Sroot /* 9268099Sroot * First, just locate a slot for a process 9278099Sroot * and copy the useful info from this process into it. 9288099Sroot * The panic "cannot happen" because fork has already 9298099Sroot * checked for the existence of a slot. 9308099Sroot */ 9318099Sroot retry: 9328099Sroot mpid++; 9338099Sroot if (mpid >= 30000) { 9348099Sroot mpid = 0; 9358099Sroot goto retry; 9368099Sroot } 9378099Sroot for (rpp = proc; rpp < procNPROC; rpp++) { 9388099Sroot if (rpp->p_stat == NULL && p==NULL) 9398099Sroot p = rpp; 9408099Sroot if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) 9418099Sroot goto retry; 9428099Sroot } 9438099Sroot if ((rpp = p) == NULL) 9448099Sroot panic("no procs"); 9458099Sroot 9468099Sroot /* 9478099Sroot * Make a proc table entry for the new process. 9488099Sroot */ 9498099Sroot rip = u.u_procp; 9508099Sroot #ifdef QUOTA 9518099Sroot (rpp->p_quota = rip->p_quota)->q_cnt++; 9528099Sroot #endif 9538099Sroot rpp->p_stat = SIDL; 9548099Sroot timerclear(&rpp->p_realtimer.it_value); 9558099Sroot rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG)); 9568099Sroot if (isvfork) { 9578099Sroot rpp->p_flag |= SVFORK; 9588099Sroot rpp->p_ndx = rip->p_ndx; 9598099Sroot } else 9608099Sroot rpp->p_ndx = rpp - proc; 9618099Sroot rpp->p_uid = rip->p_uid; 9628099Sroot rpp->p_pgrp = rip->p_pgrp; 9638099Sroot rpp->p_nice = rip->p_nice; 9648099Sroot rpp->p_textp = isvfork ? 0 : rip->p_textp; 9658099Sroot rpp->p_pid = mpid; 9668099Sroot rpp->p_ppid = rip->p_pid; 9678099Sroot rpp->p_pptr = rip; 9688099Sroot rpp->p_osptr = rip->p_cptr; 9698099Sroot if (rip->p_cptr) 9708099Sroot rip->p_cptr->p_ysptr = rpp; 9718099Sroot rpp->p_ysptr = NULL; 9728099Sroot rpp->p_cptr = NULL; 9738099Sroot rip->p_cptr = rpp; 9748099Sroot rpp->p_time = 0; 9758099Sroot rpp->p_cpu = 0; 9768099Sroot rpp->p_siga0 = rip->p_siga0; 9778099Sroot rpp->p_siga1 = rip->p_siga1; 9788099Sroot /* take along any pending signals, like stops? */ 9798099Sroot if (isvfork) { 9808099Sroot rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; 9818099Sroot rpp->p_szpt = clrnd(ctopt(UPAGES)); 9828099Sroot forkstat.cntvfork++; 9838099Sroot forkstat.sizvfork += rip->p_dsize + rip->p_ssize; 9848099Sroot } else { 9858099Sroot rpp->p_tsize = rip->p_tsize; 9868099Sroot rpp->p_dsize = rip->p_dsize; 9878099Sroot rpp->p_ssize = rip->p_ssize; 9888099Sroot rpp->p_szpt = rip->p_szpt; 9898099Sroot forkstat.cntfork++; 9908099Sroot forkstat.sizfork += rip->p_dsize + rip->p_ssize; 9918099Sroot } 9928099Sroot rpp->p_rssize = 0; 9938099Sroot rpp->p_maxrss = rip->p_maxrss; 9948099Sroot rpp->p_wchan = 0; 9958099Sroot rpp->p_slptime = 0; 9968099Sroot rpp->p_pctcpu = 0; 9978099Sroot rpp->p_cpticks = 0; 9988099Sroot n = PIDHASH(rpp->p_pid); 9998099Sroot p->p_idhash = pidhash[n]; 10008099Sroot pidhash[n] = rpp - proc; 10018099Sroot multprog++; 10028099Sroot 10038099Sroot /* 10048099Sroot * Increase reference counts on shared objects. 10058099Sroot */ 10068099Sroot for (n = 0; n < NOFILE; n++) { 10078099Sroot fp = u.u_ofile[n]; 10088099Sroot if (fp == NULL) 10098099Sroot continue; 10108099Sroot fp->f_count++; 10119591Ssam if (u.u_pofile[n]&UF_SHLOCK) 10129159Ssam fp->f_inode->i_shlockc++; 10139591Ssam if (u.u_pofile[n]&UF_EXLOCK) 10149159Ssam fp->f_inode->i_exlockc++; 10158099Sroot } 10168099Sroot u.u_cdir->i_count++; 10178099Sroot if (u.u_rdir) 10188099Sroot u.u_rdir->i_count++; 10198099Sroot 10208099Sroot /* 10218099Sroot * Partially simulate the environment 10228099Sroot * of the new process so that when it is actually 10238099Sroot * created (by copying) it will look right. 10248099Sroot * This begins the section where we must prevent the parent 10258099Sroot * from being swapped. 10268099Sroot */ 10278099Sroot rip->p_flag |= SKEEP; 10288099Sroot if (procdup(rpp, isvfork)) 10298099Sroot return (1); 10308099Sroot 10318099Sroot /* 10328099Sroot * Make child runnable and add to run queue. 10338099Sroot */ 10348099Sroot (void) spl6(); 10358099Sroot rpp->p_stat = SRUN; 10368099Sroot setrq(rpp); 10378099Sroot (void) spl0(); 10388099Sroot 10398099Sroot /* 10408099Sroot * Cause child to take a non-local goto as soon as it runs. 10418099Sroot * On older systems this was done with SSWAP bit in proc 10428099Sroot * table; on VAX we use u.u_pcb.pcb_sswap so don't need 10438099Sroot * to do rpp->p_flag |= SSWAP. Actually do nothing here. 10448099Sroot */ 10458099Sroot /* rpp->p_flag |= SSWAP; */ 10468099Sroot 10478099Sroot /* 10488099Sroot * Now can be swapped. 10498099Sroot */ 10508099Sroot rip->p_flag &= ~SKEEP; 10518099Sroot 10528099Sroot /* 10538099Sroot * If vfork make chain from parent process to child 10548099Sroot * (where virtal memory is temporarily). Wait for 10558099Sroot * child to finish, steal virtual memory back, 10568099Sroot * and wakeup child to let it die. 10578099Sroot */ 10588099Sroot if (isvfork) { 10598099Sroot u.u_procp->p_xlink = rpp; 10608099Sroot u.u_procp->p_flag |= SNOVM; 10618099Sroot while (rpp->p_flag & SVFORK) 10628099Sroot sleep((caddr_t)rpp, PZERO - 1); 10638099Sroot if ((rpp->p_flag & SLOAD) == 0) 10648099Sroot panic("newproc vfork"); 10658099Sroot uaccess(rpp, Vfmap, &vfutl); 10668099Sroot u.u_procp->p_xlink = 0; 10678099Sroot vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 10688099Sroot u.u_procp->p_flag &= ~SNOVM; 10698099Sroot rpp->p_ndx = rpp - proc; 10708099Sroot rpp->p_flag |= SVFDONE; 10718099Sroot wakeup((caddr_t)rpp); 10728099Sroot } 10738099Sroot 10748099Sroot /* 10758099Sroot * 0 return means parent. 10768099Sroot */ 10778099Sroot return (0); 10788099Sroot } 1079