1*8968Sroot /* kern_proc.c 4.46 82/10/31 */ 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" 15*8968Sroot #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); 266*8968Sroot 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: 2866568Smckusic for (c = 0; c < nc; c += CLSIZE*NBPG) 287*8968Sroot bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG)); 288*8968Sroot 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 } 29436Sbill goto bad; 29536Sbill } 29636Sbill 29736Sbill /* 29836Sbill * copy back arglist 29936Sbill */ 30036Sbill ucp = USRSTACK - nc - NBPW; 30136Sbill ap = ucp - na*NBPW - 3*NBPW; 30236Sbill u.u_ar0[SP] = ap; 303132Sbill (void) suword((caddr_t)ap, na-ne); 30436Sbill nc = 0; 30536Sbill for (;;) { 30636Sbill ap += NBPW; 30736Sbill if (na==ne) { 308132Sbill (void) suword((caddr_t)ap, 0); 30936Sbill ap += NBPW; 31036Sbill } 31136Sbill if (--na < 0) 31236Sbill break; 313132Sbill (void) suword((caddr_t)ap, ucp); 31436Sbill do { 3156568Smckusic if (nc % (CLSIZE*NBPG) == 0) { 31636Sbill if (bp) 31736Sbill brelse(bp); 3186568Smckusic bp = bread(argdev, bno + nc / NBPG, 3196568Smckusic CLSIZE*NBPG); 32036Sbill bp->b_flags |= B_AGE; /* throw away */ 32136Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 32236Sbill cp = bp->b_un.b_addr; 32336Sbill } 324132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 32536Sbill nc++; 32636Sbill } while(c&0377); 32736Sbill } 328132Sbill (void) suword((caddr_t)ap, 0); 329132Sbill (void) suword((caddr_t)ucp, 0); 33036Sbill setregs(); 33136Sbill bad: 33236Sbill if (bp) 33336Sbill brelse(bp); 33436Sbill if (bno) 3358816Sroot rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); 33636Sbill iput(ip); 33736Sbill } 33836Sbill 33936Sbill /* 34036Sbill * Read in and set up memory for executed file. 34136Sbill */ 3422301Skre getxfile(ip, nargc, uid, gid) 34336Sbill register struct inode *ip; 34436Sbill { 34536Sbill register size_t ts, ds, ss; 3462301Skre int pagi; 34736Sbill 3482301Skre if (u.u_exdata.ux_mag == 0413) 34936Sbill pagi = SPAGI; 3502301Skre else 3512301Skre pagi = 0; 3524827Swnj if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && 3534827Swnj ip->i_count!=1) { 354890Sbill register struct file *fp; 355890Sbill 3564827Swnj for (fp = file; fp < fileNFILE; fp++) { 3577497Sroot if (fp->f_type == DTYPE_FILE && 3587497Sroot fp->f_inode == ip && (fp->f_flag&FWRITE)) { 359890Sbill u.u_error = ETXTBSY; 360890Sbill goto bad; 361890Sbill } 3624827Swnj } 36336Sbill } 36436Sbill 36536Sbill /* 3664827Swnj * Compute text and data sizes and make sure not too large. 36736Sbill */ 36836Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 36936Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 37036Sbill ss = clrnd(SSIZE + btoc(nargc)); 371912Sbill if (chksize(ts, ds, ss)) 372912Sbill goto bad; 3734827Swnj 3744827Swnj /* 3754827Swnj * Make sure enough space to start process. 3764827Swnj */ 377912Sbill u.u_cdmap = zdmap; 378912Sbill u.u_csmap = zdmap; 379912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 380912Sbill goto bad; 38136Sbill 382912Sbill /* 383912Sbill * At this point, committed to the new image! 384912Sbill * Release virtual memory resources of old process, and 385912Sbill * initialize the virtual memory of the new process. 386912Sbill * If we resulted from vfork(), instead wakeup our 387912Sbill * parent who will set SVFDONE when he has taken back 388912Sbill * our resources. 389912Sbill */ 390912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 391912Sbill vrelvm(); 392912Sbill else { 393912Sbill u.u_procp->p_flag &= ~SVFORK; 394912Sbill u.u_procp->p_flag |= SKEEP; 395912Sbill wakeup((caddr_t)u.u_procp); 396912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 397912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 398912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 399912Sbill } 4003592Swnj u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); 401912Sbill u.u_procp->p_flag |= pagi; 402912Sbill u.u_dmap = u.u_cdmap; 403912Sbill u.u_smap = u.u_csmap; 404912Sbill vgetvm(ts, ds, ss); 405912Sbill 4067748Sroot if (pagi == 0) 4077816Sroot u.u_error = 4087816Sroot rdwri(UIO_READ, ip, 409*8968Sroot (char *)ctob(dptov(u.u_procp, 0)), 410*8968Sroot (int)u.u_exdata.ux_dsize, 4117816Sroot (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), 4127816Sroot 0, (int *)0); 413912Sbill xalloc(ip, pagi); 414912Sbill if (pagi && u.u_procp->p_textp) 415912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 416912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 4178665S (long)(1 + ts/CLSIZE), (int)btoc(u.u_exdata.ux_dsize)); 41836Sbill 419*8968Sroot #ifdef vax 420912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 4218443Sroot #include "../vax/mtpr.h" /* XXX */ 422912Sbill mtpr(TBIA, 0); 423*8968Sroot #endif 42436Sbill 4257530Sroot if (u.u_error) 4267530Sroot swkill(u.u_procp, "i/o error mapping pages"); 427912Sbill /* 428912Sbill * set SUID/SGID protections, if no tracing 429912Sbill */ 430912Sbill if ((u.u_procp->p_flag&STRC)==0) { 4314827Swnj u.u_uid = uid; 4324827Swnj u.u_procp->p_uid = uid; 4332301Skre u.u_gid = gid; 4348665S (void) entergroup(gid); 435912Sbill } else 436912Sbill psignal(u.u_procp, SIGTRAP); 43736Sbill u.u_tsize = ts; 43836Sbill u.u_dsize = ds; 43936Sbill u.u_ssize = ss; 44036Sbill bad: 441912Sbill return; 44236Sbill } 44336Sbill 44436Sbill /* 44536Sbill * Clear registers on exec 44636Sbill */ 44736Sbill setregs() 44836Sbill { 449173Sbill register int (**rp)(); 45036Sbill register i; 451188Sbill long sigmask; 45236Sbill 4536464Swnj for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; 454188Sbill sigmask <<= 1, rp++) { 455188Sbill switch (*rp) { 456188Sbill 457188Sbill case SIG_IGN: 458188Sbill case SIG_DFL: 459188Sbill case SIG_HOLD: 460188Sbill continue; 461188Sbill 462188Sbill default: 463188Sbill /* 464206Sbill * Normal or deferring catch; revert to default. 465188Sbill */ 466206Sbill (void) spl6(); 467206Sbill *rp = SIG_DFL; 468188Sbill if ((int)*rp & 1) 469188Sbill u.u_procp->p_siga0 |= sigmask; 470188Sbill else 4716327Swnj u.u_procp->p_siga0 &= ~sigmask; 472188Sbill if ((int)*rp & 2) 473188Sbill u.u_procp->p_siga1 |= sigmask; 474188Sbill else 475188Sbill u.u_procp->p_siga1 &= ~sigmask; 476206Sbill (void) spl0(); 477188Sbill continue; 478188Sbill } 479188Sbill } 480*8968Sroot #ifdef vax 48136Sbill /* 4824827Swnj for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 48336Sbill *rp++ = 0; 48436Sbill */ 485*8968Sroot u.u_ar0[PC] = u.u_exdata.ux_entloc+2; 486*8968Sroot #endif 487*8968Sroot #ifdef sun 488*8968Sroot { register struct regs *r = (struct regs *)u.u_ar0; 489*8968Sroot for (i = 0; i < 8; i++) { 490*8968Sroot r->r_dreg[i] = 0; 491*8968Sroot if (&r->r_areg[i] != &r->r_sp) 492*8968Sroot r->r_areg[i] = 0; 493*8968Sroot } 494*8968Sroot r->r_sr = PSL_USERSET; 495*8968Sroot r->r_pc = u.u_exdata.ux_entloc; 496*8968Sroot } 497*8968Sroot #endif 4984827Swnj for (i=0; i<NOFILE; i++) { 49936Sbill if (u.u_pofile[i]&EXCLOSE) { 5007697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 50136Sbill u.u_ofile[i] = NULL; 5027697Ssam u.u_pofile[i] = 0; 50336Sbill } 504*8968Sroot #ifdef SUNMMAP 505*8968Sroot u.u_pofile[i] &= ~UF_MAPPED; 506*8968Sroot #endif 50736Sbill } 5084827Swnj 50936Sbill /* 51036Sbill * Remember file name for accounting. 51136Sbill */ 51236Sbill u.u_acflag &= ~AFORK; 5136568Smckusic bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm, 5147816Sroot (unsigned)(u.u_dent.d_namlen + 1)); 515*8968Sroot #ifdef sun 516*8968Sroot u.u_eosys = REALLYRETURN; 517*8968Sroot #endif 51836Sbill } 51936Sbill 52036Sbill /* 5214827Swnj * Exit system call: pass back caller's arg 52236Sbill */ 52336Sbill rexit() 52436Sbill { 52536Sbill register struct a { 52636Sbill int rval; 52736Sbill } *uap; 52836Sbill 52936Sbill uap = (struct a *)u.u_ap; 53036Sbill exit((uap->rval & 0377) << 8); 53136Sbill } 53236Sbill 53336Sbill /* 53436Sbill * Release resources. 53536Sbill * Save u. area for parent to look at. 53636Sbill * Enter zombie state. 53736Sbill * Wake up parent and init processes, 53836Sbill * and dispose of children. 53936Sbill */ 54036Sbill exit(rv) 54136Sbill { 54236Sbill register int i; 54336Sbill register struct proc *p, *q; 54436Sbill register int x; 5458827Sroot struct mbuf *m = m_getclr(M_WAIT); 54636Sbill 54736Sbill #ifdef PGINPROF 54836Sbill vmsizmon(); 54936Sbill #endif 55036Sbill p = u.u_procp; 55136Sbill p->p_flag &= ~(STRC|SULOCK); 55236Sbill p->p_flag |= SWEXIT; 553188Sbill (void) spl6(); 554188Sbill if ((int)SIG_IGN & 1) 555188Sbill p->p_siga0 = ~0; 556188Sbill else 557188Sbill p->p_siga0 = 0; 558188Sbill if ((int)SIG_IGN & 2) 559188Sbill p->p_siga1 = ~0; 560188Sbill else 561206Sbill p->p_siga1 = 0; 562188Sbill (void) spl0(); 5631399Sbill p->p_cpticks = 0; 5641399Sbill p->p_pctcpu = 0; 5654827Swnj for (i=0; i<NSIG; i++) 566173Sbill u.u_signal[i] = SIG_IGN; 5678623Sroot untimeout(realitexpire, (caddr_t)p); 56836Sbill /* 56936Sbill * Release virtual memory. If we resulted from 57036Sbill * a vfork(), instead give the resources back to 57136Sbill * the parent. 57236Sbill */ 57336Sbill if ((p->p_flag & SVFORK) == 0) 57436Sbill vrelvm(); 57536Sbill else { 57636Sbill p->p_flag &= ~SVFORK; 57736Sbill wakeup((caddr_t)p); 57836Sbill while ((p->p_flag & SVFDONE) == 0) 57936Sbill sleep((caddr_t)p, PZERO - 1); 58036Sbill p->p_flag &= ~SVFDONE; 58136Sbill } 5827697Ssam for (i = 0; i < NOFILE; i++) { 5837697Ssam #ifdef notdef 5847697Ssam /* why was this like this? */ 58536Sbill f = u.u_ofile[i]; 58636Sbill u.u_ofile[i] = NULL; 5875581Swnj closef(f, 1); 5887697Ssam #else 5897697Ssam closef(u.u_ofile[i], 1, u.u_pofile[i]); 5907697Ssam u.u_ofile[i] = NULL; 5917697Ssam u.u_pofile[i] = 0; 5927697Ssam #endif 59336Sbill } 5944827Swnj ilock(u.u_cdir); 59536Sbill iput(u.u_cdir); 59636Sbill if (u.u_rdir) { 5974827Swnj ilock(u.u_rdir); 59836Sbill iput(u.u_rdir); 59936Sbill } 6008030Sroot u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 60136Sbill acct(); 6027488Skre #ifdef QUOTA 6037488Skre qclean(); 6047488Skre #endif 605*8968Sroot #ifdef sun 606*8968Sroot ctxfree(&u); 607*8968Sroot #endif 60836Sbill vrelpt(u.u_procp); 60936Sbill vrelu(u.u_procp, 0); 6105630Swnj (void) spl5(); /* hack for mem alloc race XXX */ 61136Sbill multprog--; 612931Sbill p->p_stat = SZOMB; 613307Sbill noproc = 1; 61436Sbill i = PIDHASH(p->p_pid); 61536Sbill x = p - proc; 61636Sbill if (pidhash[i] == x) 61736Sbill pidhash[i] = p->p_idhash; 61836Sbill else { 61936Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 62036Sbill if (proc[i].p_idhash == x) { 62136Sbill proc[i].p_idhash = p->p_idhash; 62236Sbill goto done; 62336Sbill } 62436Sbill panic("exit"); 62536Sbill } 6261409Sbill if (p->p_pid == 1) 6271409Sbill panic("init died"); 62836Sbill done: 6298030Sroot p->p_xstat = rv; 6308827Sroot p->p_ru = mtod(m, struct rusage *); 6318030Sroot *p->p_ru = u.u_ru; 6328030Sroot ruadd(p->p_ru, &u.u_cru); 6334827Swnj for (q = proc; q < procNPROC; q++) 6344827Swnj if (q->p_pptr == p) { 6357488Skre if (q->p_osptr) 6367488Skre q->p_osptr->p_ysptr = q->p_ysptr; 6377488Skre if (q->p_ysptr) 6387488Skre q->p_ysptr->p_osptr = q->p_osptr; 6397488Skre if (proc[1].p_cptr) 6407488Skre proc[1].p_cptr->p_ysptr = q; 6417488Skre q->p_osptr = proc[1].p_cptr; 6427488Skre q->p_ysptr = NULL; 6437488Skre proc[1].p_cptr = q; 6447488Skre 645188Sbill q->p_pptr = &proc[1]; 646188Sbill q->p_ppid = 1; 64736Sbill wakeup((caddr_t)&proc[1]); 648188Sbill /* 649212Sbill * Traced processes are killed 650188Sbill * since their existence means someone is screwing up. 651354Sbill * Stopped processes are sent a hangup and a continue. 652212Sbill * This is designed to be ``safe'' for setuid 653212Sbill * processes since they must be willing to tolerate 654212Sbill * hangups anyways. 655188Sbill */ 656212Sbill if (q->p_flag&STRC) { 657188Sbill q->p_flag &= ~STRC; 658188Sbill psignal(q, SIGKILL); 659212Sbill } else if (q->p_stat == SSTOP) { 660212Sbill psignal(q, SIGHUP); 661212Sbill psignal(q, SIGCONT); 662188Sbill } 663215Sbill /* 664215Sbill * Protect this process from future 6655619Swnj * tty signals, clear TSTP/TTIN/TTOU if pending. 666215Sbill */ 6671788Sbill (void) spgrp(q, -1); 66836Sbill } 6696464Swnj psignal(p->p_pptr, SIGCHLD); 670188Sbill wakeup((caddr_t)p->p_pptr); 67136Sbill swtch(); 67236Sbill } 67336Sbill 6748151Sroot #include <vtimes.h> 6758151Sroot 6768099Sroot owait() 67736Sbill { 6788151Sroot struct rusage ru; 6798151Sroot struct vtimes *vtp, avt; 68036Sbill 681188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 6828030Sroot wait1(0, (struct rusage *)0); 683188Sbill return; 684188Sbill } 6858151Sroot vtp = (struct vtimes *)u.u_ar0[R1]; 6868030Sroot wait1(u.u_ar0[R0], &ru); 687188Sbill if (u.u_error) 688188Sbill return; 6898151Sroot getvtimes(&ru, &avt); 6908151Sroot (void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes)); 69136Sbill } 69236Sbill 69336Sbill /* 69436Sbill * Wait system call. 69536Sbill * Search for a terminated (zombie) child, 69636Sbill * finally lay it to rest, and collect its status. 69736Sbill * Look also for stopped (traced) children, 69836Sbill * and pass back status from them. 69936Sbill */ 7008030Sroot wait1(options, ru) 7018030Sroot register int options; 7028030Sroot struct rusage *ru; 70336Sbill { 70436Sbill register f; 7057488Skre register struct proc *p, *q; 70636Sbill 70736Sbill f = 0; 70836Sbill loop: 7094827Swnj for (p = proc; p < procNPROC; p++) 7104827Swnj if (p->p_pptr == u.u_procp) { 71136Sbill f++; 7124827Swnj if (p->p_stat == SZOMB) { 71336Sbill u.u_r.r_val1 = p->p_pid; 7148030Sroot u.u_r.r_val2 = p->p_xstat; 7158030Sroot p->p_xstat = 0; 7168030Sroot if (ru) 7178030Sroot *ru = *p->p_ru; 7188030Sroot ruadd(&u.u_cru, p->p_ru); 7198665S (void) m_free(dtom(p->p_ru)); 7208030Sroot p->p_ru = 0; 72136Sbill p->p_stat = NULL; 72236Sbill p->p_pid = 0; 72336Sbill p->p_ppid = 0; 7247488Skre if (q = p->p_ysptr) 7257488Skre q->p_osptr = p->p_osptr; 7267488Skre if (q = p->p_osptr) 7277488Skre q->p_ysptr = p->p_ysptr; 7287488Skre if ((q = p->p_pptr)->p_cptr == p) 7297488Skre q->p_cptr = p->p_osptr; 730188Sbill p->p_pptr = 0; 7317488Skre p->p_ysptr = 0; 7327488Skre p->p_osptr = 0; 7337488Skre p->p_cptr = 0; 73436Sbill p->p_sig = 0; 735188Sbill p->p_siga0 = 0; 736188Sbill p->p_siga1 = 0; 73736Sbill p->p_pgrp = 0; 73836Sbill p->p_flag = 0; 73936Sbill p->p_wchan = 0; 740188Sbill p->p_cursig = 0; 74136Sbill return; 74236Sbill } 743188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 744188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 745188Sbill p->p_flag |= SWTED; 746188Sbill u.u_r.r_val1 = p->p_pid; 747188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 748188Sbill return; 74936Sbill } 75036Sbill } 751188Sbill if (f==0) { 752188Sbill u.u_error = ECHILD; 753188Sbill return; 75436Sbill } 755188Sbill if (options&WNOHANG) { 756188Sbill u.u_r.r_val1 = 0; 757188Sbill return; 758188Sbill } 7598116Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 760188Sbill u.u_eosys = RESTARTSYS; 761188Sbill return; 762188Sbill } 763188Sbill sleep((caddr_t)u.u_procp, PWAIT); 764188Sbill goto loop; 76536Sbill } 76636Sbill 76736Sbill /* 76836Sbill * fork system call. 76936Sbill */ 77036Sbill fork() 77136Sbill { 77236Sbill 77336Sbill u.u_cdmap = zdmap; 77436Sbill u.u_csmap = zdmap; 77536Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 77636Sbill u.u_r.r_val2 = 0; 77736Sbill return; 77836Sbill } 77936Sbill fork1(0); 78036Sbill } 78136Sbill 78236Sbill fork1(isvfork) 78336Sbill { 78436Sbill register struct proc *p1, *p2; 7857488Skre #ifndef QUOTA 78636Sbill register a; 78736Sbill 78836Sbill a = 0; 7897488Skre #else 7907488Skre if (u.u_quota != NOQUOT && u.u_quota->q_plim && 7917488Skre u.u_quota->q_cnt >= u.u_quota->q_plim) { 7927488Skre u.u_error = EPROCLIM; 7937488Skre return; 7947488Skre } 7957488Skre #endif 79636Sbill p2 = NULL; 7974827Swnj for (p1 = proc; p1 < procNPROC; p1++) { 7987488Skre #ifdef QUOTA 7997488Skre if (p1->p_stat == NULL) { 8007488Skre p2 = p1; 8017488Skre break; 8027488Skre } 8037488Skre #else 80436Sbill if (p1->p_stat==NULL && p2==NULL) 80536Sbill p2 = p1; 80636Sbill else { 80736Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 80836Sbill a++; 80936Sbill } 8107488Skre #endif 81136Sbill } 81236Sbill /* 81336Sbill * Disallow if 81436Sbill * No processes at all; 81536Sbill * not su and too many procs owned; or 81636Sbill * not su and would take last slot. 81736Sbill */ 8182938Swnj if (p2==NULL) 8192938Swnj tablefull("proc"); 8207488Skre #ifdef QUOTA 8217488Skre if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { 8227488Skre #else 8232741Swnj if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 8247488Skre #endif 82536Sbill u.u_error = EAGAIN; 82636Sbill if (!isvfork) { 827132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 828132Sbill (void) vsexpand(0, &u.u_csmap, 1); 82936Sbill } 83036Sbill goto out; 83136Sbill } 83236Sbill p1 = u.u_procp; 8334827Swnj if (newproc(isvfork)) { 83436Sbill u.u_r.r_val1 = p1->p_pid; 83536Sbill u.u_r.r_val2 = 1; /* child */ 8368030Sroot u.u_start = time.tv_sec; 83736Sbill u.u_acflag = AFORK; 8387488Skre #ifdef QUOTA 8397488Skre u.u_qflags &= ~QUF_LOGIN; 8407488Skre #endif 84136Sbill return; 84236Sbill } 84336Sbill u.u_r.r_val1 = p2->p_pid; 84436Sbill 84536Sbill out: 84636Sbill u.u_r.r_val2 = 0; 84736Sbill } 84836Sbill 8497497Sroot spgrp(top, npgrp) 8507497Sroot register struct proc *top; 8517497Sroot { 8527497Sroot register struct proc *pp, *p; 8537497Sroot int f = 0; 8547497Sroot 8557497Sroot for (p = top; npgrp == -1 || u.u_uid == p->p_uid || 8567497Sroot !u.u_uid || inferior(p); p = pp) { 8577497Sroot if (npgrp == -1) { 8587497Sroot #define bit(a) (1<<(a-1)) 8597497Sroot p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 8607497Sroot } else 8617497Sroot p->p_pgrp = npgrp; 8627497Sroot f++; 8637497Sroot /* 8647497Sroot * Search for children. 8657497Sroot */ 8667497Sroot for (pp = proc; pp < procNPROC; pp++) 8677497Sroot if (pp->p_pptr == p) 8687497Sroot goto cont; 8697497Sroot /* 8707497Sroot * Search for siblings. 8717497Sroot */ 8727497Sroot for (; p != top; p = p->p_pptr) 8737497Sroot for (pp = p + 1; pp < procNPROC; pp++) 8747497Sroot if (pp->p_pptr == p->p_pptr) 8757497Sroot goto cont; 8767497Sroot break; 8777497Sroot cont: 8787497Sroot ; 8797497Sroot } 8807497Sroot return (f); 8817497Sroot } 8827497Sroot 88336Sbill /* 8847497Sroot * Is p an inferior of the current process? 88536Sbill */ 8867497Sroot inferior(p) 8877816Sroot register struct proc *p; 88836Sbill { 88936Sbill 8907497Sroot for (; p != u.u_procp; p = p->p_pptr) 8917497Sroot if (p->p_ppid == 0) 8927497Sroot return (0); 8937497Sroot return (1); 89436Sbill } 8957816Sroot 8967816Sroot struct proc * 8977816Sroot pfind(pid) 8987816Sroot int pid; 8997816Sroot { 9007816Sroot register struct proc *p; 9017816Sroot 9027816Sroot for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 9037816Sroot if (p->p_pid == pid) 9047816Sroot return (p); 9057816Sroot return ((struct proc *)0); 9067816Sroot } 9078099Sroot 9088099Sroot /* 9098099Sroot * Create a new process-- the internal version of 9108099Sroot * sys fork. 9118099Sroot * It returns 1 in the new process, 0 in the old. 9128099Sroot */ 9138099Sroot newproc(isvfork) 9148099Sroot int isvfork; 9158099Sroot { 9168099Sroot register struct proc *p; 9178099Sroot register struct proc *rpp, *rip; 9188099Sroot register int n; 9198099Sroot register struct file *fp; 9208099Sroot 9218099Sroot p = NULL; 9228099Sroot /* 9238099Sroot * First, just locate a slot for a process 9248099Sroot * and copy the useful info from this process into it. 9258099Sroot * The panic "cannot happen" because fork has already 9268099Sroot * checked for the existence of a slot. 9278099Sroot */ 9288099Sroot retry: 9298099Sroot mpid++; 9308099Sroot if (mpid >= 30000) { 9318099Sroot mpid = 0; 9328099Sroot goto retry; 9338099Sroot } 9348099Sroot for (rpp = proc; rpp < procNPROC; rpp++) { 9358099Sroot if (rpp->p_stat == NULL && p==NULL) 9368099Sroot p = rpp; 9378099Sroot if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) 9388099Sroot goto retry; 9398099Sroot } 9408099Sroot if ((rpp = p) == NULL) 9418099Sroot panic("no procs"); 9428099Sroot 9438099Sroot /* 9448099Sroot * Make a proc table entry for the new process. 9458099Sroot */ 9468099Sroot rip = u.u_procp; 9478099Sroot #ifdef QUOTA 9488099Sroot (rpp->p_quota = rip->p_quota)->q_cnt++; 9498099Sroot #endif 9508099Sroot rpp->p_stat = SIDL; 9518099Sroot timerclear(&rpp->p_realtimer.it_value); 9528099Sroot rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG)); 9538099Sroot if (isvfork) { 9548099Sroot rpp->p_flag |= SVFORK; 9558099Sroot rpp->p_ndx = rip->p_ndx; 9568099Sroot } else 9578099Sroot rpp->p_ndx = rpp - proc; 9588099Sroot rpp->p_uid = rip->p_uid; 9598099Sroot rpp->p_pgrp = rip->p_pgrp; 9608099Sroot rpp->p_nice = rip->p_nice; 9618099Sroot rpp->p_textp = isvfork ? 0 : rip->p_textp; 9628099Sroot rpp->p_pid = mpid; 9638099Sroot rpp->p_ppid = rip->p_pid; 9648099Sroot rpp->p_pptr = rip; 9658099Sroot rpp->p_osptr = rip->p_cptr; 9668099Sroot if (rip->p_cptr) 9678099Sroot rip->p_cptr->p_ysptr = rpp; 9688099Sroot rpp->p_ysptr = NULL; 9698099Sroot rpp->p_cptr = NULL; 9708099Sroot rip->p_cptr = rpp; 9718099Sroot rpp->p_time = 0; 9728099Sroot rpp->p_cpu = 0; 9738099Sroot rpp->p_siga0 = rip->p_siga0; 9748099Sroot rpp->p_siga1 = rip->p_siga1; 9758099Sroot /* take along any pending signals, like stops? */ 9768099Sroot if (isvfork) { 9778099Sroot rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; 9788099Sroot rpp->p_szpt = clrnd(ctopt(UPAGES)); 9798099Sroot forkstat.cntvfork++; 9808099Sroot forkstat.sizvfork += rip->p_dsize + rip->p_ssize; 9818099Sroot } else { 9828099Sroot rpp->p_tsize = rip->p_tsize; 9838099Sroot rpp->p_dsize = rip->p_dsize; 9848099Sroot rpp->p_ssize = rip->p_ssize; 9858099Sroot rpp->p_szpt = rip->p_szpt; 9868099Sroot forkstat.cntfork++; 9878099Sroot forkstat.sizfork += rip->p_dsize + rip->p_ssize; 9888099Sroot } 9898099Sroot rpp->p_rssize = 0; 9908099Sroot rpp->p_maxrss = rip->p_maxrss; 9918099Sroot rpp->p_wchan = 0; 9928099Sroot rpp->p_slptime = 0; 9938099Sroot rpp->p_pctcpu = 0; 9948099Sroot rpp->p_cpticks = 0; 9958099Sroot n = PIDHASH(rpp->p_pid); 9968099Sroot p->p_idhash = pidhash[n]; 9978099Sroot pidhash[n] = rpp - proc; 9988099Sroot multprog++; 9998099Sroot 10008099Sroot /* 10018099Sroot * Increase reference counts on shared objects. 10028099Sroot */ 10038099Sroot for (n = 0; n < NOFILE; n++) { 10048099Sroot fp = u.u_ofile[n]; 10058099Sroot if (fp == NULL) 10068099Sroot continue; 10078099Sroot fp->f_count++; 10088099Sroot if (u.u_pofile[n]&RDLOCK) 10098099Sroot fp->f_inode->i_rdlockc++; 10108099Sroot if (u.u_pofile[n]&WRLOCK) 10118099Sroot fp->f_inode->i_wrlockc++; 10128099Sroot } 10138099Sroot u.u_cdir->i_count++; 10148099Sroot if (u.u_rdir) 10158099Sroot u.u_rdir->i_count++; 10168099Sroot 10178099Sroot /* 10188099Sroot * Partially simulate the environment 10198099Sroot * of the new process so that when it is actually 10208099Sroot * created (by copying) it will look right. 10218099Sroot * This begins the section where we must prevent the parent 10228099Sroot * from being swapped. 10238099Sroot */ 10248099Sroot rip->p_flag |= SKEEP; 10258099Sroot if (procdup(rpp, isvfork)) 10268099Sroot return (1); 10278099Sroot 10288099Sroot /* 10298099Sroot * Make child runnable and add to run queue. 10308099Sroot */ 10318099Sroot (void) spl6(); 10328099Sroot rpp->p_stat = SRUN; 10338099Sroot setrq(rpp); 10348099Sroot (void) spl0(); 10358099Sroot 10368099Sroot /* 10378099Sroot * Cause child to take a non-local goto as soon as it runs. 10388099Sroot * On older systems this was done with SSWAP bit in proc 10398099Sroot * table; on VAX we use u.u_pcb.pcb_sswap so don't need 10408099Sroot * to do rpp->p_flag |= SSWAP. Actually do nothing here. 10418099Sroot */ 10428099Sroot /* rpp->p_flag |= SSWAP; */ 10438099Sroot 10448099Sroot /* 10458099Sroot * Now can be swapped. 10468099Sroot */ 10478099Sroot rip->p_flag &= ~SKEEP; 10488099Sroot 10498099Sroot /* 10508099Sroot * If vfork make chain from parent process to child 10518099Sroot * (where virtal memory is temporarily). Wait for 10528099Sroot * child to finish, steal virtual memory back, 10538099Sroot * and wakeup child to let it die. 10548099Sroot */ 10558099Sroot if (isvfork) { 10568099Sroot u.u_procp->p_xlink = rpp; 10578099Sroot u.u_procp->p_flag |= SNOVM; 10588099Sroot while (rpp->p_flag & SVFORK) 10598099Sroot sleep((caddr_t)rpp, PZERO - 1); 10608099Sroot if ((rpp->p_flag & SLOAD) == 0) 10618099Sroot panic("newproc vfork"); 10628099Sroot uaccess(rpp, Vfmap, &vfutl); 10638099Sroot u.u_procp->p_xlink = 0; 10648099Sroot vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 10658099Sroot u.u_procp->p_flag &= ~SNOVM; 10668099Sroot rpp->p_ndx = rpp - proc; 10678099Sroot rpp->p_flag |= SVFDONE; 10688099Sroot wakeup((caddr_t)rpp); 10698099Sroot } 10708099Sroot 10718099Sroot /* 10728099Sroot * 0 return means parent. 10738099Sroot */ 10748099Sroot return (0); 10758099Sroot } 1076