xref: /csrg-svn/sys/kern/kern_proc.c (revision 2329)
1 /*	kern_proc.c	4.4	02/01/81	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/map.h"
6 #include "../h/mtpr.h"
7 #include "../h/dir.h"
8 #include "../h/user.h"
9 #include "../h/proc.h"
10 #include "../h/buf.h"
11 #include "../h/reg.h"
12 #include "../h/inode.h"
13 #include "../h/seg.h"
14 #include "../h/acct.h"
15 #include "/usr/include/wait.h"
16 #include "../h/pte.h"
17 #include "../h/vm.h"
18 #include "../h/text.h"
19 #include "../h/psl.h"
20 #include "../h/vlimit.h"
21 #include "../h/file.h"
22 
23 /*
24  * exec system call, with and without environments.
25  */
26 struct execa {
27 	char	*fname;
28 	char	**argp;
29 	char	**envp;
30 };
31 
32 exec()
33 {
34 	((struct execa *)u.u_ap)->envp = NULL;
35 	exece();
36 }
37 
38 exece()
39 {
40 	register nc;
41 	register char *cp;
42 	register struct buf *bp;
43 	register struct execa *uap;
44 	int na, ne, ucp, ap, c;
45 	int indir, uid, gid;
46 	char *sharg;
47 	struct inode *ip;
48 	swblk_t bno;
49 	char cfname[DIRSIZ];
50 	char cfarg[SHSIZE];
51 
52 	if ((ip = namei(uchar, 0)) == NULL)
53 		return;
54 
55 	bno = 0;
56 	bp = 0;
57 	indir = 0;
58 	uid = u.u_uid;
59 	gid = u.u_gid;
60 
61 	if (ip->i_mode & ISUID)
62 		uid = ip->i_uid;
63 	if (ip->i_mode & ISGID)
64 		gid = ip->i_gid;
65 
66   again:
67 	if(access(ip, IEXEC))
68 		goto bad;
69 	if((ip->i_mode & IFMT) != IFREG ||
70 	   (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) {
71 		u.u_error = EACCES;
72 		goto bad;
73 	}
74 
75 	/*
76 	 * Read in first few bytes of file for segment sizes, ux_mag:
77 	 *	407 = plain executable
78 	 *	410 = RO text
79 	 *	413 = demand paged RO text
80 	 * Also an ASCII line beginning with #! is
81 	 * the file name of a ``shell'' and arguments may be prepended
82 	 * to the argument list if given here.
83 	 *
84 	 * SHELL NAMES ARE LIMITED IN LENGTH.
85 	 *
86 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
87 	 * THE ASCII LINE.
88 	 */
89 	u.u_base = (caddr_t)&u.u_exdata;
90 	u.u_count = sizeof(u.u_exdata);
91 	u.u_offset = 0;
92 	u.u_segflg = 1;
93 	readi(ip);
94 	u.u_segflg = 0;
95 	if(u.u_error)
96 		goto bad;
97 	if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A)
98 		&& u.u_exdata.ux_shell[0] != '#') {
99 		u.u_error = ENOEXEC;
100 		goto bad;
101 	}
102 	switch (u.u_exdata.ux_mag) {
103 
104 	case 0407:
105 		u.u_exdata.ux_dsize += u.u_exdata.ux_tsize;
106 		u.u_exdata.ux_tsize = 0;
107 		break;
108 
109 	case 0413:
110 	case 0410:
111 		if (u.u_exdata.ux_tsize == 0) {
112 			u.u_error = ENOEXEC;
113 			goto bad;
114 		}
115 		break;
116 
117 	default:
118 		if (u.u_exdata.ux_shell[0] != '#' ||
119 		    u.u_exdata.ux_shell[1] != '!' ||
120 		    indir) {
121 			u.u_error = ENOEXEC;
122 			goto bad;
123 		}
124 		cp = &u.u_exdata.ux_shell[2];		/* skip "#!" */
125 		while (cp < &u.u_exdata.ux_shell[SHSIZE]) {
126 			if (*cp == '\t')
127 				*cp = ' ';
128 			else if (*cp == '\n') {
129 				*cp = '\0';
130 				break;
131 			}
132 			cp++;
133 		}
134 		if (*cp != '\0') {
135 			u.u_error = ENOEXEC;
136 			goto bad;
137 		}
138 		cp = &u.u_exdata.ux_shell[2];
139 		while (*cp == ' ')
140 			cp++;
141 		u.u_dirp = cp;
142 		while (*cp && *cp != ' ')
143 			cp++;
144 		sharg = NULL;
145 		if (*cp) {
146 			*cp++ = '\0';
147 			while (*cp == ' ')
148 				cp++;
149 			if (*cp) {
150 				bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
151 				sharg = cfarg;
152 			}
153 		}
154 		bcopy((caddr_t)u.u_dbuf, (caddr_t)cfname, DIRSIZ);
155 		indir = 1;
156 		iput(ip);
157 		ip = namei(schar, 0);
158 		if (ip == NULL)
159 			return;
160 		goto again;
161 	}
162 
163 	/*
164 	 * Collect arguments on "file" in swap space.
165 	 */
166 	na = 0;
167 	ne = 0;
168 	nc = 0;
169 	uap = (struct execa *)u.u_ap;
170 	if ((bno = malloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) {
171 		swkill(u.u_procp, "exece");
172 		goto bad;
173 	}
174 	if (bno % CLSIZE)
175 		panic("execa malloc");
176 	if (uap->argp) for (;;) {
177 		ap = NULL;
178 		if (na == 1 && indir) {
179 			if (sharg == NULL)
180 				ap = (int)uap->fname;
181 		} else if (na == 2 && indir && sharg != NULL)
182 			ap = (int)uap->fname;
183 		else if (uap->argp) {
184 			ap = fuword((caddr_t)uap->argp);
185 			uap->argp++;
186 		}
187 		if (ap==NULL && uap->envp) {
188 			uap->argp = NULL;
189 			if ((ap = fuword((caddr_t)uap->envp)) == NULL)
190 				break;
191 			uap->envp++;
192 			ne++;
193 		}
194 		if (ap==NULL)
195 			break;
196 		na++;
197 		if(ap == -1)
198 			u.u_error = EFAULT;
199 		do {
200 			if (nc >= NCARGS-1)
201 				u.u_error = E2BIG;
202 			if (indir && na == 2 && sharg != NULL)
203 				c = *sharg++ & 0377;
204 			else if ((c = fubyte((caddr_t)ap++)) < 0)
205 				u.u_error = EFAULT;
206 			if (u.u_error) {
207 				if (bp)
208 					brelse(bp);
209 				bp = 0;
210 				goto badarg;
211 			}
212 			if ((nc&BMASK) == 0) {
213 				if (bp)
214 					bdwrite(bp);
215 				bp = getblk(argdev,
216 				    (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT)));
217 				cp = bp->b_un.b_addr;
218 			}
219 			nc++;
220 			*cp++ = c;
221 		} while (c>0);
222 	}
223 	if (bp)
224 		bdwrite(bp);
225 	bp = 0;
226 	nc = (nc + NBPW-1) & ~(NBPW-1);
227 	if (indir)
228 		bcopy((caddr_t)cfname, (caddr_t)u.u_dbuf, DIRSIZ);
229 	getxfile(ip, nc + (na+4)*NBPW, uid, gid);
230 	if (u.u_error) {
231 badarg:
232 		for (c = 0; c < nc; c += BSIZE)
233 			if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) {
234 				bp->b_flags |= B_AGE;		/* throw away */
235 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
236 				brelse(bp);
237 				bp = 0;
238 			}
239 		goto bad;
240 	}
241 
242 	/*
243 	 * copy back arglist
244 	 */
245 
246 	ucp = USRSTACK - nc - NBPW;
247 	ap = ucp - na*NBPW - 3*NBPW;
248 	u.u_ar0[SP] = ap;
249 	(void) suword((caddr_t)ap, na-ne);
250 	nc = 0;
251 	for (;;) {
252 		ap += NBPW;
253 		if (na==ne) {
254 			(void) suword((caddr_t)ap, 0);
255 			ap += NBPW;
256 		}
257 		if (--na < 0)
258 			break;
259 		(void) suword((caddr_t)ap, ucp);
260 		do {
261 			if ((nc&BMASK) == 0) {
262 				if (bp)
263 					brelse(bp);
264 				bp = bread(argdev,
265 				    (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT)));
266 				bp->b_flags |= B_AGE;		/* throw away */
267 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
268 				cp = bp->b_un.b_addr;
269 			}
270 			(void) subyte((caddr_t)ucp++, (c = *cp++));
271 			nc++;
272 		} while(c&0377);
273 	}
274 	(void) suword((caddr_t)ap, 0);
275 	(void) suword((caddr_t)ucp, 0);
276 	setregs();
277 bad:
278 	if (bp)
279 		brelse(bp);
280 	if (bno)
281 		mfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno);
282 	iput(ip);
283 }
284 
285 /*
286  * Read in and set up memory for executed file.
287  */
288 getxfile(ip, nargc, uid, gid)
289 register struct inode *ip;
290 {
291 	register size_t ts, ds, ss;
292 	int pagi;
293 
294 	if (u.u_exdata.ux_mag == 0413)
295 		pagi = SPAGI;
296 	else
297 		pagi = 0;
298 
299 	if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
300 		register struct file *fp;
301 
302 		for (fp = file; fp < &file[NFILE]; fp++)
303 			if (fp->f_inode == ip && (fp->f_flag&FWRITE)) {
304 				u.u_error = ETXTBSY;
305 				goto bad;
306 			}
307 	}
308 
309 	/*
310 	 * find text and data sizes
311 	 * try them out for possible
312 	 * exceed of max sizes
313 	 */
314 
315 	ts = clrnd(btoc(u.u_exdata.ux_tsize));
316 	ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize)));
317 	ss = clrnd(SSIZE + btoc(nargc));
318 	if (chksize(ts, ds, ss))
319 		goto bad;
320 	u.u_cdmap = zdmap;
321 	u.u_csmap = zdmap;
322 	if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL)
323 		goto bad;
324 
325 	/*
326 	 * At this point, committed to the new image!
327 	 * Release virtual memory resources of old process, and
328 	 * initialize the virtual memory of the new process.
329 	 * If we resulted from vfork(), instead wakeup our
330 	 * parent who will set SVFDONE when he has taken back
331 	 * our resources.
332 	 */
333 	u.u_prof.pr_scale = 0;
334 	if ((u.u_procp->p_flag & SVFORK) == 0)
335 		vrelvm();
336 	else {
337 		u.u_procp->p_flag &= ~SVFORK;
338 		u.u_procp->p_flag |= SKEEP;
339 		wakeup((caddr_t)u.u_procp);
340 		while ((u.u_procp->p_flag & SVFDONE) == 0)
341 			sleep((caddr_t)u.u_procp, PZERO - 1);
342 		u.u_procp->p_flag &= ~(SVFDONE|SKEEP);
343 	}
344 	u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM|SNUSIG);
345 	u.u_procp->p_flag |= pagi;
346 	u.u_dmap = u.u_cdmap;
347 	u.u_smap = u.u_csmap;
348 	vgetvm(ts, ds, ss);
349 
350 	if (pagi == 0) {
351 		/*
352 		 * Read in data segment.
353 		 */
354 		u.u_base = (char *)ctob(ts);
355 		u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize;
356 		u.u_count = u.u_exdata.ux_dsize;
357 		readi(ip);
358 	}
359 	xalloc(ip, pagi);
360 	if (pagi && u.u_procp->p_textp)
361 		vinifod((struct fpte *)dptopte(u.u_procp, 0),
362 		    PG_FTEXT, u.u_procp->p_textp->x_iptr,
363 		    1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize));
364 
365 	/* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
366 	mtpr(TBIA, 0);
367 
368 	/*
369 	 * set SUID/SGID protections, if no tracing
370 	 */
371 	if ((u.u_procp->p_flag&STRC)==0) {
372 #ifndef	MELB
373 		if(u.u_uid != 0)
374 #endif
375 		{
376 			u.u_uid = uid;
377 			u.u_procp->p_uid = uid;
378 		}
379 		u.u_gid = gid;
380 	} else
381 		psignal(u.u_procp, SIGTRAP);
382 	u.u_tsize = ts;
383 	u.u_dsize = ds;
384 	u.u_ssize = ss;
385 bad:
386 	return;
387 }
388 
389 /*
390  * Clear registers on exec
391  */
392 setregs()
393 {
394 	register int (**rp)();
395 	register i;
396 #ifdef UCBIPC
397 	register struct port *pt;
398 #endif UCBIPC
399 	long sigmask;
400 
401 	for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG];
402 	    sigmask <<= 1, rp++) {
403 		switch (*rp) {
404 
405 		case SIG_IGN:
406 		case SIG_DFL:
407 		case SIG_HOLD:
408 			continue;
409 
410 		default:
411 			/*
412 			 * Normal or deferring catch; revert to default.
413 			 */
414 			(void) spl6();
415 			*rp = SIG_DFL;
416 			if ((int)*rp & 1)
417 				u.u_procp->p_siga0 |= sigmask;
418 			else
419 				u.u_procp->p_siga1 &= ~sigmask;
420 			if ((int)*rp & 2)
421 				u.u_procp->p_siga1 |= sigmask;
422 			else
423 				u.u_procp->p_siga1 &= ~sigmask;
424 			(void) spl0();
425 			continue;
426 		}
427 	}
428 /*
429 	for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
430 		*rp++ = 0;
431 */
432 	u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */
433 	for(i=0; i<NOFILE; i++) {
434 		if (u.u_pofile[i]&EXCLOSE) {
435 #ifndef UCBIPC
436 			closef(u.u_ofile[i]);
437 			u.u_ofile[i] = NULL;
438 #else UCBIPC
439 			if (u.u_pofile[i]&ISPORT) {
440 				pt = u.u_oport[i];
441 				if (--pt->pt_count == 0)
442 					ptclose(pt);
443 				u.u_pofile[i] &= ~ISPORT;
444 				u.u_oport[i] = NULL;
445 			} else {
446 				closef(u.u_ofile[i]);
447 				u.u_ofile[i] = NULL;
448 			}
449 #endif UCBIPC
450 			u.u_pofile[i] &= ~EXCLOSE;
451 		}
452 	}
453 	/*
454 	 * Remember file name for accounting.
455 	 */
456 	u.u_acflag &= ~AFORK;
457 	bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ);
458 }
459 
460 /*
461  * exit system call:
462  * pass back caller's arg
463  */
464 rexit()
465 {
466 	register struct a {
467 		int	rval;
468 	} *uap;
469 
470 	uap = (struct a *)u.u_ap;
471 	exit((uap->rval & 0377) << 8);
472 }
473 
474 /*
475  * Release resources.
476  * Save u. area for parent to look at.
477  * Enter zombie state.
478  * Wake up parent and init processes,
479  * and dispose of children.
480  */
481 exit(rv)
482 {
483 	register int i;
484 	register struct proc *p, *q;
485 	register struct file *f;
486 #ifdef UCBIPC
487 	register struct port *pt;
488 #endif UCBIPC
489 	register int x;
490 
491 #ifdef PGINPROF
492 	vmsizmon();
493 #endif
494 	p = u.u_procp;
495 	p->p_flag &= ~(STRC|SULOCK);
496 	p->p_flag |= SWEXIT;
497 	p->p_clktim = 0;
498 	(void) spl6();
499 	if ((int)SIG_IGN & 1)
500 		p->p_siga0 = ~0;
501 	else
502 		p->p_siga0 = 0;
503 	if ((int)SIG_IGN & 2)
504 		p->p_siga1 = ~0;
505 	else
506 		p->p_siga1 = 0;
507 	(void) spl0();
508 	p->p_cpticks = 0;
509 	p->p_pctcpu = 0;
510 	for(i=0; i<NSIG; i++)
511 		u.u_signal[i] = SIG_IGN;
512 	/*
513 	 * Release virtual memory.  If we resulted from
514 	 * a vfork(), instead give the resources back to
515 	 * the parent.
516 	 */
517 	if ((p->p_flag & SVFORK) == 0)
518 		vrelvm();
519 	else {
520 		p->p_flag &= ~SVFORK;
521 		wakeup((caddr_t)p);
522 		while ((p->p_flag & SVFDONE) == 0)
523 			sleep((caddr_t)p, PZERO - 1);
524 		p->p_flag &= ~SVFDONE;
525 	}
526 	for(i=0; i<NOFILE; i++) {
527 #ifndef UCBIPC
528 		f = u.u_ofile[i];
529 		u.u_ofile[i] = NULL;
530 		closef(f);
531 #else UCBIPC
532 		if (u.u_pofile[i]&ISPORT) {
533 			pt = u.u_oport[i];
534 			if (--pt->pt_count == 0)
535 				ptclose(pt);
536 			u.u_oport[i] = NULL;
537 		} else {
538 			f = u.u_ofile[i];
539 			u.u_ofile[i] = NULL;
540 			closef(f);
541 		}
542 #endif UCBIPC
543 	}
544 	plock(u.u_cdir);
545 	iput(u.u_cdir);
546 	if (u.u_rdir) {
547 		plock(u.u_rdir);
548 		iput(u.u_rdir);
549 	}
550 	u.u_limit[LIM_FSIZE] = INFINITY;
551 	acct();
552 	vrelpt(u.u_procp);
553 	vrelu(u.u_procp, 0);
554 	multprog--;
555 /*	spl7();			/* clock will get mad because of overlaying */
556 	p->p_stat = SZOMB;
557 	noproc = 1;
558 	i = PIDHASH(p->p_pid);
559 	x = p - proc;
560 	if (pidhash[i] == x)
561 		pidhash[i] = p->p_idhash;
562 	else {
563 		for (i = pidhash[i]; i != 0; i = proc[i].p_idhash)
564 			if (proc[i].p_idhash == x) {
565 				proc[i].p_idhash = p->p_idhash;
566 				goto done;
567 			}
568 		panic("exit");
569 	}
570 	if (p->p_pid == 1)
571 		panic("init died");
572 done:
573 	((struct xproc *)p)->xp_xstat = rv;		/* overlay */
574 	((struct xproc *)p)->xp_vm = u.u_vm;		/* overlay */
575 	vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm);
576 	for(q = &proc[0]; q < &proc[NPROC]; q++)
577 		if(q->p_pptr == p) {
578 			q->p_pptr = &proc[1];
579 			q->p_ppid = 1;
580 			wakeup((caddr_t)&proc[1]);
581 			/*
582 			 * Traced processes are killed
583 			 * since their existence means someone is screwing up.
584 			 * Stopped processes are sent a hangup and a continue.
585 			 * This is designed to be ``safe'' for setuid
586 			 * processes since they must be willing to tolerate
587 			 * hangups anyways.
588 			 */
589 			if (q->p_flag&STRC) {
590 				q->p_flag &= ~STRC;
591 				psignal(q, SIGKILL);
592 			} else if (q->p_stat == SSTOP) {
593 				psignal(q, SIGHUP);
594 				psignal(q, SIGCONT);
595 			}
596 			/*
597 			 * Protect this process from future
598 			 * tty signals, clear TSTP/TTIN/TTOU if pending,
599 			 * and set SDETACH bit on procs.
600 			 */
601 			(void) spgrp(q, -1);
602 		}
603 	wakeup((caddr_t)p->p_pptr);
604 	psignal(p->p_pptr, SIGCHLD);
605 	swtch();
606 }
607 
608 wait()
609 {
610 	struct vtimes vm;
611 	struct vtimes *vp;
612 
613 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
614 		wait1(0, (struct vtimes *)0);
615 		return;
616 	}
617 	vp = (struct vtimes *)u.u_ar0[R1];
618 	wait1(u.u_ar0[R0], &vm);
619 	if (u.u_error)
620 		return;
621 	(void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes));
622 }
623 
624 /*
625  * Wait system call.
626  * Search for a terminated (zombie) child,
627  * finally lay it to rest, and collect its status.
628  * Look also for stopped (traced) children,
629  * and pass back status from them.
630  */
631 wait1(options, vp)
632 	register options;
633 	struct vtimes *vp;
634 {
635 	register f;
636 	register struct proc *p;
637 
638 	f = 0;
639 loop:
640 	for(p = &proc[0]; p < &proc[NPROC]; p++)
641 	if(p->p_pptr == u.u_procp) {
642 		f++;
643 		if(p->p_stat == SZOMB) {
644 			u.u_r.r_val1 = p->p_pid;
645 			u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat;
646 			((struct xproc *)p)->xp_xstat = 0;
647 			if (vp)
648 				*vp = ((struct xproc *)p)->xp_vm;
649 			vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm);
650 			((struct xproc *)p)->xp_vm = zvms;
651 			p->p_stat = NULL;
652 			p->p_pid = 0;
653 			p->p_ppid = 0;
654 			p->p_pptr = 0;
655 			p->p_sig = 0;
656 			p->p_siga0 = 0;
657 			p->p_siga1 = 0;
658 			p->p_pgrp = 0;
659 			p->p_flag = 0;
660 			p->p_wchan = 0;
661 			p->p_cursig = 0;
662 			return;
663 		}
664 		if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
665 		    (p->p_flag&STRC || options&WUNTRACED)) {
666 			p->p_flag |= SWTED;
667 			u.u_r.r_val1 = p->p_pid;
668 			u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
669 			return;
670 		}
671 	}
672 	if (f==0) {
673 		u.u_error = ECHILD;
674 		return;
675 	}
676 	if (options&WNOHANG) {
677 		u.u_r.r_val1 = 0;
678 		return;
679 	}
680 	if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) {
681 		u.u_eosys = RESTARTSYS;
682 		return;
683 	}
684 	sleep((caddr_t)u.u_procp, PWAIT);
685 	goto loop;
686 }
687 
688 /*
689  * fork system call.
690  */
691 fork()
692 {
693 
694 	u.u_cdmap = zdmap;
695 	u.u_csmap = zdmap;
696 	if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) {
697 		u.u_r.r_val2 = 0;
698 		return;
699 	}
700 	fork1(0);
701 }
702 
703 fork1(isvfork)
704 {
705 	register struct proc *p1, *p2;
706 	register a;
707 
708 	a = 0;
709 	p2 = NULL;
710 	for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) {
711 		if (p1->p_stat==NULL && p2==NULL)
712 			p2 = p1;
713 		else {
714 			if (p1->p_uid==u.u_uid && p1->p_stat!=NULL)
715 				a++;
716 		}
717 	}
718 	/*
719 	 * Disallow if
720 	 *  No processes at all;
721 	 *  not su and too many procs owned; or
722 	 *  not su and would take last slot.
723 	 */
724 	if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) {
725 		u.u_error = EAGAIN;
726 		if (!isvfork) {
727 			(void) vsexpand(0, &u.u_cdmap, 1);
728 			(void) vsexpand(0, &u.u_csmap, 1);
729 		}
730 		goto out;
731 	}
732 	p1 = u.u_procp;
733 	if(newproc(isvfork)) {
734 		u.u_r.r_val1 = p1->p_pid;
735 		u.u_r.r_val2 = 1;  /* child */
736 		u.u_start = time;
737 		u.u_acflag = AFORK;
738 		return;
739 	}
740 	u.u_r.r_val1 = p2->p_pid;
741 
742 out:
743 	u.u_r.r_val2 = 0;
744 }
745 
746 /*
747  * break system call.
748  *  -- bad planning: "break" is a dirty word in C.
749  */
750 sbreak()
751 {
752 	struct a {
753 		char	*nsiz;
754 	};
755 	register int n, d;
756 
757 	/*
758 	 * set n to new data size
759 	 * set d to new-old
760 	 */
761 
762 	n = btoc(((struct a *)u.u_ap)->nsiz);
763 	if (!u.u_sep)
764 		n -= ctos(u.u_tsize) * stoc(1);
765 	if (n < 0)
766 		n = 0;
767 	d = clrnd(n - u.u_dsize);
768 	if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) {
769 		u.u_error = ENOMEM;
770 		return;
771 	}
772 	if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize))
773 		return;
774 	if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0)
775 		return;
776 	expand(d, P0BR);
777 }
778