xref: /original-bsd/sys/kern/kern_proc.c (revision 3708840b)
1 /*	kern_proc.c	4.63	83/05/21	*/
2 
3 #include "../machine/reg.h"
4 #include "../machine/pte.h"
5 #include "../machine/psl.h"
6 
7 #include "../h/param.h"
8 #include "../h/systm.h"
9 #include "../h/map.h"
10 #include "../h/dir.h"
11 #include "../h/user.h"
12 #include "../h/kernel.h"
13 #include "../h/proc.h"
14 #include "../h/buf.h"
15 #include "../h/inode.h"
16 #include "../h/seg.h"
17 #include "../h/acct.h"
18 #include "../h/wait.h"
19 #include "../h/vm.h"
20 #include "../h/text.h"
21 #include "../h/file.h"
22 #include "../h/quota.h"
23 #include "../h/descrip.h"
24 #include "../h/uio.h"
25 #include "../h/mbuf.h"
26 #include "../h/nami.h"
27 
28 gethostid()
29 {
30 
31 	u.u_r.r_val1 = hostid;
32 }
33 
34 sethostid()
35 {
36 	struct a {
37 		int	hostid;
38 	} *uap = (struct a *)u.u_ap;
39 
40 	if (suser())
41 		hostid = uap->hostid;
42 }
43 
44 gethostname()
45 {
46 	register struct a {
47 		char	*hostname;
48 		int	len;
49 	} *uap = (struct a *)u.u_ap;
50 	register u_int len;
51 
52 	len = uap->len;
53 	if (len > hostnamelen + 1)
54 		len = hostnamelen + 1;
55 	u.u_error = copyout((caddr_t)hostname, (caddr_t)uap->hostname, len);
56 }
57 
58 sethostname()
59 {
60 	register struct a {
61 		char	*hostname;
62 		u_int	len;
63 	} *uap = (struct a *)u.u_ap;
64 
65 	if (!suser())
66 		return;
67 	if (uap->len > sizeof (hostname) - 1) {
68 		u.u_error = EINVAL;
69 		return;
70 	}
71 	hostnamelen = uap->len;
72 	u.u_error = copyin((caddr_t)uap->hostname, hostname, uap->len);
73 	hostname[hostnamelen] = 0;
74 }
75 
76 /*
77  * exec system call, with and without environments.
78  */
79 struct execa {
80 	char	*fname;
81 	char	**argp;
82 	char	**envp;
83 };
84 
85 execv()
86 {
87 	((struct execa *)u.u_ap)->envp = NULL;
88 	execve();
89 }
90 
91 execve()
92 {
93 	register nc;
94 	register char *cp;
95 	register struct buf *bp;
96 	register struct execa *uap;
97 	int na, ne, ucp, ap, c;
98 	int indir, uid, gid;
99 	char *sharg;
100 	struct inode *ip;
101 	swblk_t bno;
102 	char cfname[MAXCOMLEN + 1];
103 	char cfarg[SHSIZE];
104 	int resid;
105 
106 	if ((ip = namei(uchar, LOOKUP, 1)) == NULL)
107 		return;
108 	bno = 0;
109 	bp = 0;
110 	indir = 0;
111 	uid = u.u_uid;
112 	gid = u.u_gid;
113 	if (ip->i_mode & ISUID)
114 		uid = ip->i_uid;
115 	if (ip->i_mode & ISGID)
116 		gid = ip->i_gid;
117 
118   again:
119 	if (access(ip, IEXEC))
120 		goto bad;
121 	if ((u.u_procp->p_flag&STRC) && access(ip, IREAD))
122 		goto bad;
123 	if ((ip->i_mode & IFMT) != IFREG ||
124 	   (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) {
125 		u.u_error = EACCES;
126 		goto bad;
127 	}
128 
129 	/*
130 	 * Read in first few bytes of file for segment sizes, ux_mag:
131 	 *	407 = plain executable
132 	 *	410 = RO text
133 	 *	413 = demand paged RO text
134 	 * Also an ASCII line beginning with #! is
135 	 * the file name of a ``shell'' and arguments may be prepended
136 	 * to the argument list if given here.
137 	 *
138 	 * SHELL NAMES ARE LIMITED IN LENGTH.
139 	 *
140 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
141 	 * THE ASCII LINE.
142 	 */
143 	u.u_exdata.ux_shell[0] = 0;	/* for zero length files */
144 	u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata),
145 	    0, 1, &resid);
146 	if (u.u_error)
147 		goto bad;
148 	u.u_count = resid;
149 #ifndef lint
150 	if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) &&
151 	    u.u_exdata.ux_shell[0] != '#') {
152 		u.u_error = ENOEXEC;
153 		goto bad;
154 	}
155 #endif
156 	switch (u.u_exdata.ux_mag) {
157 
158 	case 0407:
159 		u.u_exdata.ux_dsize += u.u_exdata.ux_tsize;
160 		u.u_exdata.ux_tsize = 0;
161 		break;
162 
163 	case 0413:
164 	case 0410:
165 		if (u.u_exdata.ux_tsize == 0) {
166 			u.u_error = ENOEXEC;
167 			goto bad;
168 		}
169 		break;
170 
171 	default:
172 		if (u.u_exdata.ux_shell[0] != '#' ||
173 		    u.u_exdata.ux_shell[1] != '!' ||
174 		    indir) {
175 			u.u_error = ENOEXEC;
176 			goto bad;
177 		}
178 		cp = &u.u_exdata.ux_shell[2];		/* skip "#!" */
179 		while (cp < &u.u_exdata.ux_shell[SHSIZE]) {
180 			if (*cp == '\t')
181 				*cp = ' ';
182 			else if (*cp == '\n') {
183 				*cp = '\0';
184 				break;
185 			}
186 			cp++;
187 		}
188 		if (*cp != '\0') {
189 			u.u_error = ENOEXEC;
190 			goto bad;
191 		}
192 		cp = &u.u_exdata.ux_shell[2];
193 		while (*cp == ' ')
194 			cp++;
195 		u.u_dirp = cp;
196 		while (*cp && *cp != ' ')
197 			cp++;
198 		sharg = NULL;
199 		if (*cp) {
200 			*cp++ = '\0';
201 			while (*cp == ' ')
202 				cp++;
203 			if (*cp) {
204 				bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
205 				sharg = cfarg;
206 			}
207 		}
208 		if (u.u_dent.d_namlen > MAXCOMLEN)
209 			u.u_dent.d_namlen = MAXCOMLEN;
210 		bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname,
211 		    (unsigned)(u.u_dent.d_namlen + 1));
212 		cfname[MAXCOMLEN] = 0;
213 		indir = 1;
214 		iput(ip);
215 		ip = namei(schar, LOOKUP, 1);
216 		if (ip == NULL)
217 			return;
218 		goto again;
219 	}
220 
221 	/*
222 	 * Collect arguments on "file" in swap space.
223 	 */
224 	na = 0;
225 	ne = 0;
226 	nc = 0;
227 	uap = (struct execa *)u.u_ap;
228 	if ((bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))))) == 0) {
229 		swkill(u.u_procp, "exece");
230 		goto bad;
231 	}
232 	if (bno % CLSIZE)
233 		panic("execa rmalloc");
234 	if (uap->argp) for (;;) {
235 		ap = NULL;
236 		if (indir && (na == 1 || na == 2 && sharg))
237 			ap = (int)uap->fname;
238 		else if (uap->argp) {
239 			ap = fuword((caddr_t)uap->argp);
240 			uap->argp++;
241 		}
242 		if (ap==NULL && uap->envp) {
243 			uap->argp = NULL;
244 			if ((ap = fuword((caddr_t)uap->envp)) == NULL)
245 				break;
246 			uap->envp++;
247 			ne++;
248 		}
249 		if (ap == NULL)
250 			break;
251 		na++;
252 		if (ap == -1)
253 			u.u_error = EFAULT;
254 		do {
255 			if (nc >= NCARGS-1)
256 				u.u_error = E2BIG;
257 			if (indir && na == 2 && sharg != NULL)
258 				c = *sharg++ & 0377;
259 			else if ((c = fubyte((caddr_t)ap++)) < 0)
260 				u.u_error = EFAULT;
261 			if (u.u_error) {
262 				if (bp)
263 					brelse(bp);
264 				bp = 0;
265 				goto badarg;
266 			}
267 			if (nc % (CLSIZE*NBPG) == 0) {
268 				if (bp)
269 					bdwrite(bp);
270 				bp = getblk(argdev, bno + ctod(nc / NBPG),
271 				    CLSIZE*NBPG);
272 				cp = bp->b_un.b_addr;
273 			}
274 			nc++;
275 			*cp++ = c;
276 		} while (c > 0);
277 	}
278 	if (bp)
279 		bdwrite(bp);
280 	bp = 0;
281 	nc = (nc + NBPW-1) & ~(NBPW-1);
282 	if (indir) {
283 		u.u_dent.d_namlen = strlen(cfname);
284 		bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name,
285 		    (unsigned)(u.u_dent.d_namlen + 1));
286 	}
287 	getxfile(ip, nc + (na+4)*NBPW, uid, gid);
288 	if (u.u_error) {
289 badarg:
290 		for (c = 0; c < nc; c += CLSIZE*NBPG) {
291 			bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG);
292 			if (bp) {
293 				bp->b_flags |= B_AGE;		/* throw away */
294 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
295 				brelse(bp);
296 				bp = 0;
297 			}
298 		}
299 		goto bad;
300 	}
301 
302 	/*
303 	 * copy back arglist
304 	 */
305 	ucp = USRSTACK - nc - NBPW;
306 	ap = ucp - na*NBPW - 3*NBPW;
307 	u.u_ar0[SP] = ap;
308 	(void) suword((caddr_t)ap, na-ne);
309 	nc = 0;
310 	for (;;) {
311 		ap += NBPW;
312 		if (na==ne) {
313 			(void) suword((caddr_t)ap, 0);
314 			ap += NBPW;
315 		}
316 		if (--na < 0)
317 			break;
318 		(void) suword((caddr_t)ap, ucp);
319 		do {
320 			if (nc % (CLSIZE*NBPG) == 0) {
321 				if (bp)
322 					brelse(bp);
323 				bp = bread(argdev, bno + ctod(nc / NBPG),
324 				    CLSIZE*NBPG);
325 				bp->b_flags |= B_AGE;		/* throw away */
326 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
327 				cp = bp->b_un.b_addr;
328 			}
329 			(void) subyte((caddr_t)ucp++, (c = *cp++));
330 			nc++;
331 		} while(c&0377);
332 	}
333 	(void) suword((caddr_t)ap, 0);
334 	setregs();
335 bad:
336 	if (bp)
337 		brelse(bp);
338 	if (bno)
339 		rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno);
340 	iput(ip);
341 }
342 
343 /*
344  * Read in and set up memory for executed file.
345  */
346 getxfile(ip, nargc, uid, gid)
347 register struct inode *ip;
348 {
349 	register size_t ts, ds, ss;
350 	int pagi;
351 
352 	if (u.u_exdata.ux_mag == 0413)
353 		pagi = SPAGI;
354 	else
355 		pagi = 0;
356 	if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 &&
357 	    ip->i_count!=1) {
358 		register struct file *fp;
359 
360 		for (fp = file; fp < fileNFILE; fp++) {
361 			if (fp->f_type == DTYPE_FILE &&
362 			    fp->f_count > 0 &&
363 			    fp->f_inode == ip && (fp->f_flag&FWRITE)) {
364 				u.u_error = ETXTBSY;
365 				goto bad;
366 			}
367 		}
368 	}
369 
370 	/*
371 	 * Compute text and data sizes and make sure not too large.
372 	 */
373 	ts = clrnd(btoc(u.u_exdata.ux_tsize));
374 	ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize)));
375 	ss = clrnd(SSIZE + btoc(nargc));
376 	if (chksize(ts, ds, ss))
377 		goto bad;
378 
379 	/*
380 	 * Make sure enough space to start process.
381 	 */
382 	u.u_cdmap = zdmap;
383 	u.u_csmap = zdmap;
384 	if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL)
385 		goto bad;
386 
387 	/*
388 	 * At this point, committed to the new image!
389 	 * Release virtual memory resources of old process, and
390 	 * initialize the virtual memory of the new process.
391 	 * If we resulted from vfork(), instead wakeup our
392 	 * parent who will set SVFDONE when he has taken back
393 	 * our resources.
394 	 */
395 	if ((u.u_procp->p_flag & SVFORK) == 0)
396 		vrelvm();
397 	else {
398 		u.u_procp->p_flag &= ~SVFORK;
399 		u.u_procp->p_flag |= SKEEP;
400 		wakeup((caddr_t)u.u_procp);
401 		while ((u.u_procp->p_flag & SVFDONE) == 0)
402 			sleep((caddr_t)u.u_procp, PZERO - 1);
403 		u.u_procp->p_flag &= ~(SVFDONE|SKEEP);
404 	}
405 	u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG);
406 	u.u_procp->p_flag |= pagi;
407 	u.u_dmap = u.u_cdmap;
408 	u.u_smap = u.u_csmap;
409 	vgetvm(ts, ds, ss);
410 
411 	if (pagi == 0)
412 		u.u_error =
413 		    rdwri(UIO_READ, ip,
414 			(char *)ctob(dptov(u.u_procp, 0)),
415 			(int)u.u_exdata.ux_dsize,
416 			(int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize),
417 			0, (int *)0);
418 	xalloc(ip, pagi);
419 	if (pagi && u.u_procp->p_textp)
420 		vinifod((struct fpte *)dptopte(u.u_procp, 0),
421 		    PG_FTEXT, u.u_procp->p_textp->x_iptr,
422 		    (long)(1 + ts/CLSIZE), (int)btoc(u.u_exdata.ux_dsize));
423 
424 #ifdef vax
425 	/* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
426 #include "../vax/mtpr.h"		/* XXX */
427 	mtpr(TBIA, 0);
428 #endif
429 
430 	if (u.u_error)
431 		swkill(u.u_procp, "i/o error mapping pages");
432 	/*
433 	 * set SUID/SGID protections, if no tracing
434 	 */
435 	if ((u.u_procp->p_flag&STRC)==0) {
436 		u.u_uid = uid;
437 		u.u_procp->p_uid = uid;
438 		u.u_gid = gid;
439 	} else
440 		psignal(u.u_procp, SIGTRAP);
441 	u.u_tsize = ts;
442 	u.u_dsize = ds;
443 	u.u_ssize = ss;
444 bad:
445 	return;
446 }
447 
448 /*
449  * Clear registers on exec
450  */
451 setregs()
452 {
453 	register int (**rp)();
454 	register i;
455 	long sigmask;
456 
457 	for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG];
458 	    sigmask <<= 1, rp++) {
459 		switch (*rp) {
460 
461 		case SIG_IGN:
462 		case SIG_DFL:
463 		case SIG_HOLD:
464 			continue;
465 
466 		default:
467 			/*
468 			 * Normal or deferring catch; revert to default.
469 			 */
470 			(void) spl6();
471 			*rp = SIG_DFL;
472 			if ((int)*rp & 1)
473 				u.u_procp->p_siga0 |= sigmask;
474 			else
475 				u.u_procp->p_siga0 &= ~sigmask;
476 			if ((int)*rp & 2)
477 				u.u_procp->p_siga1 |= sigmask;
478 			else
479 				u.u_procp->p_siga1 &= ~sigmask;
480 			(void) spl0();
481 			continue;
482 		}
483 	}
484 #ifdef vax
485 /*
486 	for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
487 		*rp++ = 0;
488 */
489 	u.u_ar0[PC] = u.u_exdata.ux_entloc+2;
490 #endif
491 #ifdef sun
492 	{ register struct regs *r = (struct regs *)u.u_ar0;
493 	  for (i = 0; i < 8; i++) {
494 		r->r_dreg[i] = 0;
495 		if (&r->r_areg[i] != &r->r_sp)
496 			r->r_areg[i] = 0;
497 	  }
498 	  r->r_sr = PSL_USERSET;
499 	  r->r_pc = u.u_exdata.ux_entloc;
500 	}
501 #endif
502 	for (i=0; i<NOFILE; i++) {
503 		if (u.u_pofile[i]&UF_EXCLOSE) {
504 			closef(u.u_ofile[i], 1, u.u_pofile[i]);
505 			u.u_ofile[i] = NULL;
506 			u.u_pofile[i] = 0;
507 		}
508 		u.u_pofile[i] &= ~UF_MAPPED;
509 	}
510 
511 	/*
512 	 * Remember file name for accounting.
513 	 */
514 	u.u_acflag &= ~AFORK;
515 	bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm,
516 	    (unsigned)(u.u_dent.d_namlen + 1));
517 #ifdef sun
518 	u.u_eosys = REALLYRETURN;
519 #endif
520 }
521 
522 /*
523  * Exit system call: pass back caller's arg
524  */
525 rexit()
526 {
527 	register struct a {
528 		int	rval;
529 	} *uap;
530 
531 	uap = (struct a *)u.u_ap;
532 	exit((uap->rval & 0377) << 8);
533 }
534 
535 /*
536  * Release resources.
537  * Save u. area for parent to look at.
538  * Enter zombie state.
539  * Wake up parent and init processes,
540  * and dispose of children.
541  */
542 exit(rv)
543 {
544 	register int i;
545 	register struct proc *p, *q;
546 	register int x;
547 	struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE);
548 
549 #ifdef PGINPROF
550 	vmsizmon();
551 #endif
552 	p = u.u_procp;
553 	p->p_flag &= ~(STRC|SULOCK);
554 	p->p_flag |= SWEXIT;
555 	(void) spl6();
556 	if ((int)SIG_IGN & 1)
557 		p->p_siga0 = ~0;
558 	else
559 		p->p_siga0 = 0;
560 	if ((int)SIG_IGN & 2)
561 		p->p_siga1 = ~0;
562 	else
563 		p->p_siga1 = 0;
564 	(void) spl0();
565 	p->p_cpticks = 0;
566 	p->p_pctcpu = 0;
567 	for (i=0; i<NSIG; i++)
568 		u.u_signal[i] = SIG_IGN;
569 	untimeout(realitexpire, (caddr_t)p);
570 	/*
571 	 * Release virtual memory.  If we resulted from
572 	 * a vfork(), instead give the resources back to
573 	 * the parent.
574 	 */
575 	if ((p->p_flag & SVFORK) == 0)
576 		vrelvm();
577 	else {
578 		p->p_flag &= ~SVFORK;
579 		wakeup((caddr_t)p);
580 		while ((p->p_flag & SVFDONE) == 0)
581 			sleep((caddr_t)p, PZERO - 1);
582 		p->p_flag &= ~SVFDONE;
583 	}
584 	for (i = 0; i < NOFILE; i++) {
585 		struct file *f;
586 		int p;
587 
588 		f = u.u_ofile[i];
589 		u.u_ofile[i] = NULL;
590 		p = u.u_pofile[i];
591 		u.u_pofile[i] = 0;
592 		closef(f, 1, p);
593 	}
594 	ilock(u.u_cdir);
595 	iput(u.u_cdir);
596 	if (u.u_rdir) {
597 		ilock(u.u_rdir);
598 		iput(u.u_rdir);
599 	}
600 	u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
601 	acct();
602 #ifdef QUOTA
603 	qclean();
604 #endif
605 #ifdef sun
606 	ctxfree(u.u_procp);
607 #endif
608 	vrelpt(u.u_procp);
609 	vrelu(u.u_procp, 0);
610 	(void) spl5();		/* hack for mem alloc race XXX */
611 	multprog--;
612 	p->p_stat = SZOMB;
613 	noproc = 1;
614 	i = PIDHASH(p->p_pid);
615 	x = p - proc;
616 	if (pidhash[i] == x)
617 		pidhash[i] = p->p_idhash;
618 	else {
619 		for (i = pidhash[i]; i != 0; i = proc[i].p_idhash)
620 			if (proc[i].p_idhash == x) {
621 				proc[i].p_idhash = p->p_idhash;
622 				goto done;
623 			}
624 		panic("exit");
625 	}
626 	if (p->p_pid == 1)
627 		panic("init died");
628 done:
629 	p->p_xstat = rv;
630 if (m == 0)
631 panic("exit: m_getclr");
632 	p->p_ru = mtod(m, struct rusage *);
633 	*p->p_ru = u.u_ru;
634 	ruadd(p->p_ru, &u.u_cru);
635 	for (q = proc; q < procNPROC; q++)
636 		if (q->p_pptr == p) {
637 			if (q->p_osptr)
638 				q->p_osptr->p_ysptr = q->p_ysptr;
639 			if (q->p_ysptr)
640 				q->p_ysptr->p_osptr = q->p_osptr;
641 			if (proc[1].p_cptr)
642 				proc[1].p_cptr->p_ysptr = q;
643 			q->p_osptr = proc[1].p_cptr;
644 			q->p_ysptr = NULL;
645 			proc[1].p_cptr = q;
646 
647 			q->p_pptr = &proc[1];
648 			q->p_ppid = 1;
649 			wakeup((caddr_t)&proc[1]);
650 			/*
651 			 * Traced processes are killed
652 			 * since their existence means someone is screwing up.
653 			 * Stopped processes are sent a hangup and a continue.
654 			 * This is designed to be ``safe'' for setuid
655 			 * processes since they must be willing to tolerate
656 			 * hangups anyways.
657 			 */
658 			if (q->p_flag&STRC) {
659 				q->p_flag &= ~STRC;
660 				psignal(q, SIGKILL);
661 			} else if (q->p_stat == SSTOP) {
662 				psignal(q, SIGHUP);
663 				psignal(q, SIGCONT);
664 			}
665 			/*
666 			 * Protect this process from future
667 			 * tty signals, clear TSTP/TTIN/TTOU if pending.
668 			 */
669 			(void) spgrp(q, -1);
670 		}
671 	psignal(p->p_pptr, SIGCHLD);
672 	wakeup((caddr_t)p->p_pptr);
673 	swtch();
674 }
675 
676 wait()
677 {
678 	struct rusage ru, *rup;
679 
680 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
681 		u.u_error = wait1(0, (struct rusage *)0);
682 		return;
683 	}
684 	rup = (struct rusage *)u.u_ar0[R1];
685 	u.u_error = wait1(u.u_ar0[R0], &ru);
686 	if (u.u_error)
687 		return;
688 	(void) copyout((caddr_t)&ru, (caddr_t)rup, sizeof (struct rusage));
689 }
690 
691 #ifndef NOCOMPAT
692 #include "../h/vtimes.h"
693 
694 owait()
695 {
696 	struct rusage ru;
697 	struct vtimes *vtp, avt;
698 
699 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
700 		u.u_error = wait1(0, (struct rusage *)0);
701 		return;
702 	}
703 	vtp = (struct vtimes *)u.u_ar0[R1];
704 	u.u_error = wait1(u.u_ar0[R0], &ru);
705 	if (u.u_error)
706 		return;
707 	getvtimes(&ru, &avt);
708 	(void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes));
709 }
710 #endif
711 
712 /*
713  * Wait system call.
714  * Search for a terminated (zombie) child,
715  * finally lay it to rest, and collect its status.
716  * Look also for stopped (traced) children,
717  * and pass back status from them.
718  */
719 wait1(options, ru)
720 	register int options;
721 	struct rusage *ru;
722 {
723 	register f;
724 	register struct proc *p, *q;
725 
726 	f = 0;
727 loop:
728 	for (p = proc; p < procNPROC; p++)
729 	if (p->p_pptr == u.u_procp) {
730 		f++;
731 		if (p->p_stat == SZOMB) {
732 			u.u_r.r_val1 = p->p_pid;
733 			u.u_r.r_val2 = p->p_xstat;
734 			p->p_xstat = 0;
735 			if (ru)
736 				*ru = *p->p_ru;
737 			ruadd(&u.u_cru, p->p_ru);
738 			(void) m_free(dtom(p->p_ru));
739 			p->p_ru = 0;
740 			p->p_stat = NULL;
741 			p->p_pid = 0;
742 			p->p_ppid = 0;
743 			if (q = p->p_ysptr)
744 				q->p_osptr = p->p_osptr;
745 			if (q = p->p_osptr)
746 				q->p_ysptr = p->p_ysptr;
747 			if ((q = p->p_pptr)->p_cptr == p)
748 				q->p_cptr = p->p_osptr;
749 			p->p_pptr = 0;
750 			p->p_ysptr = 0;
751 			p->p_osptr = 0;
752 			p->p_cptr = 0;
753 			p->p_sig = 0;
754 			p->p_siga0 = 0;
755 			p->p_siga1 = 0;
756 			p->p_pgrp = 0;
757 			p->p_flag = 0;
758 			p->p_wchan = 0;
759 			p->p_cursig = 0;
760 			return (0);
761 		}
762 		if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
763 		    (p->p_flag&STRC || options&WUNTRACED)) {
764 			p->p_flag |= SWTED;
765 			u.u_r.r_val1 = p->p_pid;
766 			u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
767 			return (0);
768 		}
769 	}
770 	if (f == 0) {
771 		return (ECHILD);
772 	}
773 	if (options&WNOHANG) {
774 		u.u_r.r_val1 = 0;
775 		return (0);
776 	}
777 	if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
778 		u.u_eosys = RESTARTSYS;
779 		return (0);
780 	}
781 	sleep((caddr_t)u.u_procp, PWAIT);
782 	goto loop;
783 }
784 
785 /*
786  * fork system call.
787  */
788 fork()
789 {
790 
791 	u.u_cdmap = zdmap;
792 	u.u_csmap = zdmap;
793 	if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) {
794 		u.u_r.r_val2 = 0;
795 		return;
796 	}
797 	fork1(0);
798 }
799 
800 fork1(isvfork)
801 {
802 	register struct proc *p1, *p2;
803 	register a;
804 
805 	a = 0;
806 	p2 = NULL;
807 	for (p1 = proc; p1 < procNPROC; p1++) {
808 		if (p1->p_stat==NULL && p2==NULL)
809 			p2 = p1;
810 		else {
811 			if (p1->p_uid==u.u_uid && p1->p_stat!=NULL)
812 				a++;
813 		}
814 	}
815 	/*
816 	 * Disallow if
817 	 *  No processes at all;
818 	 *  not su and too many procs owned; or
819 	 *  not su and would take last slot.
820 	 */
821 	if (p2==NULL)
822 		tablefull("proc");
823 	if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) {
824 		u.u_error = EAGAIN;
825 		if (!isvfork) {
826 			(void) vsexpand(0, &u.u_cdmap, 1);
827 			(void) vsexpand(0, &u.u_csmap, 1);
828 		}
829 		goto out;
830 	}
831 	p1 = u.u_procp;
832 	if (newproc(isvfork)) {
833 		u.u_r.r_val1 = p1->p_pid;
834 		u.u_r.r_val2 = 1;  /* child */
835 		u.u_start = time.tv_sec;
836 		u.u_acflag = AFORK;
837 		return;
838 	}
839 	u.u_r.r_val1 = p2->p_pid;
840 
841 out:
842 	u.u_r.r_val2 = 0;
843 }
844 
845 spgrp(top, npgrp)
846 register struct proc *top;
847 {
848 	register struct proc *pp, *p;
849 	int f = 0;
850 
851 	for (p = top; npgrp == -1 || u.u_uid == p->p_uid ||
852 	    !u.u_uid || inferior(p); p = pp) {
853 		if (npgrp == -1) {
854 #define	bit(a)	(1<<(a-1))
855 			p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU));
856 		} else
857 			p->p_pgrp = npgrp;
858 		f++;
859 		/*
860 		 * Search for children.
861 		 */
862 		for (pp = proc; pp < procNPROC; pp++)
863 			if (pp->p_pptr == p)
864 				goto cont;
865 		/*
866 		 * Search for siblings.
867 		 */
868 		for (; p != top; p = p->p_pptr)
869 			for (pp = p + 1; pp < procNPROC; pp++)
870 				if (pp->p_pptr == p->p_pptr)
871 					goto cont;
872 		break;
873 	cont:
874 		;
875 	}
876 	return (f);
877 }
878 
879 /*
880  * Is p an inferior of the current process?
881  */
882 inferior(p)
883 	register struct proc *p;
884 {
885 
886 	for (; p != u.u_procp; p = p->p_pptr)
887 		if (p->p_ppid == 0)
888 			return (0);
889 	return (1);
890 }
891 
892 struct proc *
893 pfind(pid)
894 	int pid;
895 {
896 	register struct proc *p;
897 
898 	for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash])
899 		if (p->p_pid == pid)
900 			return (p);
901 	return ((struct proc *)0);
902 }
903 
904 /*
905  * Create a new process-- the internal version of
906  * sys fork.
907  * It returns 1 in the new process, 0 in the old.
908  */
909 newproc(isvfork)
910 	int isvfork;
911 {
912 	register struct proc *p;
913 	register struct proc *rpp, *rip;
914 	register int n;
915 	register struct file *fp;
916 
917 	p = NULL;
918 	/*
919 	 * First, just locate a slot for a process
920 	 * and copy the useful info from this process into it.
921 	 * The panic "cannot happen" because fork has already
922 	 * checked for the existence of a slot.
923 	 */
924 retry:
925 	mpid++;
926 	if (mpid >= 30000) {
927 		mpid = 0;
928 		goto retry;
929 	}
930 	for (rpp = proc; rpp < procNPROC; rpp++) {
931 		if (rpp->p_stat == NULL && p==NULL)
932 			p = rpp;
933 		if (rpp->p_pid==mpid || rpp->p_pgrp==mpid)
934 			goto retry;
935 	}
936 	if ((rpp = p) == NULL)
937 		panic("no procs");
938 
939 	/*
940 	 * Make a proc table entry for the new process.
941 	 */
942 	rip = u.u_procp;
943 #ifdef QUOTA
944 	rpp->p_quota = rip->p_quota;
945 	rpp->p_quota->q_cnt++;
946 #endif
947 	rpp->p_stat = SIDL;
948 	timerclear(&rpp->p_realtimer.it_value);
949 	rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG));
950 	if (isvfork) {
951 		rpp->p_flag |= SVFORK;
952 		rpp->p_ndx = rip->p_ndx;
953 	} else
954 		rpp->p_ndx = rpp - proc;
955 	rpp->p_uid = rip->p_uid;
956 	rpp->p_pgrp = rip->p_pgrp;
957 	rpp->p_nice = rip->p_nice;
958 	rpp->p_textp = isvfork ? 0 : rip->p_textp;
959 	rpp->p_pid = mpid;
960 	rpp->p_ppid = rip->p_pid;
961 	rpp->p_pptr = rip;
962 	rpp->p_osptr = rip->p_cptr;
963 	if (rip->p_cptr)
964 		rip->p_cptr->p_ysptr = rpp;
965 	rpp->p_ysptr = NULL;
966 	rpp->p_cptr = NULL;
967 	rip->p_cptr = rpp;
968 	rpp->p_time = 0;
969 	rpp->p_cpu = 0;
970 	rpp->p_siga0 = rip->p_siga0;
971 	rpp->p_siga1 = rip->p_siga1;
972 	/* take along any pending signals, like stops? */
973 	if (isvfork) {
974 		rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0;
975 		rpp->p_szpt = clrnd(ctopt(UPAGES));
976 		forkstat.cntvfork++;
977 		forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
978 	} else {
979 		rpp->p_tsize = rip->p_tsize;
980 		rpp->p_dsize = rip->p_dsize;
981 		rpp->p_ssize = rip->p_ssize;
982 		rpp->p_szpt = rip->p_szpt;
983 		forkstat.cntfork++;
984 		forkstat.sizfork += rip->p_dsize + rip->p_ssize;
985 	}
986 	rpp->p_rssize = 0;
987 	rpp->p_maxrss = rip->p_maxrss;
988 	rpp->p_wchan = 0;
989 	rpp->p_slptime = 0;
990 	rpp->p_pctcpu = 0;
991 	rpp->p_cpticks = 0;
992 	n = PIDHASH(rpp->p_pid);
993 	p->p_idhash = pidhash[n];
994 	pidhash[n] = rpp - proc;
995 	multprog++;
996 
997 	/*
998 	 * Increase reference counts on shared objects.
999 	 */
1000 	for (n = 0; n < NOFILE; n++) {
1001 		fp = u.u_ofile[n];
1002 		if (fp == NULL)
1003 			continue;
1004 		fp->f_count++;
1005 		if (u.u_pofile[n]&UF_SHLOCK)
1006 			fp->f_inode->i_shlockc++;
1007 		if (u.u_pofile[n]&UF_EXLOCK)
1008 			fp->f_inode->i_exlockc++;
1009 	}
1010 	u.u_cdir->i_count++;
1011 	if (u.u_rdir)
1012 		u.u_rdir->i_count++;
1013 
1014 	/*
1015 	 * Partially simulate the environment
1016 	 * of the new process so that when it is actually
1017 	 * created (by copying) it will look right.
1018 	 * This begins the section where we must prevent the parent
1019 	 * from being swapped.
1020 	 */
1021 	rip->p_flag |= SKEEP;
1022 	if (procdup(rpp, isvfork))
1023 		return (1);
1024 
1025 	/*
1026 	 * Make child runnable and add to run queue.
1027 	 */
1028 	(void) spl6();
1029 	rpp->p_stat = SRUN;
1030 	setrq(rpp);
1031 	(void) spl0();
1032 
1033 	/*
1034 	 * Cause child to take a non-local goto as soon as it runs.
1035 	 * On older systems this was done with SSWAP bit in proc
1036 	 * table; on VAX we use u.u_pcb.pcb_sswap so don't need
1037 	 * to do rpp->p_flag |= SSWAP.  Actually do nothing here.
1038 	 */
1039 	/* rpp->p_flag |= SSWAP; */
1040 
1041 	/*
1042 	 * Now can be swapped.
1043 	 */
1044 	rip->p_flag &= ~SKEEP;
1045 
1046 	/*
1047 	 * If vfork make chain from parent process to child
1048 	 * (where virtal memory is temporarily).  Wait for
1049 	 * child to finish, steal virtual memory back,
1050 	 * and wakeup child to let it die.
1051 	 */
1052 	if (isvfork) {
1053 		u.u_procp->p_xlink = rpp;
1054 		u.u_procp->p_flag |= SNOVM;
1055 		while (rpp->p_flag & SVFORK)
1056 			sleep((caddr_t)rpp, PZERO - 1);
1057 		if ((rpp->p_flag & SLOAD) == 0)
1058 			panic("newproc vfork");
1059 		uaccess(rpp, Vfmap, &vfutl);
1060 		u.u_procp->p_xlink = 0;
1061 		vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
1062 		u.u_procp->p_flag &= ~SNOVM;
1063 		rpp->p_ndx = rpp - proc;
1064 		rpp->p_flag |= SVFDONE;
1065 		wakeup((caddr_t)rpp);
1066 	}
1067 
1068 	/*
1069 	 * 0 return means parent.
1070 	 */
1071 	return (0);
1072 }
1073