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