print user@hostname; filter header lines
[unix-history] / usr / src / sys / kern / kern_proc.c
CommitLineData
8a39458a 1/* kern_proc.c 4.63 83/05/21 */
961945a8
SL
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"
cf1233e6 18#include "../h/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;
1cad6c91
SL
53 if (len > hostnamelen + 1)
54 len = hostnamelen + 1;
127f7d76 55 u.u_error = copyout((caddr_t)hostname, (caddr_t)uap->hostname, len);
1edb1cf8
BJ
56}
57
58sethostname()
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 }
1cad6c91 71 hostnamelen = uap->len;
127f7d76 72 u.u_error = copyin((caddr_t)uap->hostname, hostname, uap->len);
1cad6c91 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;
8a39458a 102 char cfname[MAXCOMLEN + 1];
7eeaac77 103 char cfarg[SHSIZE];
a6b6f679 104 int resid;
29dd101b 105
4f083fd7 106 if ((ip = namei(uchar, LOOKUP, 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 */
961945a8 143 u.u_exdata.ux_shell[0] = 0; /* for zero length files */
a2a2a0d6 144 u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata),
a6b6f679 145 0, 1, &resid);
e92a04af 146 if (u.u_error)
7eeaac77 147 goto bad;
a6b6f679 148 u.u_count = resid;
a2a2a0d6 149#ifndef lint
348d7c13
BJ
150 if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) &&
151 u.u_exdata.ux_shell[0] != '#') {
7eeaac77
RE
152 u.u_error = ENOEXEC;
153 goto bad;
154 }
a2a2a0d6 155#endif
7eeaac77
RE
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 }
8a39458a
SL
208 if (u.u_dent.d_namlen > MAXCOMLEN)
209 u.u_dent.d_namlen = MAXCOMLEN;
6459ebe0 210 bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname,
a2a2a0d6 211 (unsigned)(u.u_dent.d_namlen + 1));
8a39458a 212 cfname[MAXCOMLEN] = 0;
7eeaac77
RE
213 indir = 1;
214 iput(ip);
4f083fd7 215 ip = namei(schar, LOOKUP, 1);
7eeaac77
RE
216 if (ip == NULL)
217 return;
218 goto again;
219 }
220
29dd101b
BJ
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;
39d536e6 228 if ((bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))))) == 0) {
29dd101b
BJ
229 swkill(u.u_procp, "exece");
230 goto bad;
231 }
232 if (bno % CLSIZE)
b725a0ca 233 panic("execa rmalloc");
29dd101b
BJ
234 if (uap->argp) for (;;) {
235 ap = NULL;
40d07ebb 236 if (indir && (na == 1 || na == 2 && sharg))
7eeaac77
RE
237 ap = (int)uap->fname;
238 else if (uap->argp) {
29dd101b
BJ
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 }
6459ebe0 249 if (ap == NULL)
29dd101b
BJ
250 break;
251 na++;
e92a04af 252 if (ap == -1)
29dd101b
BJ
253 u.u_error = EFAULT;
254 do {
255 if (nc >= NCARGS-1)
256 u.u_error = E2BIG;
7eeaac77
RE
257 if (indir && na == 2 && sharg != NULL)
258 c = *sharg++ & 0377;
259 else if ((c = fubyte((caddr_t)ap++)) < 0)
29dd101b 260 u.u_error = EFAULT;
64d6118b
BJ
261 if (u.u_error) {
262 if (bp)
263 brelse(bp);
264 bp = 0;
29dd101b 265 goto badarg;
64d6118b 266 }
6459ebe0 267 if (nc % (CLSIZE*NBPG) == 0) {
29dd101b
BJ
268 if (bp)
269 bdwrite(bp);
e0fc9a90 270 bp = getblk(argdev, bno + ctod(nc / NBPG),
6459ebe0 271 CLSIZE*NBPG);
29dd101b
BJ
272 cp = bp->b_un.b_addr;
273 }
274 nc++;
275 *cp++ = c;
6459ebe0 276 } while (c > 0);
29dd101b
BJ
277 }
278 if (bp)
279 bdwrite(bp);
280 bp = 0;
281 nc = (nc + NBPW-1) & ~(NBPW-1);
6459ebe0
KM
282 if (indir) {
283 u.u_dent.d_namlen = strlen(cfname);
284 bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name,
a2a2a0d6 285 (unsigned)(u.u_dent.d_namlen + 1));
6459ebe0 286 }
7eeaac77 287 getxfile(ip, nc + (na+4)*NBPW, uid, gid);
29a06346 288 if (u.u_error) {
29dd101b 289badarg:
0981aef0
BJ
290 for (c = 0; c < nc; c += CLSIZE*NBPG) {
291 bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG);
e0fc9a90 292 if (bp) {
29dd101b
BJ
293 bp->b_flags |= B_AGE; /* throw away */
294 bp->b_flags &= ~B_DELWRI; /* cancel io */
295 brelse(bp);
296 bp = 0;
297 }
0981aef0 298 }
29dd101b
BJ
299 goto bad;
300 }
301
302 /*
303 * copy back arglist
304 */
29dd101b
BJ
305 ucp = USRSTACK - nc - NBPW;
306 ap = ucp - na*NBPW - 3*NBPW;
307 u.u_ar0[SP] = ap;
81263dba 308 (void) suword((caddr_t)ap, na-ne);
29dd101b
BJ
309 nc = 0;
310 for (;;) {
311 ap += NBPW;
312 if (na==ne) {
81263dba 313 (void) suword((caddr_t)ap, 0);
29dd101b
BJ
314 ap += NBPW;
315 }
316 if (--na < 0)
317 break;
81263dba 318 (void) suword((caddr_t)ap, ucp);
29dd101b 319 do {
6459ebe0 320 if (nc % (CLSIZE*NBPG) == 0) {
29dd101b
BJ
321 if (bp)
322 brelse(bp);
62cd6584 323 bp = bread(argdev, bno + ctod(nc / NBPG),
6459ebe0 324 CLSIZE*NBPG);
29dd101b
BJ
325 bp->b_flags |= B_AGE; /* throw away */
326 bp->b_flags &= ~B_DELWRI; /* cancel io */
327 cp = bp->b_un.b_addr;
328 }
81263dba 329 (void) subyte((caddr_t)ucp++, (c = *cp++));
29dd101b
BJ
330 nc++;
331 } while(c&0377);
332 }
81263dba 333 (void) suword((caddr_t)ap, 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;
29a06346
BJ
439 } else
440 psignal(u.u_procp, SIGTRAP);
29dd101b
BJ
441 u.u_tsize = ts;
442 u.u_dsize = ds;
443 u.u_ssize = ss;
29dd101b 444bad:
29a06346 445 return;
29dd101b
BJ
446}
447
448/*
449 * Clear registers on exec
450 */
451setregs()
452{
594ebedd 453 register int (**rp)();
29dd101b 454 register i;
bdfe5b0f 455 long sigmask;
29dd101b 456
4e6e3887 457 for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG];
bdfe5b0f
BJ
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 /*
99fa88a2 468 * Normal or deferring catch; revert to default.
bdfe5b0f 469 */
99fa88a2
BJ
470 (void) spl6();
471 *rp = SIG_DFL;
bdfe5b0f
BJ
472 if ((int)*rp & 1)
473 u.u_procp->p_siga0 |= sigmask;
474 else
a4aaef65 475 u.u_procp->p_siga0 &= ~sigmask;
bdfe5b0f
BJ
476 if ((int)*rp & 2)
477 u.u_procp->p_siga1 |= sigmask;
478 else
479 u.u_procp->p_siga1 &= ~sigmask;
99fa88a2 480 (void) spl0();
bdfe5b0f
BJ
481 continue;
482 }
483 }
e0fc9a90 484#ifdef vax
29dd101b 485/*
e92a04af 486 for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
29dd101b
BJ
487 *rp++ = 0;
488*/
e0fc9a90
BJ
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
e92a04af 502 for (i=0; i<NOFILE; i++) {
3650c37d 503 if (u.u_pofile[i]&UF_EXCLOSE) {
a81e9a81 504 closef(u.u_ofile[i], 1, u.u_pofile[i]);
29dd101b 505 u.u_ofile[i] = NULL;
a81e9a81 506 u.u_pofile[i] = 0;
29dd101b 507 }
e0fc9a90 508 u.u_pofile[i] &= ~UF_MAPPED;
29dd101b 509 }
e92a04af 510
29dd101b
BJ
511 /*
512 * Remember file name for accounting.
513 */
514 u.u_acflag &= ~AFORK;
6459ebe0 515 bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm,
a2a2a0d6 516 (unsigned)(u.u_dent.d_namlen + 1));
e0fc9a90
BJ
517#ifdef sun
518 u.u_eosys = REALLYRETURN;
519#endif
29dd101b
BJ
520}
521
522/*
e92a04af 523 * Exit system call: pass back caller's arg
29dd101b
BJ
524 */
525rexit()
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 */
542exit(rv)
543{
544 register int i;
545 register struct proc *p, *q;
29dd101b 546 register int x;
cce93e4b 547 struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE);
29dd101b
BJ
548
549#ifdef PGINPROF
550 vmsizmon();
551#endif
552 p = u.u_procp;
553 p->p_flag &= ~(STRC|SULOCK);
554 p->p_flag |= SWEXIT;
bdfe5b0f
BJ
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
99fa88a2 563 p->p_siga1 = 0;
bdfe5b0f 564 (void) spl0();
dd808ba3
BJ
565 p->p_cpticks = 0;
566 p->p_pctcpu = 0;
e92a04af 567 for (i=0; i<NSIG; i++)
594ebedd 568 u.u_signal[i] = SIG_IGN;
b32450f4 569 untimeout(realitexpire, (caddr_t)p);
29dd101b
BJ
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 }
a81e9a81 584 for (i = 0; i < NOFILE; i++) {
c5c236f8
SL
585 struct file *f;
586 int p;
587
29dd101b
BJ
588 f = u.u_ofile[i];
589 u.u_ofile[i] = NULL;
c5c236f8 590 p = u.u_pofile[i];
a81e9a81 591 u.u_pofile[i] = 0;
c5c236f8 592 closef(f, 1, p);
29dd101b 593 }
e92a04af 594 ilock(u.u_cdir);
29dd101b
BJ
595 iput(u.u_cdir);
596 if (u.u_rdir) {
e92a04af 597 ilock(u.u_rdir);
29dd101b
BJ
598 iput(u.u_rdir);
599 }
a1bce776 600 u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
29dd101b 601 acct();
feab6b5e
RE
602#ifdef QUOTA
603 qclean();
e0fc9a90
BJ
604#endif
605#ifdef sun
1cad6c91 606 ctxfree(u.u_procp);
feab6b5e 607#endif
29dd101b
BJ
608 vrelpt(u.u_procp);
609 vrelu(u.u_procp, 0);
f12a8410 610 (void) spl5(); /* hack for mem alloc race XXX */
29dd101b 611 multprog--;
29dd101b 612 p->p_stat = SZOMB;
42343c0f 613 noproc = 1;
29dd101b
BJ
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 }
9c82b9fd
BJ
626 if (p->p_pid == 1)
627 panic("init died");
29dd101b 628done:
a1bce776 629 p->p_xstat = rv;
c5c236f8
SL
630if (m == 0)
631panic("exit: m_getclr");
8c2b0bcd 632 p->p_ru = mtod(m, struct rusage *);
a1bce776
BJ
633 *p->p_ru = u.u_ru;
634 ruadd(p->p_ru, &u.u_cru);
e92a04af
BJ
635 for (q = proc; q < procNPROC; q++)
636 if (q->p_pptr == p) {
feab6b5e
RE
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
bdfe5b0f 647 q->p_pptr = &proc[1];
29dd101b 648 q->p_ppid = 1;
bdfe5b0f
BJ
649 wakeup((caddr_t)&proc[1]);
650 /*
0dde1c43 651 * Traced processes are killed
bdfe5b0f 652 * since their existence means someone is screwing up.
62bac59f 653 * Stopped processes are sent a hangup and a continue.
0dde1c43
BJ
654 * This is designed to be ``safe'' for setuid
655 * processes since they must be willing to tolerate
656 * hangups anyways.
bdfe5b0f 657 */
0dde1c43 658 if (q->p_flag&STRC) {
bdfe5b0f
BJ
659 q->p_flag &= ~STRC;
660 psignal(q, SIGKILL);
0dde1c43
BJ
661 } else if (q->p_stat == SSTOP) {
662 psignal(q, SIGHUP);
663 psignal(q, SIGCONT);
bdfe5b0f 664 }
8643403f
BJ
665 /*
666 * Protect this process from future
7ac93404 667 * tty signals, clear TSTP/TTIN/TTOU if pending.
8643403f 668 */
934e4ecf 669 (void) spgrp(q, -1);
29dd101b 670 }
bdfe5b0f 671 psignal(p->p_pptr, SIGCHLD);
4e6e3887 672 wakeup((caddr_t)p->p_pptr);
29dd101b
BJ
673 swtch();
674}
675
8ec6ce7a
SL
676wait()
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
961945a8 692#include "../h/vtimes.h"
3269c554 693
1edb1cf8 694owait()
29dd101b 695{
3269c554
BJ
696 struct rusage ru;
697 struct vtimes *vtp, avt;
29dd101b 698
bdfe5b0f 699 if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
8ec6ce7a 700 u.u_error = wait1(0, (struct rusage *)0);
bdfe5b0f
BJ
701 return;
702 }
3269c554 703 vtp = (struct vtimes *)u.u_ar0[R1];
8ec6ce7a 704 u.u_error = wait1(u.u_ar0[R0], &ru);
bdfe5b0f
BJ
705 if (u.u_error)
706 return;
3269c554
BJ
707 getvtimes(&ru, &avt);
708 (void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes));
29dd101b 709}
8ec6ce7a 710#endif
29dd101b
BJ
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 */
a1bce776
BJ
719wait1(options, ru)
720 register int options;
721 struct rusage *ru;
29dd101b
BJ
722{
723 register f;
feab6b5e 724 register struct proc *p, *q;
29dd101b
BJ
725
726 f = 0;
29dd101b 727loop:
e92a04af
BJ
728 for (p = proc; p < procNPROC; p++)
729 if (p->p_pptr == u.u_procp) {
29dd101b 730 f++;
e92a04af 731 if (p->p_stat == SZOMB) {
29dd101b 732 u.u_r.r_val1 = p->p_pid;
a1bce776
BJ
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);
39d536e6 738 (void) m_free(dtom(p->p_ru));
a1bce776 739 p->p_ru = 0;
29dd101b
BJ
740 p->p_stat = NULL;
741 p->p_pid = 0;
742 p->p_ppid = 0;
feab6b5e
RE
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;
bdfe5b0f 749 p->p_pptr = 0;
feab6b5e
RE
750 p->p_ysptr = 0;
751 p->p_osptr = 0;
752 p->p_cptr = 0;
29dd101b 753 p->p_sig = 0;
bdfe5b0f
BJ
754 p->p_siga0 = 0;
755 p->p_siga1 = 0;
29dd101b
BJ
756 p->p_pgrp = 0;
757 p->p_flag = 0;
758 p->p_wchan = 0;
bdfe5b0f 759 p->p_cursig = 0;
8ec6ce7a 760 return (0);
29dd101b 761 }
bdfe5b0f
BJ
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;
8ec6ce7a 767 return (0);
29dd101b
BJ
768 }
769 }
8ec6ce7a
SL
770 if (f == 0) {
771 return (ECHILD);
bdfe5b0f
BJ
772 }
773 if (options&WNOHANG) {
774 u.u_r.r_val1 = 0;
8ec6ce7a 775 return (0);
bdfe5b0f 776 }
f9c5db19 777 if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) {
bdfe5b0f 778 u.u_eosys = RESTARTSYS;
8ec6ce7a 779 return (0);
29dd101b 780 }
bdfe5b0f
BJ
781 sleep((caddr_t)u.u_procp, PWAIT);
782 goto loop;
29dd101b
BJ
783}
784
785/*
786 * fork system call.
787 */
788fork()
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
800fork1(isvfork)
801{
802 register struct proc *p1, *p2;
803 register a;
804
805 a = 0;
806 p2 = NULL;
e92a04af 807 for (p1 = proc; p1 < procNPROC; p1++) {
29dd101b
BJ
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 */
62901f34
BJ
821 if (p2==NULL)
822 tablefull("proc");
86fd527f 823 if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) {
29dd101b
BJ
824 u.u_error = EAGAIN;
825 if (!isvfork) {
81263dba
BJ
826 (void) vsexpand(0, &u.u_cdmap, 1);
827 (void) vsexpand(0, &u.u_csmap, 1);
29dd101b
BJ
828 }
829 goto out;
830 }
831 p1 = u.u_procp;
e92a04af 832 if (newproc(isvfork)) {
29dd101b
BJ
833 u.u_r.r_val1 = p1->p_pid;
834 u.u_r.r_val2 = 1; /* child */
a1bce776 835 u.u_start = time.tv_sec;
29dd101b
BJ
836 u.u_acflag = AFORK;
837 return;
838 }
839 u.u_r.r_val1 = p2->p_pid;
840
841out:
842 u.u_r.r_val2 = 0;
843}
844
4147b3f6
BJ
845spgrp(top, npgrp)
846register 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
29dd101b 879/*
4147b3f6 880 * Is p an inferior of the current process?
29dd101b 881 */
4147b3f6 882inferior(p)
a2a2a0d6 883 register struct proc *p;
29dd101b 884{
29dd101b 885
4147b3f6
BJ
886 for (; p != u.u_procp; p = p->p_pptr)
887 if (p->p_ppid == 0)
888 return (0);
889 return (1);
29dd101b 890}
a2a2a0d6
BJ
891
892struct proc *
893pfind(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}
1edb1cf8
BJ
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 */
909newproc(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 */
924retry:
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
8a39458a
SL
944 rpp->p_quota = rip->p_quota;
945 rpp->p_quota->q_cnt++;
1edb1cf8
BJ
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++;
3650c37d 1005 if (u.u_pofile[n]&UF_SHLOCK)
4f083fd7 1006 fp->f_inode->i_shlockc++;
3650c37d 1007 if (u.u_pofile[n]&UF_EXLOCK)
4f083fd7 1008 fp->f_inode->i_exlockc++;
1edb1cf8
BJ
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}