1*9006Sroot /* kern_proc.c 4.47 82/11/02 */ 236Sbill 336Sbill #include "../h/param.h" 436Sbill #include "../h/systm.h" 536Sbill #include "../h/map.h" 636Sbill #include "../h/dir.h" 736Sbill #include "../h/user.h" 88030Sroot #include "../h/kernel.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" 158968Sroot #include <wait.h> 1636Sbill #include "../h/pte.h" 1736Sbill #include "../h/vm.h" 1836Sbill #include "../h/text.h" 19188Sbill #include "../h/psl.h" 20890Sbill #include "../h/file.h" 217488Skre #include "../h/quota.h" 227497Sroot #include "../h/descrip.h" 237713Sroot #include "../h/uio.h" 248030Sroot #include "../h/mbuf.h" 2536Sbill 268030Sroot gethostid() 278030Sroot { 288030Sroot 298099Sroot u.u_r.r_val1 = hostid; 308030Sroot } 318030Sroot 328030Sroot sethostid() 338030Sroot { 348099Sroot struct a { 358099Sroot int hostid; 368099Sroot } *uap = (struct a *)u.u_ap; 378030Sroot 388099Sroot if (suser()) 398099Sroot hostid = uap->hostid; 408030Sroot } 418030Sroot 428099Sroot gethostname() 438099Sroot { 448099Sroot register struct a { 458099Sroot char *hostname; 468099Sroot int len; 478099Sroot } *uap = (struct a *)u.u_ap; 488099Sroot register u_int len; 498099Sroot 508099Sroot len = uap->len; 518099Sroot if (len > hostnamelen) 528099Sroot len = hostnamelen; 538099Sroot if (copyout((caddr_t)hostname, (caddr_t)uap->hostname, len)) 548099Sroot u.u_error = EFAULT; 558099Sroot } 568099Sroot 578099Sroot sethostname() 588099Sroot { 598099Sroot register struct a { 608099Sroot char *hostname; 618099Sroot u_int len; 628099Sroot } *uap = (struct a *)u.u_ap; 638099Sroot 648099Sroot if (!suser()) 658099Sroot return; 668099Sroot if (uap->len > sizeof (hostname) - 1) { 678099Sroot u.u_error = EINVAL; 688099Sroot return; 698099Sroot } 708099Sroot hostnamelen = uap->len; 718099Sroot if (copyin((caddr_t)uap->hostname, hostname, uap->len)) 728099Sroot u.u_error = EFAULT; 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 1065991Swnj if ((ip = namei(uchar, 0, 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 */ 1437816Sroot u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata), 1447748Sroot 0, 1, &resid); 1454827Swnj if (u.u_error) 1462301Skre goto bad; 1477748Sroot u.u_count = resid; 1487816Sroot #ifndef lint 1494982Swnj if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && 1504982Swnj u.u_exdata.ux_shell[0] != '#') { 1512301Skre u.u_error = ENOEXEC; 1522301Skre goto bad; 1532301Skre } 1547816Sroot #endif 1552301Skre switch (u.u_exdata.ux_mag) { 1562301Skre 1572301Skre case 0407: 1582301Skre u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 1592301Skre u.u_exdata.ux_tsize = 0; 1602301Skre break; 1612301Skre 1622301Skre case 0413: 1632301Skre case 0410: 1642301Skre if (u.u_exdata.ux_tsize == 0) { 1652301Skre u.u_error = ENOEXEC; 1662301Skre goto bad; 1672301Skre } 1682301Skre break; 1692301Skre 1702301Skre default: 1712301Skre if (u.u_exdata.ux_shell[0] != '#' || 1722301Skre u.u_exdata.ux_shell[1] != '!' || 1732301Skre indir) { 1742301Skre u.u_error = ENOEXEC; 1752301Skre goto bad; 1762301Skre } 1772301Skre cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 1782301Skre while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 1792301Skre if (*cp == '\t') 1802301Skre *cp = ' '; 1812301Skre else if (*cp == '\n') { 1822301Skre *cp = '\0'; 1832301Skre break; 1842301Skre } 1852301Skre cp++; 1862301Skre } 1872301Skre if (*cp != '\0') { 1882301Skre u.u_error = ENOEXEC; 1892301Skre goto bad; 1902301Skre } 1912301Skre cp = &u.u_exdata.ux_shell[2]; 1922301Skre while (*cp == ' ') 1932301Skre cp++; 1942301Skre u.u_dirp = cp; 1952301Skre while (*cp && *cp != ' ') 1962301Skre cp++; 1972301Skre sharg = NULL; 1982301Skre if (*cp) { 1992301Skre *cp++ = '\0'; 2002301Skre while (*cp == ' ') 2012301Skre cp++; 2022301Skre if (*cp) { 2032301Skre bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 2042301Skre sharg = cfarg; 2052301Skre } 2062301Skre } 2076568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, 2087816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2092301Skre indir = 1; 2102301Skre iput(ip); 2115991Swnj ip = namei(schar, 0, 1); 2122301Skre if (ip == NULL) 2132301Skre return; 2142301Skre goto again; 2152301Skre } 2162301Skre 2172301Skre /* 21836Sbill * Collect arguments on "file" in swap space. 21936Sbill */ 22036Sbill na = 0; 22136Sbill ne = 0; 22236Sbill nc = 0; 22336Sbill uap = (struct execa *)u.u_ap; 2248665S if ((bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))))) == 0) { 22536Sbill swkill(u.u_procp, "exece"); 22636Sbill goto bad; 22736Sbill } 22836Sbill if (bno % CLSIZE) 2292780Swnj panic("execa rmalloc"); 23036Sbill if (uap->argp) for (;;) { 23136Sbill ap = NULL; 2323621Sroot if (indir && (na == 1 || na == 2 && sharg)) 2332301Skre ap = (int)uap->fname; 2342301Skre else if (uap->argp) { 23536Sbill ap = fuword((caddr_t)uap->argp); 23636Sbill uap->argp++; 23736Sbill } 23836Sbill if (ap==NULL && uap->envp) { 23936Sbill uap->argp = NULL; 24036Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 24136Sbill break; 24236Sbill uap->envp++; 24336Sbill ne++; 24436Sbill } 2456568Smckusic if (ap == NULL) 24636Sbill break; 24736Sbill na++; 2484827Swnj if (ap == -1) 24936Sbill u.u_error = EFAULT; 25036Sbill do { 25136Sbill if (nc >= NCARGS-1) 25236Sbill u.u_error = E2BIG; 2532301Skre if (indir && na == 2 && sharg != NULL) 2542301Skre c = *sharg++ & 0377; 2552301Skre else if ((c = fubyte((caddr_t)ap++)) < 0) 25636Sbill u.u_error = EFAULT; 25783Sbill if (u.u_error) { 25883Sbill if (bp) 25983Sbill brelse(bp); 26083Sbill bp = 0; 26136Sbill goto badarg; 26283Sbill } 2636568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 26436Sbill if (bp) 26536Sbill bdwrite(bp); 2668968Sroot bp = getblk(argdev, bno + ctod(nc / NBPG), 2676568Smckusic CLSIZE*NBPG); 26836Sbill cp = bp->b_un.b_addr; 26936Sbill } 27036Sbill nc++; 27136Sbill *cp++ = c; 2726568Smckusic } while (c > 0); 27336Sbill } 27436Sbill if (bp) 27536Sbill bdwrite(bp); 27636Sbill bp = 0; 27736Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 2786568Smckusic if (indir) { 2796568Smckusic u.u_dent.d_namlen = strlen(cfname); 2806568Smckusic bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, 2817816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 2826568Smckusic } 2832301Skre getxfile(ip, nc + (na+4)*NBPW, uid, gid); 284912Sbill if (u.u_error) { 28536Sbill badarg: 286*9006Sroot for (c = 0; c < nc; c += CLSIZE*NBPG) { 287*9006Sroot bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG); 2888968Sroot if (bp) { 28936Sbill bp->b_flags |= B_AGE; /* throw away */ 29036Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 29136Sbill brelse(bp); 29236Sbill bp = 0; 29336Sbill } 294*9006Sroot } 29536Sbill goto bad; 29636Sbill } 29736Sbill 29836Sbill /* 29936Sbill * copy back arglist 30036Sbill */ 30136Sbill ucp = USRSTACK - nc - NBPW; 30236Sbill ap = ucp - na*NBPW - 3*NBPW; 30336Sbill u.u_ar0[SP] = ap; 304132Sbill (void) suword((caddr_t)ap, na-ne); 30536Sbill nc = 0; 30636Sbill for (;;) { 30736Sbill ap += NBPW; 30836Sbill if (na==ne) { 309132Sbill (void) suword((caddr_t)ap, 0); 31036Sbill ap += NBPW; 31136Sbill } 31236Sbill if (--na < 0) 31336Sbill break; 314132Sbill (void) suword((caddr_t)ap, ucp); 31536Sbill do { 3166568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 31736Sbill if (bp) 31836Sbill brelse(bp); 3196568Smckusic bp = bread(argdev, bno + nc / NBPG, 3206568Smckusic CLSIZE*NBPG); 32136Sbill bp->b_flags |= B_AGE; /* throw away */ 32236Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 32336Sbill cp = bp->b_un.b_addr; 32436Sbill } 325132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 32636Sbill nc++; 32736Sbill } while(c&0377); 32836Sbill } 329132Sbill (void) suword((caddr_t)ap, 0); 330132Sbill (void) suword((caddr_t)ucp, 0); 33136Sbill setregs(); 33236Sbill bad: 33336Sbill if (bp) 33436Sbill brelse(bp); 33536Sbill if (bno) 3368816Sroot rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); 33736Sbill iput(ip); 33836Sbill } 33936Sbill 34036Sbill /* 34136Sbill * Read in and set up memory for executed file. 34236Sbill */ 3432301Skre getxfile(ip, nargc, uid, gid) 34436Sbill register struct inode *ip; 34536Sbill { 34636Sbill register size_t ts, ds, ss; 3472301Skre int pagi; 34836Sbill 3492301Skre if (u.u_exdata.ux_mag == 0413) 35036Sbill pagi = SPAGI; 3512301Skre else 3522301Skre pagi = 0; 3534827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 3544827Swnj ip->i_count!=1) { 355890Sbill register struct file *fp; 356890Sbill 3574827Swnj for (fp = file; fp < fileNFILE; fp++) { 3587497Sroot if (fp->f_type == DTYPE_FILE && 3597497Sroot fp->f_inode == ip && (fp->f_flag&FWRITE)) { 360890Sbill u.u_error = ETXTBSY; 361890Sbill goto bad; 362890Sbill } 3634827Swnj } 36436Sbill } 36536Sbill 36636Sbill /* 3674827Swnj * Compute text and data sizes and make sure not too large. 36836Sbill */ 36936Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 37036Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 37136Sbill ss = clrnd(SSIZE + btoc(nargc)); 372912Sbill if (chksize(ts, ds, ss)) 373912Sbill goto bad; 3744827Swnj 3754827Swnj /* 3764827Swnj * Make sure enough space to start process. 3774827Swnj */ 378912Sbill u.u_cdmap = zdmap; 379912Sbill u.u_csmap = zdmap; 380912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 381912Sbill goto bad; 38236Sbill 383912Sbill /* 384912Sbill * At this point, committed to the new image! 385912Sbill * Release virtual memory resources of old process, and 386912Sbill * initialize the virtual memory of the new process. 387912Sbill * If we resulted from vfork(), instead wakeup our 388912Sbill * parent who will set SVFDONE when he has taken back 389912Sbill * our resources. 390912Sbill */ 391912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 392912Sbill vrelvm(); 393912Sbill else { 394912Sbill u.u_procp->p_flag &= ~SVFORK; 395912Sbill u.u_procp->p_flag |= SKEEP; 396912Sbill wakeup((caddr_t)u.u_procp); 397912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 398912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 399912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 400912Sbill } 4013592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 402912Sbill u.u_procp->p_flag |= pagi; 403912Sbill u.u_dmap = u.u_cdmap; 404912Sbill u.u_smap = u.u_csmap; 405912Sbill vgetvm(ts, ds, ss); 406912Sbill 4077748Sroot if (pagi == 0) 4087816Sroot u.u_error = 4097816Sroot rdwri(UIO_READ, ip, 4108968Sroot (char *)ctob(dptov(u.u_procp, 0)), 4118968Sroot (int)u.u_exdata.ux_dsize, 4127816Sroot (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), 4137816Sroot 0, (int *)0); 414912Sbill xalloc(ip, pagi); 415912Sbill if (pagi && u.u_procp->p_textp) 416912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 417912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 4188665S (long)(1 + ts/CLSIZE), (int)btoc(u.u_exdata.ux_dsize)); 41936Sbill 4208968Sroot #ifdef vax 421912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 4228443Sroot #include "../vax/mtpr.h" /* XXX */ 423912Sbill mtpr(TBIA, 0); 4248968Sroot #endif 42536Sbill 4267530Sroot if (u.u_error) 4277530Sroot swkill(u.u_procp, "i/o error mapping pages"); 428912Sbill /* 429912Sbill * set SUID/SGID protections, if no tracing 430912Sbill */ 431912Sbill if ((u.u_procp->p_flag&STRC)==0) { 4324827Swnj u.u_uid = uid; 4334827Swnj u.u_procp->p_uid = uid; 4342301Skre u.u_gid = gid; 4358665S (void) entergroup(gid); 436912Sbill } else 437912Sbill psignal(u.u_procp, SIGTRAP); 43836Sbill u.u_tsize = ts; 43936Sbill u.u_dsize = ds; 44036Sbill u.u_ssize = ss; 44136Sbill bad: 442912Sbill return; 44336Sbill } 44436Sbill 44536Sbill /* 44636Sbill * Clear registers on exec 44736Sbill */ 44836Sbill setregs() 44936Sbill { 450173Sbill register int (**rp)(); 45136Sbill register i; 452188Sbill long sigmask; 45336Sbill 4546464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 455188Sbill sigmask <<= 1, rp++) { 456188Sbill switch (*rp) { 457188Sbill 458188Sbill case SIG_IGN: 459188Sbill case SIG_DFL: 460188Sbill case SIG_HOLD: 461188Sbill continue; 462188Sbill 463188Sbill default: 464188Sbill /* 465206Sbill * Normal or deferring catch; revert to default. 466188Sbill */ 467206Sbill (void) spl6(); 468206Sbill *rp = SIG_DFL; 469188Sbill if ((int)*rp & 1) 470188Sbill u.u_procp->p_siga0 |= sigmask; 471188Sbill else 4726327Swnj u.u_procp->p_siga0 &= ~sigmask; 473188Sbill if ((int)*rp & 2) 474188Sbill u.u_procp->p_siga1 |= sigmask; 475188Sbill else 476188Sbill u.u_procp->p_siga1 &= ~sigmask; 477206Sbill (void) spl0(); 478188Sbill continue; 479188Sbill } 480188Sbill } 4818968Sroot #ifdef vax 48236Sbill /* 4834827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 48436Sbill *rp++ = 0; 48536Sbill */ 4868968Sroot u.u_ar0[PC] = u.u_exdata.ux_entloc+2; 4878968Sroot #endif 4888968Sroot #ifdef sun 4898968Sroot { register struct regs *r = (struct regs *)u.u_ar0; 4908968Sroot for (i = 0; i < 8; i++) { 4918968Sroot r->r_dreg[i] = 0; 4928968Sroot if (&r->r_areg[i] != &r->r_sp) 4938968Sroot r->r_areg[i] = 0; 4948968Sroot } 4958968Sroot r->r_sr = PSL_USERSET; 4968968Sroot r->r_pc = u.u_exdata.ux_entloc; 4978968Sroot } 4988968Sroot #endif 4994827Swnj for (i=0; i<NOFILE; i++) { 50036Sbill if (u.u_pofile[i]&EXCLOSE) { 5017697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 50236Sbill u.u_ofile[i] = NULL; 5037697Ssam u.u_pofile[i] = 0; 50436Sbill } 5058968Sroot #ifdef SUNMMAP 5068968Sroot u.u_pofile[i] &= ~UF_MAPPED; 5078968Sroot #endif 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; 5468827Sroot struct mbuf *m = m_getclr(M_WAIT); 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++) { 5847697Ssam #ifdef notdef 5857697Ssam /* why was this like this? */ 58636Sbill f = u.u_ofile[i]; 58736Sbill u.u_ofile[i] = NULL; 5885581Swnj closef(f, 1); 5897697Ssam #else 5907697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 5917697Ssam u.u_ofile[i] = NULL; 5927697Ssam u.u_pofile[i] = 0; 5937697Ssam #endif 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; 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 6758151Sroot #include <vtimes.h> 6768151Sroot 6778099Sroot owait() 67836Sbill { 6798151Sroot struct rusage ru; 6808151Sroot struct vtimes *vtp, avt; 68136Sbill 682188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 6838030Sroot wait1(0, (struct rusage *)0); 684188Sbill return; 685188Sbill } 6868151Sroot vtp = (struct vtimes *)u.u_ar0[R1]; 6878030Sroot wait1(u.u_ar0[R0], &ru); 688188Sbill if (u.u_error) 689188Sbill return; 6908151Sroot getvtimes(&ru, &avt); 6918151Sroot (void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes)); 69236Sbill } 69336Sbill 69436Sbill /* 69536Sbill * Wait system call. 69636Sbill * Search for a terminated (zombie) child, 69736Sbill * finally lay it to rest, and collect its status. 69836Sbill * Look also for stopped (traced) children, 69936Sbill * and pass back status from them. 70036Sbill */ 7018030Sroot wait1(options, ru) 7028030Sroot register int options; 7038030Sroot struct rusage *ru; 70436Sbill { 70536Sbill register f; 7067488Skre register struct proc *p, *q; 70736Sbill 70836Sbill f = 0; 70936Sbill loop: 7104827Swnj for (p = proc; p < procNPROC; p++) 7114827Swnj if (p->p_pptr == u.u_procp) { 71236Sbill f++; 7134827Swnj if (p->p_stat == SZOMB) { 71436Sbill u.u_r.r_val1 = p->p_pid; 7158030Sroot u.u_r.r_val2 = p->p_xstat; 7168030Sroot p->p_xstat = 0; 7178030Sroot if (ru) 7188030Sroot *ru = *p->p_ru; 7198030Sroot ruadd(&u.u_cru, p->p_ru); 7208665S (void) m_free(dtom(p->p_ru)); 7218030Sroot p->p_ru = 0; 72236Sbill p->p_stat = NULL; 72336Sbill p->p_pid = 0; 72436Sbill p->p_ppid = 0; 7257488Skre if (q = p->p_ysptr) 7267488Skre q->p_osptr = p->p_osptr; 7277488Skre if (q = p->p_osptr) 7287488Skre q->p_ysptr = p->p_ysptr; 7297488Skre if ((q = p->p_pptr)->p_cptr == p) 7307488Skre q->p_cptr = p->p_osptr; 731188Sbill p->p_pptr = 0; 7327488Skre p->p_ysptr = 0; 7337488Skre p->p_osptr = 0; 7347488Skre p->p_cptr = 0; 73536Sbill p->p_sig = 0; 736188Sbill p->p_siga0 = 0; 737188Sbill p->p_siga1 = 0; 73836Sbill p->p_pgrp = 0; 73936Sbill p->p_flag = 0; 74036Sbill p->p_wchan = 0; 741188Sbill p->p_cursig = 0; 74236Sbill return; 74336Sbill } 744188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 745188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 746188Sbill p->p_flag |= SWTED; 747188Sbill u.u_r.r_val1 = p->p_pid; 748188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 749188Sbill return; 75036Sbill } 75136Sbill } 752188Sbill if (f==0) { 753188Sbill u.u_error = ECHILD; 754188Sbill return; 75536Sbill } 756188Sbill if (options&WNOHANG) { 757188Sbill u.u_r.r_val1 = 0; 758188Sbill return; 759188Sbill } 7608116Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 761188Sbill u.u_eosys = RESTARTSYS; 762188Sbill return; 763188Sbill } 764188Sbill sleep((caddr_t)u.u_procp, PWAIT); 765188Sbill goto loop; 76636Sbill } 76736Sbill 76836Sbill /* 76936Sbill * fork system call. 77036Sbill */ 77136Sbill fork() 77236Sbill { 77336Sbill 77436Sbill u.u_cdmap = zdmap; 77536Sbill u.u_csmap = zdmap; 77636Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 77736Sbill u.u_r.r_val2 = 0; 77836Sbill return; 77936Sbill } 78036Sbill fork1(0); 78136Sbill } 78236Sbill 78336Sbill fork1(isvfork) 78436Sbill { 78536Sbill register struct proc *p1, *p2; 7867488Skre #ifndef QUOTA 78736Sbill register a; 78836Sbill 78936Sbill a = 0; 7907488Skre #else 7917488Skre if (u.u_quota != NOQUOT && u.u_quota->q_plim && 7927488Skre u.u_quota->q_cnt >= u.u_quota->q_plim) { 7937488Skre u.u_error = EPROCLIM; 7947488Skre return; 7957488Skre } 7967488Skre #endif 79736Sbill p2 = NULL; 7984827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 7997488Skre #ifdef QUOTA 8007488Skre if (p1->p_stat == NULL) { 8017488Skre p2 = p1; 8027488Skre break; 8037488Skre } 8047488Skre #else 80536Sbill if (p1->p_stat==NULL && p2==NULL) 80636Sbill p2 = p1; 80736Sbill else { 80836Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 80936Sbill a++; 81036Sbill } 8117488Skre #endif 81236Sbill } 81336Sbill /* 81436Sbill * Disallow if 81536Sbill * No processes at all; 81636Sbill * not su and too many procs owned; or 81736Sbill * not su and would take last slot. 81836Sbill */ 8192938Swnj if (p2==NULL) 8202938Swnj tablefull("proc"); 8217488Skre #ifdef QUOTA 8227488Skre if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { 8237488Skre #else 8242741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 8257488Skre #endif 82636Sbill u.u_error = EAGAIN; 82736Sbill if (!isvfork) { 828132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 829132Sbill (void) vsexpand(0, &u.u_csmap, 1); 83036Sbill } 83136Sbill goto out; 83236Sbill } 83336Sbill p1 = u.u_procp; 8344827Swnj if (newproc(isvfork)) { 83536Sbill u.u_r.r_val1 = p1->p_pid; 83636Sbill u.u_r.r_val2 = 1; /* child */ 8378030Sroot u.u_start = time.tv_sec; 83836Sbill u.u_acflag = AFORK; 8397488Skre #ifdef QUOTA 8407488Skre u.u_qflags &= ~QUF_LOGIN; 8417488Skre #endif 84236Sbill return; 84336Sbill } 84436Sbill u.u_r.r_val1 = p2->p_pid; 84536Sbill 84636Sbill out: 84736Sbill u.u_r.r_val2 = 0; 84836Sbill } 84936Sbill 8507497Sroot spgrp(top, npgrp) 8517497Sroot register struct proc *top; 8527497Sroot { 8537497Sroot register struct proc *pp, *p; 8547497Sroot int f = 0; 8557497Sroot 8567497Sroot for (p = top; npgrp == -1 || u.u_uid == p->p_uid || 8577497Sroot !u.u_uid || inferior(p); p = pp) { 8587497Sroot if (npgrp == -1) { 8597497Sroot #define bit(a) (1<<(a-1)) 8607497Sroot p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 8617497Sroot } else 8627497Sroot p->p_pgrp = npgrp; 8637497Sroot f++; 8647497Sroot /* 8657497Sroot * Search for children. 8667497Sroot */ 8677497Sroot for (pp = proc; pp < procNPROC; pp++) 8687497Sroot if (pp->p_pptr == p) 8697497Sroot goto cont; 8707497Sroot /* 8717497Sroot * Search for siblings. 8727497Sroot */ 8737497Sroot for (; p != top; p = p->p_pptr) 8747497Sroot for (pp = p + 1; pp < procNPROC; pp++) 8757497Sroot if (pp->p_pptr == p->p_pptr) 8767497Sroot goto cont; 8777497Sroot break; 8787497Sroot cont: 8797497Sroot ; 8807497Sroot } 8817497Sroot return (f); 8827497Sroot } 8837497Sroot 88436Sbill /* 8857497Sroot * Is p an inferior of the current process? 88636Sbill */ 8877497Sroot inferior(p) 8887816Sroot register struct proc *p; 88936Sbill { 89036Sbill 8917497Sroot for (; p != u.u_procp; p = p->p_pptr) 8927497Sroot if (p->p_ppid == 0) 8937497Sroot return (0); 8947497Sroot return (1); 89536Sbill } 8967816Sroot 8977816Sroot struct proc * 8987816Sroot pfind(pid) 8997816Sroot int pid; 9007816Sroot { 9017816Sroot register struct proc *p; 9027816Sroot 9037816Sroot for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 9047816Sroot if (p->p_pid == pid) 9057816Sroot return (p); 9067816Sroot return ((struct proc *)0); 9077816Sroot } 9088099Sroot 9098099Sroot /* 9108099Sroot * Create a new process-- the internal version of 9118099Sroot * sys fork. 9128099Sroot * It returns 1 in the new process, 0 in the old. 9138099Sroot */ 9148099Sroot newproc(isvfork) 9158099Sroot int isvfork; 9168099Sroot { 9178099Sroot register struct proc *p; 9188099Sroot register struct proc *rpp, *rip; 9198099Sroot register int n; 9208099Sroot register struct file *fp; 9218099Sroot 9228099Sroot p = NULL; 9238099Sroot /* 9248099Sroot * First, just locate a slot for a process 9258099Sroot * and copy the useful info from this process into it. 9268099Sroot * The panic "cannot happen" because fork has already 9278099Sroot * checked for the existence of a slot. 9288099Sroot */ 9298099Sroot retry: 9308099Sroot mpid++; 9318099Sroot if (mpid >= 30000) { 9328099Sroot mpid = 0; 9338099Sroot goto retry; 9348099Sroot } 9358099Sroot for (rpp = proc; rpp < procNPROC; rpp++) { 9368099Sroot if (rpp->p_stat == NULL && p==NULL) 9378099Sroot p = rpp; 9388099Sroot if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) 9398099Sroot goto retry; 9408099Sroot } 9418099Sroot if ((rpp = p) == NULL) 9428099Sroot panic("no procs"); 9438099Sroot 9448099Sroot /* 9458099Sroot * Make a proc table entry for the new process. 9468099Sroot */ 9478099Sroot rip = u.u_procp; 9488099Sroot #ifdef QUOTA 9498099Sroot (rpp->p_quota = rip->p_quota)->q_cnt++; 9508099Sroot #endif 9518099Sroot rpp->p_stat = SIDL; 9528099Sroot timerclear(&rpp->p_realtimer.it_value); 9538099Sroot rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG)); 9548099Sroot if (isvfork) { 9558099Sroot rpp->p_flag |= SVFORK; 9568099Sroot rpp->p_ndx = rip->p_ndx; 9578099Sroot } else 9588099Sroot rpp->p_ndx = rpp - proc; 9598099Sroot rpp->p_uid = rip->p_uid; 9608099Sroot rpp->p_pgrp = rip->p_pgrp; 9618099Sroot rpp->p_nice = rip->p_nice; 9628099Sroot rpp->p_textp = isvfork ? 0 : rip->p_textp; 9638099Sroot rpp->p_pid = mpid; 9648099Sroot rpp->p_ppid = rip->p_pid; 9658099Sroot rpp->p_pptr = rip; 9668099Sroot rpp->p_osptr = rip->p_cptr; 9678099Sroot if (rip->p_cptr) 9688099Sroot rip->p_cptr->p_ysptr = rpp; 9698099Sroot rpp->p_ysptr = NULL; 9708099Sroot rpp->p_cptr = NULL; 9718099Sroot rip->p_cptr = rpp; 9728099Sroot rpp->p_time = 0; 9738099Sroot rpp->p_cpu = 0; 9748099Sroot rpp->p_siga0 = rip->p_siga0; 9758099Sroot rpp->p_siga1 = rip->p_siga1; 9768099Sroot /* take along any pending signals, like stops? */ 9778099Sroot if (isvfork) { 9788099Sroot rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; 9798099Sroot rpp->p_szpt = clrnd(ctopt(UPAGES)); 9808099Sroot forkstat.cntvfork++; 9818099Sroot forkstat.sizvfork += rip->p_dsize + rip->p_ssize; 9828099Sroot } else { 9838099Sroot rpp->p_tsize = rip->p_tsize; 9848099Sroot rpp->p_dsize = rip->p_dsize; 9858099Sroot rpp->p_ssize = rip->p_ssize; 9868099Sroot rpp->p_szpt = rip->p_szpt; 9878099Sroot forkstat.cntfork++; 9888099Sroot forkstat.sizfork += rip->p_dsize + rip->p_ssize; 9898099Sroot } 9908099Sroot rpp->p_rssize = 0; 9918099Sroot rpp->p_maxrss = rip->p_maxrss; 9928099Sroot rpp->p_wchan = 0; 9938099Sroot rpp->p_slptime = 0; 9948099Sroot rpp->p_pctcpu = 0; 9958099Sroot rpp->p_cpticks = 0; 9968099Sroot n = PIDHASH(rpp->p_pid); 9978099Sroot p->p_idhash = pidhash[n]; 9988099Sroot pidhash[n] = rpp - proc; 9998099Sroot multprog++; 10008099Sroot 10018099Sroot /* 10028099Sroot * Increase reference counts on shared objects. 10038099Sroot */ 10048099Sroot for (n = 0; n < NOFILE; n++) { 10058099Sroot fp = u.u_ofile[n]; 10068099Sroot if (fp == NULL) 10078099Sroot continue; 10088099Sroot fp->f_count++; 10098099Sroot if (u.u_pofile[n]&RDLOCK) 10108099Sroot fp->f_inode->i_rdlockc++; 10118099Sroot if (u.u_pofile[n]&WRLOCK) 10128099Sroot fp->f_inode->i_wrlockc++; 10138099Sroot } 10148099Sroot u.u_cdir->i_count++; 10158099Sroot if (u.u_rdir) 10168099Sroot u.u_rdir->i_count++; 10178099Sroot 10188099Sroot /* 10198099Sroot * Partially simulate the environment 10208099Sroot * of the new process so that when it is actually 10218099Sroot * created (by copying) it will look right. 10228099Sroot * This begins the section where we must prevent the parent 10238099Sroot * from being swapped. 10248099Sroot */ 10258099Sroot rip->p_flag |= SKEEP; 10268099Sroot if (procdup(rpp, isvfork)) 10278099Sroot return (1); 10288099Sroot 10298099Sroot /* 10308099Sroot * Make child runnable and add to run queue. 10318099Sroot */ 10328099Sroot (void) spl6(); 10338099Sroot rpp->p_stat = SRUN; 10348099Sroot setrq(rpp); 10358099Sroot (void) spl0(); 10368099Sroot 10378099Sroot /* 10388099Sroot * Cause child to take a non-local goto as soon as it runs. 10398099Sroot * On older systems this was done with SSWAP bit in proc 10408099Sroot * table; on VAX we use u.u_pcb.pcb_sswap so don't need 10418099Sroot * to do rpp->p_flag |= SSWAP. Actually do nothing here. 10428099Sroot */ 10438099Sroot /* rpp->p_flag |= SSWAP; */ 10448099Sroot 10458099Sroot /* 10468099Sroot * Now can be swapped. 10478099Sroot */ 10488099Sroot rip->p_flag &= ~SKEEP; 10498099Sroot 10508099Sroot /* 10518099Sroot * If vfork make chain from parent process to child 10528099Sroot * (where virtal memory is temporarily). Wait for 10538099Sroot * child to finish, steal virtual memory back, 10548099Sroot * and wakeup child to let it die. 10558099Sroot */ 10568099Sroot if (isvfork) { 10578099Sroot u.u_procp->p_xlink = rpp; 10588099Sroot u.u_procp->p_flag |= SNOVM; 10598099Sroot while (rpp->p_flag & SVFORK) 10608099Sroot sleep((caddr_t)rpp, PZERO - 1); 10618099Sroot if ((rpp->p_flag & SLOAD) == 0) 10628099Sroot panic("newproc vfork"); 10638099Sroot uaccess(rpp, Vfmap, &vfutl); 10648099Sroot u.u_procp->p_xlink = 0; 10658099Sroot vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 10668099Sroot u.u_procp->p_flag &= ~SNOVM; 10678099Sroot rpp->p_ndx = rpp - proc; 10688099Sroot rpp->p_flag |= SVFDONE; 10698099Sroot wakeup((caddr_t)rpp); 10708099Sroot } 10718099Sroot 10728099Sroot /* 10738099Sroot * 0 return means parent. 10748099Sroot */ 10758099Sroot return (0); 10768099Sroot } 1077