1*206Sbill /* kern_proc.c 3.6 10/14/12 */ 236Sbill 336Sbill #include "../h/param.h" 436Sbill #include "../h/systm.h" 536Sbill #include "../h/map.h" 636Sbill #include "../h/mtpr.h" 736Sbill #include "../h/dir.h" 836Sbill #include "../h/user.h" 936Sbill #include "../h/proc.h" 1036Sbill #include "../h/buf.h" 1136Sbill #include "../h/reg.h" 1236Sbill #include "../h/inode.h" 1336Sbill #include "../h/seg.h" 1436Sbill #include "../h/acct.h" 15188Sbill #include <wait.h> 1636Sbill #include "../h/pte.h" 1736Sbill #include "../h/vm.h" 1836Sbill #include "../h/text.h" 19188Sbill #include "../h/psl.h" 2036Sbill 2136Sbill /* 2236Sbill * exec system call, with and without environments. 2336Sbill */ 2436Sbill struct execa { 2536Sbill char *fname; 2636Sbill char **argp; 2736Sbill char **envp; 2836Sbill }; 2936Sbill 3036Sbill exec() 3136Sbill { 3236Sbill ((struct execa *)u.u_ap)->envp = NULL; 3336Sbill exece(); 3436Sbill } 3536Sbill 3636Sbill exece() 3736Sbill { 3836Sbill register nc; 3936Sbill register char *cp; 4036Sbill register struct buf *bp; 4136Sbill register struct execa *uap; 4236Sbill int na, ne, ucp, ap, c; 4336Sbill struct inode *ip; 4436Sbill swblk_t bno; 4536Sbill 4636Sbill if ((ip = namei(uchar, 0)) == NULL) 4736Sbill return; 4836Sbill bno = 0; 4936Sbill bp = 0; 5036Sbill if(access(ip, IEXEC)) 5136Sbill goto bad; 5236Sbill if((ip->i_mode & IFMT) != IFREG || 5336Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 5436Sbill u.u_error = EACCES; 5536Sbill goto bad; 5636Sbill } 5736Sbill /* 5836Sbill * Collect arguments on "file" in swap space. 5936Sbill */ 6036Sbill na = 0; 6136Sbill ne = 0; 6236Sbill nc = 0; 6336Sbill uap = (struct execa *)u.u_ap; 6436Sbill if ((bno = malloc(swapmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 6536Sbill swkill(u.u_procp, "exece"); 6636Sbill goto bad; 6736Sbill } 6836Sbill if (bno % CLSIZE) 6936Sbill panic("execa malloc"); 7036Sbill if (uap->argp) for (;;) { 7136Sbill ap = NULL; 7236Sbill if (uap->argp) { 7336Sbill ap = fuword((caddr_t)uap->argp); 7436Sbill uap->argp++; 7536Sbill } 7636Sbill if (ap==NULL && uap->envp) { 7736Sbill uap->argp = NULL; 7836Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 7936Sbill break; 8036Sbill uap->envp++; 8136Sbill ne++; 8236Sbill } 8336Sbill if (ap==NULL) 8436Sbill break; 8536Sbill na++; 8636Sbill if(ap == -1) 8736Sbill u.u_error = EFAULT; 8836Sbill do { 8936Sbill if (nc >= NCARGS-1) 9036Sbill u.u_error = E2BIG; 9136Sbill if ((c = fubyte((caddr_t)ap++)) < 0) 9236Sbill u.u_error = EFAULT; 9383Sbill if (u.u_error) { 9483Sbill if (bp) 9583Sbill brelse(bp); 9683Sbill bp = 0; 9736Sbill goto badarg; 9883Sbill } 9936Sbill if ((nc&BMASK) == 0) { 10036Sbill if (bp) 10136Sbill bdwrite(bp); 10236Sbill bp = getblk(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT))); 10336Sbill cp = bp->b_un.b_addr; 10436Sbill } 10536Sbill nc++; 10636Sbill *cp++ = c; 10736Sbill } while (c>0); 10836Sbill } 10936Sbill if (bp) 11036Sbill bdwrite(bp); 11136Sbill bp = 0; 11236Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 11336Sbill if (getxfile(ip, nc) || u.u_error) { 11436Sbill badarg: 11536Sbill for (c = 0; c < nc; c += BSIZE) 11636Sbill if (bp = baddr(swapdev, dbtofsb(swplo+bno)+(c>>BSHIFT))) { 11736Sbill bp->b_flags |= B_AGE; /* throw away */ 11836Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 11936Sbill brelse(bp); 12036Sbill bp = 0; 12136Sbill } 12236Sbill goto bad; 12336Sbill } 12436Sbill 12536Sbill /* 12636Sbill * copy back arglist 12736Sbill */ 12836Sbill 12936Sbill ucp = USRSTACK - nc - NBPW; 13036Sbill ap = ucp - na*NBPW - 3*NBPW; 13136Sbill u.u_ar0[SP] = ap; 132132Sbill (void) suword((caddr_t)ap, na-ne); 13336Sbill nc = 0; 13436Sbill for (;;) { 13536Sbill ap += NBPW; 13636Sbill if (na==ne) { 137132Sbill (void) suword((caddr_t)ap, 0); 13836Sbill ap += NBPW; 13936Sbill } 14036Sbill if (--na < 0) 14136Sbill break; 142132Sbill (void) suword((caddr_t)ap, ucp); 14336Sbill do { 14436Sbill if ((nc&BMASK) == 0) { 14536Sbill if (bp) 14636Sbill brelse(bp); 14736Sbill bp = bread(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT))); 14836Sbill bp->b_flags |= B_AGE; /* throw away */ 14936Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 15036Sbill cp = bp->b_un.b_addr; 15136Sbill } 152132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 15336Sbill nc++; 15436Sbill } while(c&0377); 15536Sbill } 156132Sbill (void) suword((caddr_t)ap, 0); 157132Sbill (void) suword((caddr_t)ucp, 0); 15836Sbill setregs(); 15936Sbill bad: 16036Sbill if (bp) 16136Sbill brelse(bp); 16236Sbill if (bno) 16336Sbill mfree(swapmap, ctod(clrnd((int) btoc(NCARGS))), bno); 16436Sbill iput(ip); 16536Sbill } 16636Sbill 16736Sbill /* 16836Sbill * Read in and set up memory for executed file. 16936Sbill * Zero return is normal; 17036Sbill * non-zero means only the text is being replaced 17136Sbill */ 17236Sbill getxfile(ip, nargc) 17336Sbill register struct inode *ip; 17436Sbill { 17536Sbill register sep; 17636Sbill register size_t ts, ds, ss; 17736Sbill register int overlay; 17836Sbill int pagi = 0; 17936Sbill 18036Sbill /* 18136Sbill * read in first few bytes 18236Sbill * of file for segment 18336Sbill * sizes: 18436Sbill * ux_mag = 407/410/411/405 18536Sbill * 407 is plain executable 18636Sbill * 410 is RO text 18736Sbill * 411 is separated ID 18836Sbill * 405 is overlaid text 18936Sbill * 412 is demand paged plain executable (NOT IMPLEMENTED) 19036Sbill * 413 is demand paged RO text 19136Sbill */ 19236Sbill 19336Sbill u.u_base = (caddr_t)&u.u_exdata; 19436Sbill u.u_count = sizeof(u.u_exdata); 19536Sbill u.u_offset = 0; 19636Sbill u.u_segflg = 1; 19736Sbill readi(ip); 19836Sbill u.u_segflg = 0; 19936Sbill if(u.u_error) 20036Sbill goto bad; 20136Sbill if (u.u_count!=0) { 20236Sbill u.u_error = ENOEXEC; 20336Sbill goto bad; 20436Sbill } 20536Sbill sep = 0; 20636Sbill overlay = 0; 20736Sbill switch (u.u_exdata.ux_mag) { 20836Sbill 20936Sbill case 0405: 21036Sbill overlay++; 21136Sbill break; 21236Sbill 21336Sbill case 0412: 21436Sbill u.u_error = ENOEXEC; 21536Sbill goto bad; 21636Sbill 21736Sbill case 0407: 21836Sbill u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 21936Sbill u.u_exdata.ux_tsize = 0; 22036Sbill break; 22136Sbill 22236Sbill case 0413: 22336Sbill pagi = SPAGI; 22436Sbill /* fall into ... */ 22536Sbill 22636Sbill case 0410: 22736Sbill if (u.u_exdata.ux_tsize == 0) { 22836Sbill u.u_error = ENOEXEC; 22936Sbill goto bad; 23036Sbill } 23136Sbill break; 23236Sbill 23336Sbill case 0411: 23436Sbill u.u_error = ENOEXEC; 23536Sbill goto bad; 23636Sbill 23736Sbill default: 23836Sbill u.u_error = ENOEXEC; 23936Sbill goto bad; 24036Sbill } 24136Sbill if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { 24236Sbill u.u_error = ETXTBSY; 24336Sbill goto bad; 24436Sbill } 24536Sbill 24636Sbill /* 24736Sbill * find text and data sizes 24836Sbill * try them out for possible 24936Sbill * exceed of max sizes 25036Sbill */ 25136Sbill 25236Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 25336Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 25436Sbill ss = clrnd(SSIZE + btoc(nargc)); 25536Sbill if (overlay) { 25636Sbill if ((u.u_procp->p_flag & SPAGI) || u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) { 25736Sbill u.u_error = ENOMEM; 25836Sbill goto bad; 25936Sbill } 26036Sbill ds = u.u_dsize; 26136Sbill ss = u.u_ssize; 26236Sbill sep = u.u_sep; 26336Sbill xfree(); 26436Sbill xalloc(ip, pagi); 26536Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 26636Sbill } else { 26736Sbill if (chksize(ts, ds, ss)) 26836Sbill goto bad; 26936Sbill u.u_cdmap = zdmap; 27036Sbill u.u_csmap = zdmap; 27136Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 27236Sbill goto bad; 27336Sbill 27436Sbill /* 27536Sbill * At this point, committed to the new image! 27636Sbill * Release virtual memory resources of old process, and 27736Sbill * initialize the virtual memory of the new process. 27836Sbill * If we resulted from vfork(), instead wakeup our 27936Sbill * parent who will set SVFDONE when he has taken back 28036Sbill * our resources. 28136Sbill */ 28236Sbill u.u_prof.pr_scale = 0; 28336Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 28436Sbill vrelvm(); 28536Sbill else { 28636Sbill u.u_procp->p_flag &= ~SVFORK; 28736Sbill u.u_procp->p_flag |= SKEEP; 28836Sbill wakeup((caddr_t)u.u_procp); 28936Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 29036Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 29136Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 29236Sbill } 29336Sbill u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM); 29436Sbill u.u_procp->p_flag |= pagi; 29536Sbill u.u_dmap = u.u_cdmap; 29636Sbill u.u_smap = u.u_csmap; 29736Sbill vgetvm(ts, ds, ss); 29836Sbill 29936Sbill if (pagi == 0) { 30036Sbill /* 30136Sbill * Read in data segment. 30236Sbill */ 30336Sbill u.u_base = (char *)ctob(ts); 30436Sbill u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; 30536Sbill u.u_count = u.u_exdata.ux_dsize; 30636Sbill readi(ip); 30736Sbill } 30836Sbill xalloc(ip, pagi); 30936Sbill if (pagi && u.u_procp->p_textp) 31036Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 31136Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 31236Sbill 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 31336Sbill 31436Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 31536Sbill mtpr(TBIA,1); 31636Sbill 31736Sbill /* 31836Sbill * set SUID/SGID protections, if no tracing 31936Sbill */ 32036Sbill if ((u.u_procp->p_flag&STRC)==0) { 32136Sbill if(ip->i_mode&ISUID) 32236Sbill if(u.u_uid != 0) { 32336Sbill u.u_uid = ip->i_uid; 32436Sbill u.u_procp->p_uid = ip->i_uid; 32536Sbill } 32636Sbill if(ip->i_mode&ISGID) 32736Sbill u.u_gid = ip->i_gid; 32836Sbill } else 329173Sbill psignal(u.u_procp, SIGTRAP); 33036Sbill } 33136Sbill u.u_tsize = ts; 33236Sbill u.u_dsize = ds; 33336Sbill u.u_ssize = ss; 33436Sbill u.u_sep = sep; 33536Sbill bad: 33636Sbill return(overlay); 33736Sbill } 33836Sbill 33936Sbill /* 34036Sbill * Clear registers on exec 34136Sbill */ 34236Sbill setregs() 34336Sbill { 344173Sbill register int (**rp)(); 34536Sbill register i; 346188Sbill long sigmask; 34736Sbill 348188Sbill for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG]; 349188Sbill sigmask <<= 1, rp++) { 350188Sbill switch (*rp) { 351188Sbill 352188Sbill case SIG_IGN: 353188Sbill case SIG_DFL: 354188Sbill case SIG_HOLD: 355188Sbill continue; 356188Sbill 357188Sbill default: 358188Sbill /* 359*206Sbill * Normal or deferring catch; revert to default. 360188Sbill */ 361*206Sbill (void) spl6(); 362*206Sbill *rp = SIG_DFL; 363188Sbill if ((int)*rp & 1) 364188Sbill u.u_procp->p_siga0 |= sigmask; 365188Sbill else 366188Sbill u.u_procp->p_siga1 &= ~sigmask; 367188Sbill if ((int)*rp & 2) 368188Sbill u.u_procp->p_siga1 |= sigmask; 369188Sbill else 370188Sbill u.u_procp->p_siga1 &= ~sigmask; 371*206Sbill (void) spl0(); 372188Sbill continue; 373188Sbill } 374188Sbill } 37536Sbill /* 37636Sbill for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 37736Sbill *rp++ = 0; 37836Sbill */ 37936Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 38036Sbill for(i=0; i<NOFILE; i++) { 38136Sbill if (u.u_pofile[i]&EXCLOSE) { 38236Sbill closef(u.u_ofile[i]); 38336Sbill u.u_ofile[i] = NULL; 384188Sbill u.u_pofile[i] &= ~EXCLOSE; 38536Sbill } 38636Sbill } 38736Sbill /* 38836Sbill * Remember file name for accounting. 38936Sbill */ 39036Sbill u.u_acflag &= ~AFORK; 39136Sbill bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ); 39236Sbill } 39336Sbill 39436Sbill /* 39536Sbill * exit system call: 39636Sbill * pass back caller's arg 39736Sbill */ 39836Sbill rexit() 39936Sbill { 40036Sbill register struct a { 40136Sbill int rval; 40236Sbill } *uap; 40336Sbill 40436Sbill uap = (struct a *)u.u_ap; 40536Sbill exit((uap->rval & 0377) << 8); 40636Sbill } 40736Sbill 40836Sbill /* 40936Sbill * Release resources. 41036Sbill * Save u. area for parent to look at. 41136Sbill * Enter zombie state. 41236Sbill * Wake up parent and init processes, 41336Sbill * and dispose of children. 41436Sbill */ 41536Sbill exit(rv) 41636Sbill { 41736Sbill register int i; 41836Sbill register struct proc *p, *q; 41936Sbill register struct file *f; 42036Sbill register int x; 42136Sbill 42236Sbill #ifdef PGINPROF 42336Sbill vmsizmon(); 42436Sbill #endif 42536Sbill p = u.u_procp; 42636Sbill p->p_flag &= ~(STRC|SULOCK); 42736Sbill p->p_flag |= SWEXIT; 42836Sbill p->p_clktim = 0; 429188Sbill (void) spl6(); 430188Sbill if ((int)SIG_IGN & 1) 431188Sbill p->p_siga0 = ~0; 432188Sbill else 433188Sbill p->p_siga0 = 0; 434188Sbill if ((int)SIG_IGN & 2) 435188Sbill p->p_siga1 = ~0; 436188Sbill else 437*206Sbill p->p_siga1 = 0; 438188Sbill (void) spl0(); 43936Sbill rate.v_pgin -= p->p_aveflt; 44036Sbill p->p_aveflt = 0; 44136Sbill for(i=0; i<NSIG; i++) 442173Sbill u.u_signal[i] = SIG_IGN; 44336Sbill /* 44436Sbill * Release virtual memory. If we resulted from 44536Sbill * a vfork(), instead give the resources back to 44636Sbill * the parent. 44736Sbill */ 44836Sbill if ((p->p_flag & SVFORK) == 0) 44936Sbill vrelvm(); 45036Sbill else { 45136Sbill p->p_flag &= ~SVFORK; 45236Sbill wakeup((caddr_t)p); 45336Sbill while ((p->p_flag & SVFDONE) == 0) 45436Sbill sleep((caddr_t)p, PZERO - 1); 45536Sbill p->p_flag &= ~SVFDONE; 45636Sbill } 45736Sbill for(i=0; i<NOFILE; i++) { 45836Sbill f = u.u_ofile[i]; 45936Sbill u.u_ofile[i] = NULL; 46036Sbill closef(f); 46136Sbill } 46236Sbill plock(u.u_cdir); 46336Sbill iput(u.u_cdir); 46436Sbill if (u.u_rdir) { 46536Sbill plock(u.u_rdir); 46636Sbill iput(u.u_rdir); 46736Sbill } 46836Sbill acct(); 46936Sbill vrelpt(u.u_procp); 47036Sbill vrelu(u.u_procp, 0); 47136Sbill multprog--; 47236Sbill spl7(); /* clock will get mad because of overlaying */ 47336Sbill p->p_stat = SZOMB; 47436Sbill i = PIDHASH(p->p_pid); 47536Sbill x = p - proc; 47636Sbill if (pidhash[i] == x) 47736Sbill pidhash[i] = p->p_idhash; 47836Sbill else { 47936Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 48036Sbill if (proc[i].p_idhash == x) { 48136Sbill proc[i].p_idhash = p->p_idhash; 48236Sbill goto done; 48336Sbill } 48436Sbill panic("exit"); 48536Sbill } 48636Sbill done: 48736Sbill ((struct xproc *)p)->xp_xstat = rv; /* overlay */ 48836Sbill ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ 48936Sbill vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); 49036Sbill for(q = &proc[0]; q < &proc[NPROC]; q++) 491188Sbill if(q->p_pptr == p) { 492188Sbill q->p_pptr = &proc[1]; 493188Sbill q->p_ppid = 1; 49436Sbill wakeup((caddr_t)&proc[1]); 495188Sbill /* 496188Sbill * Stopped or traced processes are killed 497188Sbill * since their existence means someone is screwing up. 498188Sbill */ 499188Sbill if (q->p_stat == SSTOP || q->p_flag&STRC) { 500188Sbill q->p_flag &= ~STRC; 501188Sbill psignal(q, SIGKILL); 502188Sbill } 50336Sbill } 504188Sbill wakeup((caddr_t)p->p_pptr); 505188Sbill psignal(p->p_pptr, SIGCHLD); 50636Sbill swtch(); 50736Sbill } 50836Sbill 50936Sbill wait() 51036Sbill { 511188Sbill struct vtimes vm; 512188Sbill struct vtimes *vp; 51336Sbill 514188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 515188Sbill wait1(0, (struct vtimes *)0); 516188Sbill return; 517188Sbill } 518188Sbill vp = (struct vtimes *)u.u_ar0[R1]; 519188Sbill wait1(u.u_ar0[R0], &vm); 520188Sbill if (u.u_error) 521188Sbill return; 522188Sbill (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); 52336Sbill } 52436Sbill 52536Sbill /* 52636Sbill * Wait system call. 52736Sbill * Search for a terminated (zombie) child, 52836Sbill * finally lay it to rest, and collect its status. 52936Sbill * Look also for stopped (traced) children, 53036Sbill * and pass back status from them. 53136Sbill */ 532188Sbill wait1(options, vp) 533188Sbill register options; 53436Sbill struct vtimes *vp; 53536Sbill { 53636Sbill register f; 53736Sbill register struct proc *p; 53836Sbill 53936Sbill f = 0; 54036Sbill loop: 54136Sbill for(p = &proc[0]; p < &proc[NPROC]; p++) 542188Sbill if(p->p_pptr == u.u_procp) { 54336Sbill f++; 54436Sbill if(p->p_stat == SZOMB) { 54536Sbill u.u_r.r_val1 = p->p_pid; 54636Sbill u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 54736Sbill ((struct xproc *)p)->xp_xstat = 0; 54836Sbill if (vp) 54936Sbill *vp = ((struct xproc *)p)->xp_vm; 55036Sbill vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); 55136Sbill ((struct xproc *)p)->xp_vm = zvms; 55236Sbill p->p_stat = NULL; 55336Sbill p->p_pid = 0; 55436Sbill p->p_ppid = 0; 555188Sbill p->p_pptr = 0; 55636Sbill p->p_sig = 0; 557188Sbill p->p_siga0 = 0; 558188Sbill p->p_siga1 = 0; 55936Sbill p->p_pgrp = 0; 56036Sbill p->p_flag = 0; 56136Sbill p->p_wchan = 0; 562188Sbill p->p_cursig = 0; 56336Sbill return; 56436Sbill } 565188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 566188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 567188Sbill p->p_flag |= SWTED; 568188Sbill u.u_r.r_val1 = p->p_pid; 569188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 570188Sbill return; 57136Sbill } 57236Sbill } 573188Sbill if (f==0) { 574188Sbill u.u_error = ECHILD; 575188Sbill return; 57636Sbill } 577188Sbill if (options&WNOHANG) { 578188Sbill u.u_r.r_val1 = 0; 579188Sbill return; 580188Sbill } 581*206Sbill /* 582188Sbill if (setjmp(u.u_qsav)) { 583188Sbill u.u_eosys = RESTARTSYS; 584188Sbill return; 585188Sbill } 586*206Sbill */ 587188Sbill sleep((caddr_t)u.u_procp, PWAIT); 588188Sbill goto loop; 58936Sbill } 59036Sbill 59136Sbill /* 59236Sbill * fork system call. 59336Sbill */ 59436Sbill fork() 59536Sbill { 59636Sbill 59736Sbill u.u_cdmap = zdmap; 59836Sbill u.u_csmap = zdmap; 59936Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 60036Sbill u.u_r.r_val2 = 0; 60136Sbill return; 60236Sbill } 60336Sbill fork1(0); 60436Sbill } 60536Sbill 60636Sbill fork1(isvfork) 60736Sbill { 60836Sbill register struct proc *p1, *p2; 60936Sbill register a; 61036Sbill 61136Sbill a = 0; 61236Sbill p2 = NULL; 61336Sbill for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { 61436Sbill if (p1->p_stat==NULL && p2==NULL) 61536Sbill p2 = p1; 61636Sbill else { 61736Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 61836Sbill a++; 61936Sbill } 62036Sbill } 62136Sbill /* 62236Sbill * Disallow if 62336Sbill * No processes at all; 62436Sbill * not su and too many procs owned; or 62536Sbill * not su and would take last slot. 62636Sbill */ 62736Sbill if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { 62836Sbill u.u_error = EAGAIN; 62936Sbill if (!isvfork) { 630132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 631132Sbill (void) vsexpand(0, &u.u_csmap, 1); 63236Sbill } 63336Sbill goto out; 63436Sbill } 63536Sbill p1 = u.u_procp; 63636Sbill if(newproc(isvfork)) { 63736Sbill u.u_r.r_val1 = p1->p_pid; 63836Sbill u.u_r.r_val2 = 1; /* child */ 63936Sbill u.u_start = time; 64036Sbill u.u_acflag = AFORK; 64136Sbill return; 64236Sbill } 64336Sbill u.u_r.r_val1 = p2->p_pid; 64436Sbill 64536Sbill out: 64636Sbill u.u_r.r_val2 = 0; 64736Sbill } 64836Sbill 64936Sbill /* 65036Sbill * break system call. 65136Sbill * -- bad planning: "break" is a dirty word in C. 65236Sbill */ 65336Sbill sbreak() 65436Sbill { 65536Sbill struct a { 65636Sbill char *nsiz; 65736Sbill }; 65836Sbill register int n, d; 65936Sbill 66036Sbill /* 66136Sbill * set n to new data size 66236Sbill * set d to new-old 66336Sbill */ 66436Sbill 66536Sbill n = btoc(((struct a *)u.u_ap)->nsiz); 66636Sbill if (!u.u_sep) 66736Sbill n -= ctos(u.u_tsize) * stoc(1); 66836Sbill if (n < 0) 66936Sbill n = 0; 67036Sbill d = clrnd(n - u.u_dsize); 67136Sbill if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) 67236Sbill return; 67336Sbill if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) 67436Sbill return; 67536Sbill expand(d, P0BR); 67636Sbill } 677