1*1182Sbill /* kern_proc.c 3.24 10/02/80 */ 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" 15215Sbill #include "/usr/include/wait.h" 1636Sbill #include "../h/pte.h" 1736Sbill #include "../h/vm.h" 1836Sbill #include "../h/text.h" 19188Sbill #include "../h/psl.h" 20879Sbill #include "../h/vlimit.h" 21890Sbill #include "../h/file.h" 2236Sbill 2336Sbill /* 2436Sbill * exec system call, with and without environments. 2536Sbill */ 2636Sbill struct execa { 2736Sbill char *fname; 2836Sbill char **argp; 2936Sbill char **envp; 3036Sbill }; 3136Sbill 3236Sbill exec() 3336Sbill { 3436Sbill ((struct execa *)u.u_ap)->envp = NULL; 3536Sbill exece(); 3636Sbill } 3736Sbill 3836Sbill exece() 3936Sbill { 4036Sbill register nc; 4136Sbill register char *cp; 4236Sbill register struct buf *bp; 4336Sbill register struct execa *uap; 4436Sbill int na, ne, ucp, ap, c; 4536Sbill struct inode *ip; 4636Sbill swblk_t bno; 4736Sbill 4836Sbill if ((ip = namei(uchar, 0)) == NULL) 4936Sbill return; 5036Sbill bno = 0; 5136Sbill bp = 0; 5236Sbill if(access(ip, IEXEC)) 5336Sbill goto bad; 5436Sbill if((ip->i_mode & IFMT) != IFREG || 5536Sbill (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 5636Sbill u.u_error = EACCES; 5736Sbill goto bad; 5836Sbill } 5936Sbill /* 6036Sbill * Collect arguments on "file" in swap space. 6136Sbill */ 6236Sbill na = 0; 6336Sbill ne = 0; 6436Sbill nc = 0; 6536Sbill uap = (struct execa *)u.u_ap; 66307Sbill if ((bno = malloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 6736Sbill swkill(u.u_procp, "exece"); 6836Sbill goto bad; 6936Sbill } 7036Sbill if (bno % CLSIZE) 7136Sbill panic("execa malloc"); 7236Sbill if (uap->argp) for (;;) { 7336Sbill ap = NULL; 7436Sbill if (uap->argp) { 7536Sbill ap = fuword((caddr_t)uap->argp); 7636Sbill uap->argp++; 7736Sbill } 7836Sbill if (ap==NULL && uap->envp) { 7936Sbill uap->argp = NULL; 8036Sbill if ((ap = fuword((caddr_t)uap->envp)) == NULL) 8136Sbill break; 8236Sbill uap->envp++; 8336Sbill ne++; 8436Sbill } 8536Sbill if (ap==NULL) 8636Sbill break; 8736Sbill na++; 8836Sbill if(ap == -1) 8936Sbill u.u_error = EFAULT; 9036Sbill do { 9136Sbill if (nc >= NCARGS-1) 9236Sbill u.u_error = E2BIG; 9336Sbill if ((c = fubyte((caddr_t)ap++)) < 0) 9436Sbill u.u_error = EFAULT; 9583Sbill if (u.u_error) { 9683Sbill if (bp) 9783Sbill brelse(bp); 9883Sbill bp = 0; 9936Sbill goto badarg; 10083Sbill } 10136Sbill if ((nc&BMASK) == 0) { 10236Sbill if (bp) 10336Sbill bdwrite(bp); 104307Sbill bp = getblk(argdev, 105307Sbill (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); 10636Sbill cp = bp->b_un.b_addr; 10736Sbill } 10836Sbill nc++; 10936Sbill *cp++ = c; 11036Sbill } while (c>0); 11136Sbill } 11236Sbill if (bp) 11336Sbill bdwrite(bp); 11436Sbill bp = 0; 11536Sbill nc = (nc + NBPW-1) & ~(NBPW-1); 116*1182Sbill getxfile(ip, nc + (na+4)*NBPW); 117912Sbill if (u.u_error) { 11836Sbill badarg: 11936Sbill for (c = 0; c < nc; c += BSIZE) 120307Sbill if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) { 12136Sbill bp->b_flags |= B_AGE; /* throw away */ 12236Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 12336Sbill brelse(bp); 12436Sbill bp = 0; 12536Sbill } 12636Sbill goto bad; 12736Sbill } 12836Sbill 12936Sbill /* 13036Sbill * copy back arglist 13136Sbill */ 13236Sbill 13336Sbill ucp = USRSTACK - nc - NBPW; 13436Sbill ap = ucp - na*NBPW - 3*NBPW; 13536Sbill u.u_ar0[SP] = ap; 136132Sbill (void) suword((caddr_t)ap, na-ne); 13736Sbill nc = 0; 13836Sbill for (;;) { 13936Sbill ap += NBPW; 14036Sbill if (na==ne) { 141132Sbill (void) suword((caddr_t)ap, 0); 14236Sbill ap += NBPW; 14336Sbill } 14436Sbill if (--na < 0) 14536Sbill break; 146132Sbill (void) suword((caddr_t)ap, ucp); 14736Sbill do { 14836Sbill if ((nc&BMASK) == 0) { 14936Sbill if (bp) 15036Sbill brelse(bp); 151307Sbill bp = bread(argdev, 152307Sbill (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); 15336Sbill bp->b_flags |= B_AGE; /* throw away */ 15436Sbill bp->b_flags &= ~B_DELWRI; /* cancel io */ 15536Sbill cp = bp->b_un.b_addr; 15636Sbill } 157132Sbill (void) subyte((caddr_t)ucp++, (c = *cp++)); 15836Sbill nc++; 15936Sbill } while(c&0377); 16036Sbill } 161132Sbill (void) suword((caddr_t)ap, 0); 162132Sbill (void) suword((caddr_t)ucp, 0); 16336Sbill setregs(); 16436Sbill bad: 16536Sbill if (bp) 16636Sbill brelse(bp); 16736Sbill if (bno) 168307Sbill mfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); 16936Sbill iput(ip); 17036Sbill } 17136Sbill 17236Sbill /* 17336Sbill * Read in and set up memory for executed file. 17436Sbill */ 17536Sbill getxfile(ip, nargc) 17636Sbill register struct inode *ip; 17736Sbill { 17836Sbill register size_t ts, ds, ss; 17936Sbill int pagi = 0; 18036Sbill 18136Sbill /* 18236Sbill * read in first few bytes 18336Sbill * of file for segment 18436Sbill * sizes: 185912Sbill * ux_mag = 407/410/413 18636Sbill * 407 is plain executable 18736Sbill * 410 is RO text 18836Sbill * 413 is demand paged RO text 18936Sbill */ 19036Sbill 19136Sbill u.u_base = (caddr_t)&u.u_exdata; 19236Sbill u.u_count = sizeof(u.u_exdata); 19336Sbill u.u_offset = 0; 19436Sbill u.u_segflg = 1; 19536Sbill readi(ip); 19636Sbill u.u_segflg = 0; 19736Sbill if(u.u_error) 19836Sbill goto bad; 19936Sbill if (u.u_count!=0) { 20036Sbill u.u_error = ENOEXEC; 20136Sbill goto bad; 20236Sbill } 20336Sbill switch (u.u_exdata.ux_mag) { 20436Sbill 20536Sbill case 0407: 20636Sbill u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 20736Sbill u.u_exdata.ux_tsize = 0; 20836Sbill break; 20936Sbill 21036Sbill case 0413: 21136Sbill pagi = SPAGI; 21236Sbill /* fall into ... */ 21336Sbill 21436Sbill case 0410: 21536Sbill if (u.u_exdata.ux_tsize == 0) { 21636Sbill u.u_error = ENOEXEC; 21736Sbill goto bad; 21836Sbill } 21936Sbill break; 22036Sbill 22136Sbill default: 22236Sbill u.u_error = ENOEXEC; 22336Sbill goto bad; 22436Sbill } 22536Sbill if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { 226890Sbill register struct file *fp; 227890Sbill 228890Sbill for (fp = file; fp < &file[NFILE]; fp++) 229890Sbill if (fp->f_inode == ip && (fp->f_flag&FWRITE)) { 230890Sbill u.u_error = ETXTBSY; 231890Sbill goto bad; 232890Sbill } 23336Sbill } 23436Sbill 23536Sbill /* 23636Sbill * find text and data sizes 23736Sbill * try them out for possible 23836Sbill * exceed of max sizes 23936Sbill */ 24036Sbill 24136Sbill ts = clrnd(btoc(u.u_exdata.ux_tsize)); 24236Sbill ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 24336Sbill ss = clrnd(SSIZE + btoc(nargc)); 244912Sbill if (chksize(ts, ds, ss)) 245912Sbill goto bad; 246912Sbill u.u_cdmap = zdmap; 247912Sbill u.u_csmap = zdmap; 248912Sbill if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 249912Sbill goto bad; 25036Sbill 251912Sbill /* 252912Sbill * At this point, committed to the new image! 253912Sbill * Release virtual memory resources of old process, and 254912Sbill * initialize the virtual memory of the new process. 255912Sbill * If we resulted from vfork(), instead wakeup our 256912Sbill * parent who will set SVFDONE when he has taken back 257912Sbill * our resources. 258912Sbill */ 259912Sbill u.u_prof.pr_scale = 0; 260912Sbill if ((u.u_procp->p_flag & SVFORK) == 0) 261912Sbill vrelvm(); 262912Sbill else { 263912Sbill u.u_procp->p_flag &= ~SVFORK; 264912Sbill u.u_procp->p_flag |= SKEEP; 265912Sbill wakeup((caddr_t)u.u_procp); 266912Sbill while ((u.u_procp->p_flag & SVFDONE) == 0) 267912Sbill sleep((caddr_t)u.u_procp, PZERO - 1); 268912Sbill u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 269912Sbill } 270912Sbill u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM|SNUSIG); 271912Sbill u.u_procp->p_flag |= pagi; 272912Sbill u.u_dmap = u.u_cdmap; 273912Sbill u.u_smap = u.u_csmap; 274912Sbill vgetvm(ts, ds, ss); 275912Sbill 276912Sbill if (pagi == 0) { 27736Sbill /* 278912Sbill * Read in data segment. 27936Sbill */ 280912Sbill u.u_base = (char *)ctob(ts); 281912Sbill u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; 282912Sbill u.u_count = u.u_exdata.ux_dsize; 283912Sbill readi(ip); 284912Sbill } 285912Sbill xalloc(ip, pagi); 286912Sbill if (pagi && u.u_procp->p_textp) 287912Sbill vinifod((struct fpte *)dptopte(u.u_procp, 0), 288912Sbill PG_FTEXT, u.u_procp->p_textp->x_iptr, 289912Sbill 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 29036Sbill 291912Sbill /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 292912Sbill mtpr(TBIA, 0); 29336Sbill 294912Sbill /* 295912Sbill * set SUID/SGID protections, if no tracing 296912Sbill */ 297912Sbill if ((u.u_procp->p_flag&STRC)==0) { 298912Sbill if(ip->i_mode&ISUID) 299912Sbill if(u.u_uid != 0) { 300912Sbill u.u_uid = ip->i_uid; 301912Sbill u.u_procp->p_uid = ip->i_uid; 302912Sbill } 303912Sbill if(ip->i_mode&ISGID) 304912Sbill u.u_gid = ip->i_gid; 305912Sbill } else 306912Sbill psignal(u.u_procp, SIGTRAP); 30736Sbill u.u_tsize = ts; 30836Sbill u.u_dsize = ds; 30936Sbill u.u_ssize = ss; 31036Sbill bad: 311912Sbill return; 31236Sbill } 31336Sbill 31436Sbill /* 31536Sbill * Clear registers on exec 31636Sbill */ 31736Sbill setregs() 31836Sbill { 319173Sbill register int (**rp)(); 32036Sbill register i; 321188Sbill long sigmask; 32236Sbill 323188Sbill for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG]; 324188Sbill sigmask <<= 1, rp++) { 325188Sbill switch (*rp) { 326188Sbill 327188Sbill case SIG_IGN: 328188Sbill case SIG_DFL: 329188Sbill case SIG_HOLD: 330188Sbill continue; 331188Sbill 332188Sbill default: 333188Sbill /* 334206Sbill * Normal or deferring catch; revert to default. 335188Sbill */ 336206Sbill (void) spl6(); 337206Sbill *rp = SIG_DFL; 338188Sbill if ((int)*rp & 1) 339188Sbill u.u_procp->p_siga0 |= sigmask; 340188Sbill else 341188Sbill u.u_procp->p_siga1 &= ~sigmask; 342188Sbill if ((int)*rp & 2) 343188Sbill u.u_procp->p_siga1 |= sigmask; 344188Sbill else 345188Sbill u.u_procp->p_siga1 &= ~sigmask; 346206Sbill (void) spl0(); 347188Sbill continue; 348188Sbill } 349188Sbill } 35036Sbill /* 35136Sbill for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 35236Sbill *rp++ = 0; 35336Sbill */ 35436Sbill u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 35536Sbill for(i=0; i<NOFILE; i++) { 35636Sbill if (u.u_pofile[i]&EXCLOSE) { 35736Sbill closef(u.u_ofile[i]); 35836Sbill u.u_ofile[i] = NULL; 359188Sbill u.u_pofile[i] &= ~EXCLOSE; 36036Sbill } 36136Sbill } 36236Sbill /* 36336Sbill * Remember file name for accounting. 36436Sbill */ 36536Sbill u.u_acflag &= ~AFORK; 36636Sbill bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ); 36736Sbill } 36836Sbill 36936Sbill /* 37036Sbill * exit system call: 37136Sbill * pass back caller's arg 37236Sbill */ 37336Sbill rexit() 37436Sbill { 37536Sbill register struct a { 37636Sbill int rval; 37736Sbill } *uap; 37836Sbill 37936Sbill uap = (struct a *)u.u_ap; 38036Sbill exit((uap->rval & 0377) << 8); 38136Sbill } 38236Sbill 38336Sbill /* 38436Sbill * Release resources. 38536Sbill * Save u. area for parent to look at. 38636Sbill * Enter zombie state. 38736Sbill * Wake up parent and init processes, 38836Sbill * and dispose of children. 38936Sbill */ 39036Sbill exit(rv) 39136Sbill { 39236Sbill register int i; 39336Sbill register struct proc *p, *q; 39436Sbill register struct file *f; 39536Sbill register int x; 39636Sbill 39736Sbill #ifdef PGINPROF 39836Sbill vmsizmon(); 39936Sbill #endif 40036Sbill p = u.u_procp; 40136Sbill p->p_flag &= ~(STRC|SULOCK); 40236Sbill p->p_flag |= SWEXIT; 40336Sbill p->p_clktim = 0; 404188Sbill (void) spl6(); 405188Sbill if ((int)SIG_IGN & 1) 406188Sbill p->p_siga0 = ~0; 407188Sbill else 408188Sbill p->p_siga0 = 0; 409188Sbill if ((int)SIG_IGN & 2) 410188Sbill p->p_siga1 = ~0; 411188Sbill else 412206Sbill p->p_siga1 = 0; 413188Sbill (void) spl0(); 41436Sbill p->p_aveflt = 0; 41536Sbill for(i=0; i<NSIG; i++) 416173Sbill u.u_signal[i] = SIG_IGN; 41736Sbill /* 41836Sbill * Release virtual memory. If we resulted from 41936Sbill * a vfork(), instead give the resources back to 42036Sbill * the parent. 42136Sbill */ 42236Sbill if ((p->p_flag & SVFORK) == 0) 42336Sbill vrelvm(); 42436Sbill else { 42536Sbill p->p_flag &= ~SVFORK; 42636Sbill wakeup((caddr_t)p); 42736Sbill while ((p->p_flag & SVFDONE) == 0) 42836Sbill sleep((caddr_t)p, PZERO - 1); 42936Sbill p->p_flag &= ~SVFDONE; 43036Sbill } 43136Sbill for(i=0; i<NOFILE; i++) { 43236Sbill f = u.u_ofile[i]; 43336Sbill u.u_ofile[i] = NULL; 43436Sbill closef(f); 43536Sbill } 43636Sbill plock(u.u_cdir); 43736Sbill iput(u.u_cdir); 43836Sbill if (u.u_rdir) { 43936Sbill plock(u.u_rdir); 44036Sbill iput(u.u_rdir); 44136Sbill } 442363Sbill u.u_limit[LIM_FSIZE] = INFINITY; 44336Sbill acct(); 44436Sbill vrelpt(u.u_procp); 44536Sbill vrelu(u.u_procp, 0); 44636Sbill multprog--; 447307Sbill /* spl7(); /* clock will get mad because of overlaying */ 448931Sbill p->p_stat = SZOMB; 449307Sbill noproc = 1; 45036Sbill i = PIDHASH(p->p_pid); 45136Sbill x = p - proc; 45236Sbill if (pidhash[i] == x) 45336Sbill pidhash[i] = p->p_idhash; 45436Sbill else { 45536Sbill for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 45636Sbill if (proc[i].p_idhash == x) { 45736Sbill proc[i].p_idhash = p->p_idhash; 45836Sbill goto done; 45936Sbill } 46036Sbill panic("exit"); 46136Sbill } 46236Sbill done: 46336Sbill ((struct xproc *)p)->xp_xstat = rv; /* overlay */ 46436Sbill ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ 46536Sbill vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); 46636Sbill for(q = &proc[0]; q < &proc[NPROC]; q++) 467188Sbill if(q->p_pptr == p) { 468188Sbill q->p_pptr = &proc[1]; 469188Sbill q->p_ppid = 1; 47036Sbill wakeup((caddr_t)&proc[1]); 471188Sbill /* 472212Sbill * Traced processes are killed 473188Sbill * since their existence means someone is screwing up. 474354Sbill * Stopped processes are sent a hangup and a continue. 475212Sbill * This is designed to be ``safe'' for setuid 476212Sbill * processes since they must be willing to tolerate 477212Sbill * hangups anyways. 478188Sbill */ 479212Sbill if (q->p_flag&STRC) { 480188Sbill q->p_flag &= ~STRC; 481188Sbill psignal(q, SIGKILL); 482212Sbill } else if (q->p_stat == SSTOP) { 483212Sbill psignal(q, SIGHUP); 484212Sbill psignal(q, SIGCONT); 485188Sbill } 486215Sbill /* 487215Sbill * Protect this process from future 488354Sbill * tty signals, clear TSTP/TTIN/TTOU if pending, 489354Sbill * and set SDETACH bit on procs. 490215Sbill */ 491307Sbill spgrp(q, -1); 49236Sbill } 493188Sbill wakeup((caddr_t)p->p_pptr); 494188Sbill psignal(p->p_pptr, SIGCHLD); 49536Sbill swtch(); 49636Sbill } 49736Sbill 49836Sbill wait() 49936Sbill { 500188Sbill struct vtimes vm; 501188Sbill struct vtimes *vp; 50236Sbill 503188Sbill if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 504188Sbill wait1(0, (struct vtimes *)0); 505188Sbill return; 506188Sbill } 507188Sbill vp = (struct vtimes *)u.u_ar0[R1]; 508188Sbill wait1(u.u_ar0[R0], &vm); 509188Sbill if (u.u_error) 510188Sbill return; 511188Sbill (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); 51236Sbill } 51336Sbill 51436Sbill /* 51536Sbill * Wait system call. 51636Sbill * Search for a terminated (zombie) child, 51736Sbill * finally lay it to rest, and collect its status. 51836Sbill * Look also for stopped (traced) children, 51936Sbill * and pass back status from them. 52036Sbill */ 521188Sbill wait1(options, vp) 522188Sbill register options; 52336Sbill struct vtimes *vp; 52436Sbill { 52536Sbill register f; 52636Sbill register struct proc *p; 52736Sbill 52836Sbill f = 0; 52936Sbill loop: 53036Sbill for(p = &proc[0]; p < &proc[NPROC]; p++) 531188Sbill if(p->p_pptr == u.u_procp) { 53236Sbill f++; 53336Sbill if(p->p_stat == SZOMB) { 53436Sbill u.u_r.r_val1 = p->p_pid; 53536Sbill u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 53636Sbill ((struct xproc *)p)->xp_xstat = 0; 53736Sbill if (vp) 53836Sbill *vp = ((struct xproc *)p)->xp_vm; 53936Sbill vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); 54036Sbill ((struct xproc *)p)->xp_vm = zvms; 54136Sbill p->p_stat = NULL; 54236Sbill p->p_pid = 0; 54336Sbill p->p_ppid = 0; 544188Sbill p->p_pptr = 0; 54536Sbill p->p_sig = 0; 546188Sbill p->p_siga0 = 0; 547188Sbill p->p_siga1 = 0; 54836Sbill p->p_pgrp = 0; 54936Sbill p->p_flag = 0; 55036Sbill p->p_wchan = 0; 551188Sbill p->p_cursig = 0; 55236Sbill return; 55336Sbill } 554188Sbill if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 555188Sbill (p->p_flag&STRC || options&WUNTRACED)) { 556188Sbill p->p_flag |= SWTED; 557188Sbill u.u_r.r_val1 = p->p_pid; 558188Sbill u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 559188Sbill return; 56036Sbill } 56136Sbill } 562188Sbill if (f==0) { 563188Sbill u.u_error = ECHILD; 564188Sbill return; 56536Sbill } 566188Sbill if (options&WNOHANG) { 567188Sbill u.u_r.r_val1 = 0; 568188Sbill return; 569188Sbill } 570912Sbill if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 571188Sbill u.u_eosys = RESTARTSYS; 572188Sbill return; 573188Sbill } 574188Sbill sleep((caddr_t)u.u_procp, PWAIT); 575188Sbill goto loop; 57636Sbill } 57736Sbill 57836Sbill /* 57936Sbill * fork system call. 58036Sbill */ 58136Sbill fork() 58236Sbill { 58336Sbill 58436Sbill u.u_cdmap = zdmap; 58536Sbill u.u_csmap = zdmap; 58636Sbill if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 58736Sbill u.u_r.r_val2 = 0; 58836Sbill return; 58936Sbill } 59036Sbill fork1(0); 59136Sbill } 59236Sbill 59336Sbill fork1(isvfork) 59436Sbill { 59536Sbill register struct proc *p1, *p2; 59636Sbill register a; 59736Sbill 59836Sbill a = 0; 59936Sbill p2 = NULL; 60036Sbill for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { 60136Sbill if (p1->p_stat==NULL && p2==NULL) 60236Sbill p2 = p1; 60336Sbill else { 60436Sbill if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 60536Sbill a++; 60636Sbill } 60736Sbill } 60836Sbill /* 60936Sbill * Disallow if 61036Sbill * No processes at all; 61136Sbill * not su and too many procs owned; or 61236Sbill * not su and would take last slot. 61336Sbill */ 61436Sbill if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { 61536Sbill u.u_error = EAGAIN; 61636Sbill if (!isvfork) { 617132Sbill (void) vsexpand(0, &u.u_cdmap, 1); 618132Sbill (void) vsexpand(0, &u.u_csmap, 1); 61936Sbill } 62036Sbill goto out; 62136Sbill } 62236Sbill p1 = u.u_procp; 62336Sbill if(newproc(isvfork)) { 62436Sbill u.u_r.r_val1 = p1->p_pid; 62536Sbill u.u_r.r_val2 = 1; /* child */ 62636Sbill u.u_start = time; 62736Sbill u.u_acflag = AFORK; 62836Sbill return; 62936Sbill } 63036Sbill u.u_r.r_val1 = p2->p_pid; 63136Sbill 63236Sbill out: 63336Sbill u.u_r.r_val2 = 0; 63436Sbill } 63536Sbill 63636Sbill /* 63736Sbill * break system call. 63836Sbill * -- bad planning: "break" is a dirty word in C. 63936Sbill */ 64036Sbill sbreak() 64136Sbill { 64236Sbill struct a { 64336Sbill char *nsiz; 64436Sbill }; 64536Sbill register int n, d; 64636Sbill 64736Sbill /* 64836Sbill * set n to new data size 64936Sbill * set d to new-old 65036Sbill */ 65136Sbill 65236Sbill n = btoc(((struct a *)u.u_ap)->nsiz); 65336Sbill if (!u.u_sep) 65436Sbill n -= ctos(u.u_tsize) * stoc(1); 65536Sbill if (n < 0) 65636Sbill n = 0; 65736Sbill d = clrnd(n - u.u_dsize); 658368Sbill if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) { 659363Sbill u.u_error = ENOMEM; 660363Sbill return; 661363Sbill } 66236Sbill if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) 66336Sbill return; 66436Sbill if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) 66536Sbill return; 66636Sbill expand(d, P0BR); 66736Sbill } 668