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