|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/systm.h" ! 3: #include "sys/map.h" ! 4: #include "sys/mtpr.h" ! 5: #include "sys/user.h" ! 6: #include "sys/proc.h" ! 7: #include "sys/buf.h" ! 8: #include "sys/reg.h" ! 9: #include "sys/inode.h" ! 10: #include "sys/acct.h" ! 11: #include "/usr/include/wait.h" ! 12: #include "sys/pte.h" ! 13: #include "sys/vm.h" ! 14: #include "sys/text.h" ! 15: #include "sys/psl.h" ! 16: #include "sys/vlimit.h" ! 17: #include "sys/file.h" ! 18: ! 19: /* ! 20: * exec system call ! 21: */ ! 22: struct execa { ! 23: char *fname; ! 24: char **argp; ! 25: char **envp; ! 26: }; ! 27: ! 28: struct shdata { ! 29: char sd_save[DIRSIZ]; ! 30: int sd_gid; ! 31: int sd_uid; ! 32: int sd_indir; ! 33: char sd_flag[SHSIZE]; ! 34: }; ! 35: ! 36: struct swargs { ! 37: char *sw_cp; ! 38: int sw_argc; ! 39: int sw_envc; ! 40: int sw_chars; ! 41: int sw_bn; ! 42: struct buf *sw_bp; ! 43: }; ! 44: ! 45: void ! 46: str_stash(s, sp) ! 47: register char *s; ! 48: register struct swargs *sp; ! 49: { ! 50: register char *cp; ! 51: register int nc; ! 52: register int bmask; ! 53: ! 54: cp = sp->sw_cp; ! 55: nc = sp->sw_chars; ! 56: bmask = BMASK(argdev); ! 57: ! 58: do { ! 59: if ((nc & bmask) == 0) { ! 60: if (nc >= NCARGS) { ! 61: u.u_error = E2BIG; ! 62: return; ! 63: } ! 64: if (sp->sw_bp != NULL) ! 65: bdwrite(sp->sw_bp); ! 66: sp->sw_bp = getblk(argdev, (daddr_t)(dbtofsb(argdev, ! 67: sp->sw_bn) + (nc>>BSHIFT(argdev)))); ! 68: cp = sp->sw_bp->b_un.b_addr; ! 69: } ! 70: nc++; ! 71: } while ((*cp++ = *s++) != '\0'); ! 72: ! 73: sp->sw_chars = nc; ! 74: sp->sw_cp = cp; ! 75: sp->sw_argc++; ! 76: } ! 77: ! 78: int ! 79: vec_stash(v, sp) ! 80: register char **v; ! 81: register struct swargs *sp; ! 82: { ! 83: register char *s; ! 84: register int nc; ! 85: register int nleft; ! 86: register int i; ! 87: int bsize; ! 88: int count; ! 89: int ap; ! 90: ! 91: if (v == NULL) ! 92: return 0; ! 93: ! 94: nc = sp->sw_chars; ! 95: bsize = BSIZE(argdev); ! 96: nleft = ((nc + bsize-1) & ~(bsize-1)) - nc; ! 97: count = 0; ! 98: ! 99: for (;;) { ! 100: if ((ap = fuword((caddr_t)v++)) < 0) { ! 101: u.u_error = EFAULT; ! 102: return 0; ! 103: } ! 104: if ((s = (char *)ap) == NULL) ! 105: break; ! 106: if ((i = fustrlen(s)) < 0) { ! 107: u.u_error = EFAULT; ! 108: return 0; ! 109: } ! 110: while (i > nleft) { ! 111: if (sp->sw_bp) { ! 112: bcopy(s, sp->sw_cp, nleft); ! 113: s += nleft; ! 114: nc += nleft; ! 115: i -= nleft; ! 116: if (nc >= NCARGS) { ! 117: u.u_error = E2BIG; ! 118: return 0; ! 119: } ! 120: bdwrite(sp->sw_bp); ! 121: } ! 122: sp->sw_bp = getblk(argdev, (daddr_t)(dbtofsb(argdev, ! 123: sp->sw_bn) + (nc>>BSHIFT(argdev)))); ! 124: sp->sw_cp = sp->sw_bp->b_un.b_addr; ! 125: nleft = bsize; ! 126: } ! 127: bcopy(s, sp->sw_cp, i); ! 128: sp->sw_cp += i; ! 129: nc += i; ! 130: nleft -= i; ! 131: count++; ! 132: } ! 133: sp->sw_chars = nc; ! 134: sp->sw_argc += count; ! 135: return count; ! 136: } ! 137: ! 138: exece() ! 139: { ! 140: register int i; ! 141: register int ap; ! 142: register int bsize; ! 143: register char *cp; ! 144: register char *ucp; ! 145: register struct execa *uap; ! 146: struct buf *bp; ! 147: struct inode *ip; ! 148: struct shdata sh; ! 149: struct swargs sw; ! 150: extern struct map argmap[]; ! 151: extern struct inode *gethead(); ! 152: ! 153: uap = (struct execa *)u.u_ap; ! 154: sh.sd_uid = u.u_uid; ! 155: sh.sd_gid = u.u_gid; ! 156: sh.sd_indir = 0; ! 157: sh.sd_flag[0] = '\0'; ! 158: if ((ip = gethead(uap->fname, &sh)) == NULL) ! 159: return; ! 160: ! 161: sw.sw_argc = 0; ! 162: sw.sw_chars = 0; ! 163: sw.sw_bp = NULL; ! 164: bsize = BSIZE(argdev); ! 165: if ((sw.sw_bn = rmalloc(argmap, ctod(clrnd((int)btoc(NCARGS))))) == 0) { ! 166: swkill(u.u_procp, "exece"); ! 167: iput(ip); ! 168: return; ! 169: } ! 170: if (sw.sw_bn % CLSIZE) ! 171: panic("exece rmalloc"); ! 172: if (sh.sd_indir) { ! 173: if ((ap = fuword((caddr_t)uap->argp)) < 0){ ! 174: u.u_error = EFAULT; ! 175: goto out; ! 176: } ! 177: if (ap) { ! 178: uap->argp++; ! 179: if (fustrlen((char *)ap) < 0) { ! 180: u.u_error = EFAULT; ! 181: goto out; ! 182: } ! 183: /* ! 184: * improper assumption ! 185: * ap is a user address; ! 186: * str_stash assumes kernel-accessible ! 187: */ ! 188: str_stash((char *)ap, &sw); ! 189: } ! 190: if (sh.sd_flag[0] != '\0') ! 191: str_stash(sh.sd_flag, &sw); ! 192: str_stash(uap->fname, &sw); ! 193: } ! 194: vec_stash(uap->argp, &sw); ! 195: sw.sw_envc = vec_stash(uap->envp, &sw); ! 196: bp = sw.sw_bp; ! 197: if (bp) { ! 198: bdwrite(bp); ! 199: bp = NULL; ! 200: } ! 201: ! 202: if (u.u_error) ! 203: goto out; ! 204: ! 205: sw.sw_chars = (sw.sw_chars + NBPW-1) & ~(NBPW-1); ! 206: /* 4: argc, null after args, null after env, null after everything, */ ! 207: getxfile(ip, sw.sw_chars + (sw.sw_argc+4)*NBPW, sh.sd_uid, sh.sd_gid); ! 208: ! 209: if (u.u_error) ! 210: goto out; ! 211: ! 212: iput(ip); ! 213: ucp = (char *)(USRSTACK - sw.sw_chars - NBPW); ! 214: ap = (int)ucp - (sw.sw_argc + 3) * NBPW; ! 215: u.u_ar0[SP] = ap; ! 216: *(int *)ap = sw.sw_argc - sw.sw_envc; ! 217: ! 218: for (i = 0, cp = ucp; sw.sw_chars > 0; i++, cp += bsize, sw.sw_chars -= bsize) { ! 219: if (bp) ! 220: brelse(bp); ! 221: bp = bread(argdev, (daddr_t)(dbtofsb(argdev, sw.sw_bn)+i)); ! 222: bcopy(bp->b_un.b_addr, cp, min(bsize, sw.sw_chars)); ! 223: bp->b_flags |= B_AGE; ! 224: bp->b_flags &= ~B_DELWRI; ! 225: } ! 226: ! 227: if (bp) ! 228: brelse(bp); ! 229: ! 230: for (cp = ucp; ; cp += fustrlen(cp)) { ! 231: ap += NBPW; ! 232: if (sw.sw_argc == sw.sw_envc) ! 233: ap += NBPW; ! 234: if (--sw.sw_argc < 0) ! 235: break; ! 236: *(char **)ap = cp; ! 237: } ! 238: setregs(sh.sd_save); ! 239: rmfree(argmap, ctod(clrnd((int) btoc(NCARGS))), sw.sw_bn); ! 240: return; ! 241: ! 242: out: ! 243: iput(ip); ! 244: for (i = (((sw.sw_chars+bsize-1)&~(bsize-1))>>BSHIFT(argdev))-1; ! 245: i >= 0; i--) { ! 246: bp = getblk(argdev, (daddr_t)(dbtofsb(argdev, sw.sw_bn)+i)); ! 247: bp->b_flags |= B_AGE; ! 248: bp->b_flags &= ~B_DELWRI; ! 249: brelse(bp); ! 250: } ! 251: rmfree(argmap, ctod(clrnd((int) btoc(NCARGS))), sw.sw_bn); ! 252: } ! 253: ! 254: /* ! 255: * Get a shell after #! magic number. ! 256: */ ! 257: struct inode * ! 258: getshell(ip, sp) ! 259: struct inode *ip; ! 260: struct shdata *sp; ! 261: { ! 262: register char *cp, *fname; ! 263: extern struct inode *gethead(); ! 264: ! 265: if(u.u_exdata.ux_shell[0] != '#' || u.u_exdata.ux_shell[1] != '!' || sp->sd_indir) ! 266: goto error; ! 267: cp = &u.u_exdata.ux_shell[2]; ! 268: for (;;) { ! 269: if (cp == &u.u_exdata.ux_shell[SHSIZE]) ! 270: goto error; ! 271: if (*cp == '\n') { ! 272: *cp = '\0'; ! 273: break; ! 274: } ! 275: if (*cp == '\t') ! 276: *cp = ' '; ! 277: cp++; ! 278: } ! 279: for (cp = &u.u_exdata.ux_shell[2]; *cp == ' '; cp++); ! 280: if (*cp == '\0') ! 281: goto error; ! 282: fname = cp; ! 283: while (*cp != '\0') { ! 284: if (*cp == ' ') { ! 285: *cp++ = '\0'; ! 286: while (*cp == ' ') ! 287: cp++; ! 288: /* ! 289: * Shell argument (one only). ! 290: */ ! 291: if (*cp != '\0') { ! 292: register int i; ! 293: ! 294: i = 0; ! 295: do ! 296: sp->sd_flag[i++] = *cp++; ! 297: while (*cp != ' ' && *cp != '\0'); ! 298: sp->sd_flag[i] = '\0'; ! 299: } ! 300: break; ! 301: } ! 302: else ! 303: cp++; ! 304: } ! 305: iput(ip); ! 306: sp->sd_indir = 1; ! 307: return gethead(fname, sp); ! 308: ! 309: error: ! 310: iput(ip); ! 311: u.u_error = ENOEXEC; ! 312: return NULL; ! 313: } ! 314: ! 315: /* ! 316: * Get the header of an executable and do all the right tests. ! 317: */ ! 318: struct inode * ! 319: gethead(fname, sp) ! 320: char *fname; ! 321: struct shdata *sp; ! 322: { ! 323: register struct inode *ip; ! 324: struct argnamei nmarg; ! 325: ! 326: nmarg = nilargnamei; ! 327: if(sp->sd_indir == 0) { ! 328: nmarg.un.buf = (caddr_t)sp->sd_save; ! 329: nmarg.len = sizeof(sp->sd_save); ! 330: if((ip = namei(fname, SEGUDATA, &nmarg, 1)) == NULL) ! 331: return NULL; ! 332: } ! 333: else if((ip = namei(fname, SEGSYS, &nmarg, 1)) == NULL) ! 334: return NULL; ! 335: ! 336: /* ! 337: * Setuid and setgid denied for network root. ! 338: */ ! 339: if (!(ip->i_mode & ICONC)) { ! 340: if ((ip->i_mode & ISUID) != 0 && ip->i_uid != -1) ! 341: sp->sd_uid = ip->i_uid; ! 342: ! 343: if ((ip->i_mode & ISGID) != 0 && ip->i_gid != -1) ! 344: sp->sd_gid = ip->i_gid; ! 345: } ! 346: ! 347: /* ! 348: * Check permission. May not trace something we can't read. ! 349: */ ! 350: if(access(ip, IEXEC) || (PTRACED(u.u_procp) && access(ip, IREAD))) ! 351: goto out; ! 352: ! 353: /* ! 354: * Must be a regular file and must really be executable. ! 355: */ ! 356: if ((ip->i_mode & IFMT) != IFREG || ! 357: (ip->i_mode & (IEXEC | (IEXEC >> 3) | (IEXEC >> 6))) == 0) { ! 358: u.u_error = EACCES; ! 359: goto out; ! 360: } ! 361: ! 362: /* ! 363: * ux_mag = 407/410/413 ! 364: * 407 is plain executable ! 365: * 410 is RO text ! 366: * 413 is demand paged RO text ! 367: * ! 368: * Also an ASCII line beginning with #! is ! 369: * the file name of a ``shell'' and arguments may be prepended ! 370: * to the argument list if given here. ! 371: * ! 372: * Shell names are limited in length. ! 373: * ! 374: * Only one argument may be passed to the shell from the ASCII line. ! 375: */ ! 376: u.u_base = (caddr_t)&u.u_exdata; ! 377: u.u_count = sizeof(u.u_exdata); ! 378: u.u_offset = ltoL(0); ! 379: u.u_segflg = SEGSYS; ! 380: readi(ip); ! 381: u.u_segflg = SEGUDATA; ! 382: ! 383: if (u.u_error) ! 384: goto out; ! 385: ! 386: if (u.u_count > sizeof (u.u_exdata) - sizeof (u.u_exdata.Ux_A)) ! 387: ip = getshell(ip, sp); ! 388: else { ! 389: switch (u.u_exdata.ux_mag) { ! 390: case 0407: ! 391: u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; ! 392: u.u_exdata.ux_tsize = 0; ! 393: break; ! 394: ! 395: case 0410: ! 396: case 0413: ! 397: if (u.u_exdata.ux_tsize == 0) ! 398: u.u_error = ENOEXEC; ! 399: break; ! 400: ! 401: default: ! 402: ip = getshell(ip, sp); ! 403: } ! 404: } ! 405: ! 406: out: ! 407: if (u.u_error && ip != NULL) { ! 408: iput(ip); ! 409: ip = NULL; ! 410: } ! 411: ! 412: return ip; ! 413: } ! 414: ! 415: /* ! 416: * Read in and set up memory for executed file. ! 417: */ ! 418: getxfile(ip, nargc, uid, gid) ! 419: register struct inode *ip; ! 420: { ! 421: register clicks_t ts, ds, ss; ! 422: int pagi; ! 423: ! 424: /* for now, no paging off alternate file systems */ ! 425: if (u.u_exdata.ux_mag == 0413 && !BITFS(ip->i_dev) && !ip->i_fstyp) ! 426: pagi = SPAGI; ! 427: else ! 428: pagi = 0; ! 429: /* never demand-page if process is traced (panic pagein mfind) */ ! 430: if (PTRACED(u.u_procp)) ! 431: pagi = 0; ! 432: ! 433: if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { ! 434: register struct file *fp; ! 435: ! 436: for (fp = file; fp < fileNFILE; fp++) ! 437: if (fp->f_count && fp->f_inode==ip ! 438: && (fp->f_flag&FWRITE)) { ! 439: u.u_error = ETXTBSY; ! 440: goto bad; ! 441: } ! 442: } ! 443: ! 444: /* ! 445: * find text and data sizes ! 446: * try them out for possible ! 447: * exceed of max sizes ! 448: */ ! 449: ! 450: ts = clrnd(btoc(u.u_exdata.ux_tsize)); ! 451: ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); ! 452: ss = clrnd(SSIZE + btoc(nargc)); ! 453: if (chksize(ts, ds, ss)) ! 454: goto bad; ! 455: u.u_cdmap = zdmap; ! 456: u.u_csmap = zdmap; ! 457: if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) ! 458: goto bad; ! 459: ! 460: /* ! 461: * At this point, committed to the new image! ! 462: * Release virtual memory resources of old process, and ! 463: * initialize the virtual memory of the new process. ! 464: */ ! 465: u.u_prof.pr_scale = 0; ! 466: vrelvm(); ! 467: u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM); ! 468: u.u_procp->p_flag |= pagi; ! 469: u.u_dmap = u.u_cdmap; ! 470: u.u_smap = u.u_csmap; ! 471: vgetvm(ts, ds, ss); ! 472: ! 473: if (pagi == 0) { ! 474: /* ! 475: * Read in data segment. ! 476: */ ! 477: u.u_base = (char *)ctob(ts); ! 478: if(u.u_exdata.ux_mag != 0413) ! 479: u.u_offset = ltoL(sizeof(u.u_exdata)+u.u_exdata.ux_tsize); ! 480: else /* stupid 1k 0413 files */ ! 481: u.u_offset = ltoL(BSIZE(0) + u.u_exdata.ux_tsize); ! 482: u.u_count = u.u_exdata.ux_dsize; ! 483: readi(ip); ! 484: } ! 485: xalloc(ip, pagi); ! 486: if (pagi && u.u_procp->p_textp) ! 487: vinifod((struct fpte *)dptopte(u.u_procp, 0), ! 488: u.u_procp->p_textp->x_iptr, ! 489: 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); ! 490: ! 491: /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ ! 492: mtpr(TBIA, 0); ! 493: ! 494: /* ! 495: * set SUID/SGID protections, if no tracing ! 496: */ ! 497: if (!PTRACED(u.u_procp)) { ! 498: u.u_uid = uid; ! 499: u.u_procp->p_uid = uid; ! 500: u.u_gid = gid; ! 501: } ! 502: if (u.u_procp->p_flag&SSEXEC) ! 503: psignal(u.u_procp, SIGSTOP); ! 504: u.u_tsize = ts; ! 505: u.u_dsize = ds; ! 506: u.u_ssize = ss; ! 507: bad: ! 508: return; ! 509: } ! 510: ! 511: /* ! 512: * Reset context on exec ! 513: */ ! 514: setregs(comm) ! 515: char *comm; ! 516: { ! 517: register i; ! 518: register int (*f)(); ! 519: ! 520: for (i = 0; i < NSIG; i++) { ! 521: if ((f = u.u_signal[i]) == SIG_DFL ! 522: || f == SIG_IGN || f == SIG_HOLD) ! 523: continue; ! 524: spl6(); /* needed? */ ! 525: u.u_signal[i] = SIG_DFL; ! 526: P_SETDFL(u.u_procp, SIGMASK(i)); ! 527: spl0(); ! 528: } ! 529: /* ! 530: for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) ! 531: *rp++ = 0; ! 532: */ ! 533: u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ ! 534: for(i=0; i<NOFILE; i++) { ! 535: if (u.u_pofile[i]&EXCLOSE) { ! 536: closef(u.u_ofile[i]); ! 537: u.u_ofile[i] = NULL; ! 538: u.u_pofile[i] &= ~EXCLOSE; ! 539: } ! 540: } ! 541: /* ! 542: * Remember file name for accounting. ! 543: */ ! 544: u.u_acflag &= ~AFORK; ! 545: bcopy((caddr_t)comm, (caddr_t)u.u_comm, sizeof(u.u_comm)); ! 546: } ! 547: ! 548: /* ! 549: * exit system call: ! 550: * pass back caller's arg ! 551: */ ! 552: rexit() ! 553: { ! 554: register struct a { ! 555: int rval; ! 556: } *uap; ! 557: ! 558: uap = (struct a *)u.u_ap; ! 559: exit((uap->rval & 0377) << 8); ! 560: } ! 561: ! 562: /* ! 563: * Release resources. ! 564: * Save u. area for parent to look at. ! 565: * Enter zombie state. ! 566: * Wake up parent and init processes, ! 567: * and dispose of children. ! 568: */ ! 569: exit(rv) ! 570: { ! 571: register int i; ! 572: register struct proc *p, *q; ! 573: register struct file *f; ! 574: ! 575: vmsizmon(); ! 576: p = u.u_procp; ! 577: p->p_flag &= ~(STRC|SULOCK); ! 578: p->p_flag |= SWEXIT; ! 579: p->p_clktim = 0; ! 580: (void) spl6(); ! 581: p->p_siga0 = p->p_siga1 = 0; ! 582: p->p_ignsig = ~0; /* magic: ignore all */ ! 583: (void) spl0(); ! 584: p->p_cpticks = 0; ! 585: p->p_pctcpu = 0; ! 586: for(i=0; i<NSIG; i++) ! 587: u.u_signal[i] = SIG_IGN; ! 588: vrelvm(); ! 589: for(i=0; i<NOFILE; i++) { ! 590: if ((f = u.u_ofile[i]) == NULL) ! 591: continue; ! 592: u.u_ofile[i] = NULL; ! 593: closef(f); ! 594: } ! 595: plock(u.u_cdir); ! 596: iput(u.u_cdir); ! 597: if (u.u_rdir) { ! 598: plock(u.u_rdir); ! 599: iput(u.u_rdir); ! 600: } ! 601: u.u_limit[LIM_FSIZE] = INFINITY; ! 602: acct(); ! 603: vrelpt(u.u_procp); ! 604: vrelu(u.u_procp, 0); ! 605: p->p_stat = SZOMB; ! 606: noproc = 1; ! 607: if (p->p_pid < SYSPIDS) ! 608: printf("process %d died\n", p->p_pid); ! 609: done: ! 610: ((struct xproc *)p)->xp_xstat = rv; /* overlay */ ! 611: ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ ! 612: vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); ! 613: for(q = proc; q < procNPROC; q++) ! 614: if (q->p_stat != 0 && q->p_pptr == p) { ! 615: q->p_pptr = &proc[INITPID]; ! 616: q->p_ppid = 1; ! 617: wakeup((caddr_t)&proc[INITPID]); ! 618: /* ! 619: * Traced processes are killed ! 620: * since their existence means someone is screwing up. ! 621: * this is probably wrong now ! 622: * Stopped processes are sent a hangup and a continue. ! 623: * This is designed to be ``safe'' for setuid ! 624: * processes since they must be willing to tolerate ! 625: * hangups anyways. ! 626: */ ! 627: if (q->p_flag&STRC) { ! 628: q->p_flag &= ~STRC; ! 629: psignal(q, SIGKILL); ! 630: } else if (q->p_stat == SSTOP) { ! 631: psignal(q, SIGHUP); ! 632: psignal(q, SIGCONT); ! 633: } ! 634: (void) spgrp(q, -1); ! 635: } ! 636: wakeup((caddr_t)p->p_pptr); ! 637: if (p->p_trace) ! 638: wakeup((caddr_t)p->p_trace); ! 639: psignal(p->p_pptr, SIGCHLD); ! 640: swtch(); ! 641: } ! 642: ! 643: wait() ! 644: { ! 645: struct vtimes vm; ! 646: struct vtimes *vp; ! 647: ! 648: if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { ! 649: wait1(0, (struct vtimes *)0); ! 650: return; ! 651: } ! 652: vp = (struct vtimes *)u.u_ar0[R1]; ! 653: wait1(u.u_ar0[R0], &vm); ! 654: if (u.u_error) ! 655: return; ! 656: (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); ! 657: } ! 658: ! 659: /* ! 660: * Wait system call. ! 661: * Search for a terminated (zombie) child, ! 662: * finally lay it to rest, and collect its status. ! 663: * Look also for stopped (traced) children, ! 664: * and pass back status from them. ! 665: */ ! 666: wait1(options, vp) ! 667: register options; ! 668: struct vtimes *vp; ! 669: { ! 670: register f; ! 671: register struct proc *p; ! 672: register struct proc *myp; /* optimization */ ! 673: ! 674: f = 0; ! 675: myp = u.u_procp; ! 676: loop: ! 677: for(p = proc; p < procNPROC; p++) { ! 678: if (p->p_stat == 0 || p->p_pptr != myp) ! 679: continue; ! 680: f++; ! 681: if(p->p_stat == SZOMB) { ! 682: u.u_r.r_val1 = p->p_pid; ! 683: u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; ! 684: if (vp) ! 685: *vp = ((struct xproc *)p)->xp_vm; ! 686: vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); ! 687: p->p_stat = 0; ! 688: /* if it mattered, we could bzero(p, sizeof(*p)) here */ ! 689: if (p == procNPROC - 1) { ! 690: do ! 691: --p; ! 692: while (p->p_stat == 0); ! 693: procNPROC = p + 1; ! 694: } ! 695: return; ! 696: } ! 697: if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && ! 698: (p->p_flag&STRC)==0) { ! 699: p->p_flag |= SWTED; ! 700: u.u_r.r_val1 = p->p_pid; ! 701: u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; ! 702: return; ! 703: } ! 704: } ! 705: if (f==0) { ! 706: u.u_error = ECHILD; ! 707: return; ! 708: } ! 709: if (options&WNOHANG) { ! 710: u.u_r.r_val1 = 0; ! 711: return; ! 712: } ! 713: sleep((caddr_t)myp, PWAIT); ! 714: goto loop; ! 715: } ! 716: ! 717: /* ! 718: * fork system call. ! 719: */ ! 720: fork() ! 721: { ! 722: register struct proc *p1, *p2; ! 723: register int a, pid; ! 724: static int mpid = 0; ! 725: ! 726: u.u_cdmap = zdmap; ! 727: u.u_csmap = zdmap; ! 728: if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) ! 729: goto out; ! 730: retry: ! 731: pid = ++mpid; ! 732: if (pid > MAXPID) ! 733: pid = mpid = 1; ! 734: a = 0; ! 735: p2 = NULL; ! 736: for(p1 = proc; p1 < procNPROC; p1++) { ! 737: if (p1->p_stat == 0) { ! 738: if (p2 == NULL) ! 739: p2 = p1; ! 740: continue; ! 741: } ! 742: if (p1->p_pid == pid || p1->p_pgrp == pid) ! 743: goto retry; ! 744: if (p1->p_uid == u.u_uid) ! 745: a++; ! 746: } ! 747: if (p2 == NULL) { /* try pushing up high water mark */ ! 748: for (; p1 < &proc[proccnt]; p1++) ! 749: if (p1->p_stat == 0) { ! 750: p2 = p1; ! 751: p1++; ! 752: break; ! 753: } ! 754: procNPROC = p1; ! 755: } ! 756: /* ! 757: * Disallow if ! 758: * No processes at all; ! 759: * not su and too many procs owned; or ! 760: * not su and would take last slot. ! 761: */ ! 762: if (p2==NULL) ! 763: tablefull("proc"); ! 764: if (p2==NULL || (u.u_uid!=0 && (p2==&proc[proccnt-1] || a>MAXUPRC))) { ! 765: u.u_error = EAGAIN; ! 766: (void) vsexpand(0, &u.u_cdmap, 1); ! 767: (void) vsexpand(0, &u.u_csmap, 1); ! 768: goto out; ! 769: } ! 770: p1 = u.u_procp; ! 771: if(newproc(p2, pid)) { ! 772: u.u_r.r_val1 = p1->p_pid; ! 773: u.u_r.r_val2 = 1; /* child */ ! 774: u.u_start = time; ! 775: u.u_acflag = AFORK; ! 776: u.u_nbadio = 0; ! 777: return; ! 778: } ! 779: u.u_r.r_val1 = pid; ! 780: out: ! 781: u.u_r.r_val2 = 0; ! 782: } ! 783: ! 784: /* ! 785: * break system call. ! 786: * -- bad planning: "break" is a dirty word in C. ! 787: */ ! 788: sbreak() ! 789: { ! 790: struct a { ! 791: char *nsiz; ! 792: }; ! 793: register int n, d; ! 794: ! 795: /* ! 796: * set n to new data size ! 797: * set d to new-old ! 798: */ ! 799: ! 800: n = btoc(((struct a *)u.u_ap)->nsiz); ! 801: #if NOTDEF ! 802: if (!u.u_sep) ! 803: #endif ! 804: n -= ctos(u.u_tsize) * stoc(1); ! 805: if (n < 0) ! 806: n = 0; ! 807: d = clrnd(n - u.u_dsize); ! 808: if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) { ! 809: u.u_error = ENOMEM; ! 810: return; ! 811: } ! 812: if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) ! 813: return; ! 814: if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) ! 815: return; ! 816: expand(d, P0BR); ! 817: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.