1 /* kern_proc.c 4.4 02/01/81 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/map.h" 6 #include "../h/mtpr.h" 7 #include "../h/dir.h" 8 #include "../h/user.h" 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" 15 #include "/usr/include/wait.h" 16 #include "../h/pte.h" 17 #include "../h/vm.h" 18 #include "../h/text.h" 19 #include "../h/psl.h" 20 #include "../h/vlimit.h" 21 #include "../h/file.h" 22 23 /* 24 * exec system call, with and without environments. 25 */ 26 struct execa { 27 char *fname; 28 char **argp; 29 char **envp; 30 }; 31 32 exec() 33 { 34 ((struct execa *)u.u_ap)->envp = NULL; 35 exece(); 36 } 37 38 exece() 39 { 40 register nc; 41 register char *cp; 42 register struct buf *bp; 43 register struct execa *uap; 44 int na, ne, ucp, ap, c; 45 int indir, uid, gid; 46 char *sharg; 47 struct inode *ip; 48 swblk_t bno; 49 char cfname[DIRSIZ]; 50 char cfarg[SHSIZE]; 51 52 if ((ip = namei(uchar, 0)) == NULL) 53 return; 54 55 bno = 0; 56 bp = 0; 57 indir = 0; 58 uid = u.u_uid; 59 gid = u.u_gid; 60 61 if (ip->i_mode & ISUID) 62 uid = ip->i_uid; 63 if (ip->i_mode & ISGID) 64 gid = ip->i_gid; 65 66 again: 67 if(access(ip, IEXEC)) 68 goto bad; 69 if((ip->i_mode & IFMT) != IFREG || 70 (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 71 u.u_error = EACCES; 72 goto bad; 73 } 74 75 /* 76 * Read in first few bytes of file for segment sizes, ux_mag: 77 * 407 = plain executable 78 * 410 = RO text 79 * 413 = demand paged RO text 80 * Also an ASCII line beginning with #! is 81 * the file name of a ``shell'' and arguments may be prepended 82 * to the argument list if given here. 83 * 84 * SHELL NAMES ARE LIMITED IN LENGTH. 85 * 86 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 87 * THE ASCII LINE. 88 */ 89 u.u_base = (caddr_t)&u.u_exdata; 90 u.u_count = sizeof(u.u_exdata); 91 u.u_offset = 0; 92 u.u_segflg = 1; 93 readi(ip); 94 u.u_segflg = 0; 95 if(u.u_error) 96 goto bad; 97 if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) 98 && u.u_exdata.ux_shell[0] != '#') { 99 u.u_error = ENOEXEC; 100 goto bad; 101 } 102 switch (u.u_exdata.ux_mag) { 103 104 case 0407: 105 u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; 106 u.u_exdata.ux_tsize = 0; 107 break; 108 109 case 0413: 110 case 0410: 111 if (u.u_exdata.ux_tsize == 0) { 112 u.u_error = ENOEXEC; 113 goto bad; 114 } 115 break; 116 117 default: 118 if (u.u_exdata.ux_shell[0] != '#' || 119 u.u_exdata.ux_shell[1] != '!' || 120 indir) { 121 u.u_error = ENOEXEC; 122 goto bad; 123 } 124 cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ 125 while (cp < &u.u_exdata.ux_shell[SHSIZE]) { 126 if (*cp == '\t') 127 *cp = ' '; 128 else if (*cp == '\n') { 129 *cp = '\0'; 130 break; 131 } 132 cp++; 133 } 134 if (*cp != '\0') { 135 u.u_error = ENOEXEC; 136 goto bad; 137 } 138 cp = &u.u_exdata.ux_shell[2]; 139 while (*cp == ' ') 140 cp++; 141 u.u_dirp = cp; 142 while (*cp && *cp != ' ') 143 cp++; 144 sharg = NULL; 145 if (*cp) { 146 *cp++ = '\0'; 147 while (*cp == ' ') 148 cp++; 149 if (*cp) { 150 bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 151 sharg = cfarg; 152 } 153 } 154 bcopy((caddr_t)u.u_dbuf, (caddr_t)cfname, DIRSIZ); 155 indir = 1; 156 iput(ip); 157 ip = namei(schar, 0); 158 if (ip == NULL) 159 return; 160 goto again; 161 } 162 163 /* 164 * Collect arguments on "file" in swap space. 165 */ 166 na = 0; 167 ne = 0; 168 nc = 0; 169 uap = (struct execa *)u.u_ap; 170 if ((bno = malloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { 171 swkill(u.u_procp, "exece"); 172 goto bad; 173 } 174 if (bno % CLSIZE) 175 panic("execa malloc"); 176 if (uap->argp) for (;;) { 177 ap = NULL; 178 if (na == 1 && indir) { 179 if (sharg == NULL) 180 ap = (int)uap->fname; 181 } else if (na == 2 && indir && sharg != NULL) 182 ap = (int)uap->fname; 183 else if (uap->argp) { 184 ap = fuword((caddr_t)uap->argp); 185 uap->argp++; 186 } 187 if (ap==NULL && uap->envp) { 188 uap->argp = NULL; 189 if ((ap = fuword((caddr_t)uap->envp)) == NULL) 190 break; 191 uap->envp++; 192 ne++; 193 } 194 if (ap==NULL) 195 break; 196 na++; 197 if(ap == -1) 198 u.u_error = EFAULT; 199 do { 200 if (nc >= NCARGS-1) 201 u.u_error = E2BIG; 202 if (indir && na == 2 && sharg != NULL) 203 c = *sharg++ & 0377; 204 else if ((c = fubyte((caddr_t)ap++)) < 0) 205 u.u_error = EFAULT; 206 if (u.u_error) { 207 if (bp) 208 brelse(bp); 209 bp = 0; 210 goto badarg; 211 } 212 if ((nc&BMASK) == 0) { 213 if (bp) 214 bdwrite(bp); 215 bp = getblk(argdev, 216 (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); 217 cp = bp->b_un.b_addr; 218 } 219 nc++; 220 *cp++ = c; 221 } while (c>0); 222 } 223 if (bp) 224 bdwrite(bp); 225 bp = 0; 226 nc = (nc + NBPW-1) & ~(NBPW-1); 227 if (indir) 228 bcopy((caddr_t)cfname, (caddr_t)u.u_dbuf, DIRSIZ); 229 getxfile(ip, nc + (na+4)*NBPW, uid, gid); 230 if (u.u_error) { 231 badarg: 232 for (c = 0; c < nc; c += BSIZE) 233 if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) { 234 bp->b_flags |= B_AGE; /* throw away */ 235 bp->b_flags &= ~B_DELWRI; /* cancel io */ 236 brelse(bp); 237 bp = 0; 238 } 239 goto bad; 240 } 241 242 /* 243 * copy back arglist 244 */ 245 246 ucp = USRSTACK - nc - NBPW; 247 ap = ucp - na*NBPW - 3*NBPW; 248 u.u_ar0[SP] = ap; 249 (void) suword((caddr_t)ap, na-ne); 250 nc = 0; 251 for (;;) { 252 ap += NBPW; 253 if (na==ne) { 254 (void) suword((caddr_t)ap, 0); 255 ap += NBPW; 256 } 257 if (--na < 0) 258 break; 259 (void) suword((caddr_t)ap, ucp); 260 do { 261 if ((nc&BMASK) == 0) { 262 if (bp) 263 brelse(bp); 264 bp = bread(argdev, 265 (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); 266 bp->b_flags |= B_AGE; /* throw away */ 267 bp->b_flags &= ~B_DELWRI; /* cancel io */ 268 cp = bp->b_un.b_addr; 269 } 270 (void) subyte((caddr_t)ucp++, (c = *cp++)); 271 nc++; 272 } while(c&0377); 273 } 274 (void) suword((caddr_t)ap, 0); 275 (void) suword((caddr_t)ucp, 0); 276 setregs(); 277 bad: 278 if (bp) 279 brelse(bp); 280 if (bno) 281 mfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); 282 iput(ip); 283 } 284 285 /* 286 * Read in and set up memory for executed file. 287 */ 288 getxfile(ip, nargc, uid, gid) 289 register struct inode *ip; 290 { 291 register size_t ts, ds, ss; 292 int pagi; 293 294 if (u.u_exdata.ux_mag == 0413) 295 pagi = SPAGI; 296 else 297 pagi = 0; 298 299 if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { 300 register struct file *fp; 301 302 for (fp = file; fp < &file[NFILE]; fp++) 303 if (fp->f_inode == ip && (fp->f_flag&FWRITE)) { 304 u.u_error = ETXTBSY; 305 goto bad; 306 } 307 } 308 309 /* 310 * find text and data sizes 311 * try them out for possible 312 * exceed of max sizes 313 */ 314 315 ts = clrnd(btoc(u.u_exdata.ux_tsize)); 316 ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); 317 ss = clrnd(SSIZE + btoc(nargc)); 318 if (chksize(ts, ds, ss)) 319 goto bad; 320 u.u_cdmap = zdmap; 321 u.u_csmap = zdmap; 322 if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 323 goto bad; 324 325 /* 326 * At this point, committed to the new image! 327 * Release virtual memory resources of old process, and 328 * initialize the virtual memory of the new process. 329 * If we resulted from vfork(), instead wakeup our 330 * parent who will set SVFDONE when he has taken back 331 * our resources. 332 */ 333 u.u_prof.pr_scale = 0; 334 if ((u.u_procp->p_flag & SVFORK) == 0) 335 vrelvm(); 336 else { 337 u.u_procp->p_flag &= ~SVFORK; 338 u.u_procp->p_flag |= SKEEP; 339 wakeup((caddr_t)u.u_procp); 340 while ((u.u_procp->p_flag & SVFDONE) == 0) 341 sleep((caddr_t)u.u_procp, PZERO - 1); 342 u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 343 } 344 u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM|SNUSIG); 345 u.u_procp->p_flag |= pagi; 346 u.u_dmap = u.u_cdmap; 347 u.u_smap = u.u_csmap; 348 vgetvm(ts, ds, ss); 349 350 if (pagi == 0) { 351 /* 352 * Read in data segment. 353 */ 354 u.u_base = (char *)ctob(ts); 355 u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; 356 u.u_count = u.u_exdata.ux_dsize; 357 readi(ip); 358 } 359 xalloc(ip, pagi); 360 if (pagi && u.u_procp->p_textp) 361 vinifod((struct fpte *)dptopte(u.u_procp, 0), 362 PG_FTEXT, u.u_procp->p_textp->x_iptr, 363 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); 364 365 /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 366 mtpr(TBIA, 0); 367 368 /* 369 * set SUID/SGID protections, if no tracing 370 */ 371 if ((u.u_procp->p_flag&STRC)==0) { 372 #ifndef MELB 373 if(u.u_uid != 0) 374 #endif 375 { 376 u.u_uid = uid; 377 u.u_procp->p_uid = uid; 378 } 379 u.u_gid = gid; 380 } else 381 psignal(u.u_procp, SIGTRAP); 382 u.u_tsize = ts; 383 u.u_dsize = ds; 384 u.u_ssize = ss; 385 bad: 386 return; 387 } 388 389 /* 390 * Clear registers on exec 391 */ 392 setregs() 393 { 394 register int (**rp)(); 395 register i; 396 #ifdef UCBIPC 397 register struct port *pt; 398 #endif UCBIPC 399 long sigmask; 400 401 for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG]; 402 sigmask <<= 1, rp++) { 403 switch (*rp) { 404 405 case SIG_IGN: 406 case SIG_DFL: 407 case SIG_HOLD: 408 continue; 409 410 default: 411 /* 412 * Normal or deferring catch; revert to default. 413 */ 414 (void) spl6(); 415 *rp = SIG_DFL; 416 if ((int)*rp & 1) 417 u.u_procp->p_siga0 |= sigmask; 418 else 419 u.u_procp->p_siga1 &= ~sigmask; 420 if ((int)*rp & 2) 421 u.u_procp->p_siga1 |= sigmask; 422 else 423 u.u_procp->p_siga1 &= ~sigmask; 424 (void) spl0(); 425 continue; 426 } 427 } 428 /* 429 for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 430 *rp++ = 0; 431 */ 432 u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ 433 for(i=0; i<NOFILE; i++) { 434 if (u.u_pofile[i]&EXCLOSE) { 435 #ifndef UCBIPC 436 closef(u.u_ofile[i]); 437 u.u_ofile[i] = NULL; 438 #else UCBIPC 439 if (u.u_pofile[i]&ISPORT) { 440 pt = u.u_oport[i]; 441 if (--pt->pt_count == 0) 442 ptclose(pt); 443 u.u_pofile[i] &= ~ISPORT; 444 u.u_oport[i] = NULL; 445 } else { 446 closef(u.u_ofile[i]); 447 u.u_ofile[i] = NULL; 448 } 449 #endif UCBIPC 450 u.u_pofile[i] &= ~EXCLOSE; 451 } 452 } 453 /* 454 * Remember file name for accounting. 455 */ 456 u.u_acflag &= ~AFORK; 457 bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ); 458 } 459 460 /* 461 * exit system call: 462 * pass back caller's arg 463 */ 464 rexit() 465 { 466 register struct a { 467 int rval; 468 } *uap; 469 470 uap = (struct a *)u.u_ap; 471 exit((uap->rval & 0377) << 8); 472 } 473 474 /* 475 * Release resources. 476 * Save u. area for parent to look at. 477 * Enter zombie state. 478 * Wake up parent and init processes, 479 * and dispose of children. 480 */ 481 exit(rv) 482 { 483 register int i; 484 register struct proc *p, *q; 485 register struct file *f; 486 #ifdef UCBIPC 487 register struct port *pt; 488 #endif UCBIPC 489 register int x; 490 491 #ifdef PGINPROF 492 vmsizmon(); 493 #endif 494 p = u.u_procp; 495 p->p_flag &= ~(STRC|SULOCK); 496 p->p_flag |= SWEXIT; 497 p->p_clktim = 0; 498 (void) spl6(); 499 if ((int)SIG_IGN & 1) 500 p->p_siga0 = ~0; 501 else 502 p->p_siga0 = 0; 503 if ((int)SIG_IGN & 2) 504 p->p_siga1 = ~0; 505 else 506 p->p_siga1 = 0; 507 (void) spl0(); 508 p->p_cpticks = 0; 509 p->p_pctcpu = 0; 510 for(i=0; i<NSIG; i++) 511 u.u_signal[i] = SIG_IGN; 512 /* 513 * Release virtual memory. If we resulted from 514 * a vfork(), instead give the resources back to 515 * the parent. 516 */ 517 if ((p->p_flag & SVFORK) == 0) 518 vrelvm(); 519 else { 520 p->p_flag &= ~SVFORK; 521 wakeup((caddr_t)p); 522 while ((p->p_flag & SVFDONE) == 0) 523 sleep((caddr_t)p, PZERO - 1); 524 p->p_flag &= ~SVFDONE; 525 } 526 for(i=0; i<NOFILE; i++) { 527 #ifndef UCBIPC 528 f = u.u_ofile[i]; 529 u.u_ofile[i] = NULL; 530 closef(f); 531 #else UCBIPC 532 if (u.u_pofile[i]&ISPORT) { 533 pt = u.u_oport[i]; 534 if (--pt->pt_count == 0) 535 ptclose(pt); 536 u.u_oport[i] = NULL; 537 } else { 538 f = u.u_ofile[i]; 539 u.u_ofile[i] = NULL; 540 closef(f); 541 } 542 #endif UCBIPC 543 } 544 plock(u.u_cdir); 545 iput(u.u_cdir); 546 if (u.u_rdir) { 547 plock(u.u_rdir); 548 iput(u.u_rdir); 549 } 550 u.u_limit[LIM_FSIZE] = INFINITY; 551 acct(); 552 vrelpt(u.u_procp); 553 vrelu(u.u_procp, 0); 554 multprog--; 555 /* spl7(); /* clock will get mad because of overlaying */ 556 p->p_stat = SZOMB; 557 noproc = 1; 558 i = PIDHASH(p->p_pid); 559 x = p - proc; 560 if (pidhash[i] == x) 561 pidhash[i] = p->p_idhash; 562 else { 563 for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 564 if (proc[i].p_idhash == x) { 565 proc[i].p_idhash = p->p_idhash; 566 goto done; 567 } 568 panic("exit"); 569 } 570 if (p->p_pid == 1) 571 panic("init died"); 572 done: 573 ((struct xproc *)p)->xp_xstat = rv; /* overlay */ 574 ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ 575 vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); 576 for(q = &proc[0]; q < &proc[NPROC]; q++) 577 if(q->p_pptr == p) { 578 q->p_pptr = &proc[1]; 579 q->p_ppid = 1; 580 wakeup((caddr_t)&proc[1]); 581 /* 582 * Traced processes are killed 583 * since their existence means someone is screwing up. 584 * Stopped processes are sent a hangup and a continue. 585 * This is designed to be ``safe'' for setuid 586 * processes since they must be willing to tolerate 587 * hangups anyways. 588 */ 589 if (q->p_flag&STRC) { 590 q->p_flag &= ~STRC; 591 psignal(q, SIGKILL); 592 } else if (q->p_stat == SSTOP) { 593 psignal(q, SIGHUP); 594 psignal(q, SIGCONT); 595 } 596 /* 597 * Protect this process from future 598 * tty signals, clear TSTP/TTIN/TTOU if pending, 599 * and set SDETACH bit on procs. 600 */ 601 (void) spgrp(q, -1); 602 } 603 wakeup((caddr_t)p->p_pptr); 604 psignal(p->p_pptr, SIGCHLD); 605 swtch(); 606 } 607 608 wait() 609 { 610 struct vtimes vm; 611 struct vtimes *vp; 612 613 if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 614 wait1(0, (struct vtimes *)0); 615 return; 616 } 617 vp = (struct vtimes *)u.u_ar0[R1]; 618 wait1(u.u_ar0[R0], &vm); 619 if (u.u_error) 620 return; 621 (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); 622 } 623 624 /* 625 * Wait system call. 626 * Search for a terminated (zombie) child, 627 * finally lay it to rest, and collect its status. 628 * Look also for stopped (traced) children, 629 * and pass back status from them. 630 */ 631 wait1(options, vp) 632 register options; 633 struct vtimes *vp; 634 { 635 register f; 636 register struct proc *p; 637 638 f = 0; 639 loop: 640 for(p = &proc[0]; p < &proc[NPROC]; p++) 641 if(p->p_pptr == u.u_procp) { 642 f++; 643 if(p->p_stat == SZOMB) { 644 u.u_r.r_val1 = p->p_pid; 645 u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 646 ((struct xproc *)p)->xp_xstat = 0; 647 if (vp) 648 *vp = ((struct xproc *)p)->xp_vm; 649 vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); 650 ((struct xproc *)p)->xp_vm = zvms; 651 p->p_stat = NULL; 652 p->p_pid = 0; 653 p->p_ppid = 0; 654 p->p_pptr = 0; 655 p->p_sig = 0; 656 p->p_siga0 = 0; 657 p->p_siga1 = 0; 658 p->p_pgrp = 0; 659 p->p_flag = 0; 660 p->p_wchan = 0; 661 p->p_cursig = 0; 662 return; 663 } 664 if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && 665 (p->p_flag&STRC || options&WUNTRACED)) { 666 p->p_flag |= SWTED; 667 u.u_r.r_val1 = p->p_pid; 668 u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 669 return; 670 } 671 } 672 if (f==0) { 673 u.u_error = ECHILD; 674 return; 675 } 676 if (options&WNOHANG) { 677 u.u_r.r_val1 = 0; 678 return; 679 } 680 if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 681 u.u_eosys = RESTARTSYS; 682 return; 683 } 684 sleep((caddr_t)u.u_procp, PWAIT); 685 goto loop; 686 } 687 688 /* 689 * fork system call. 690 */ 691 fork() 692 { 693 694 u.u_cdmap = zdmap; 695 u.u_csmap = zdmap; 696 if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 697 u.u_r.r_val2 = 0; 698 return; 699 } 700 fork1(0); 701 } 702 703 fork1(isvfork) 704 { 705 register struct proc *p1, *p2; 706 register a; 707 708 a = 0; 709 p2 = NULL; 710 for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { 711 if (p1->p_stat==NULL && p2==NULL) 712 p2 = p1; 713 else { 714 if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 715 a++; 716 } 717 } 718 /* 719 * Disallow if 720 * No processes at all; 721 * not su and too many procs owned; or 722 * not su and would take last slot. 723 */ 724 if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { 725 u.u_error = EAGAIN; 726 if (!isvfork) { 727 (void) vsexpand(0, &u.u_cdmap, 1); 728 (void) vsexpand(0, &u.u_csmap, 1); 729 } 730 goto out; 731 } 732 p1 = u.u_procp; 733 if(newproc(isvfork)) { 734 u.u_r.r_val1 = p1->p_pid; 735 u.u_r.r_val2 = 1; /* child */ 736 u.u_start = time; 737 u.u_acflag = AFORK; 738 return; 739 } 740 u.u_r.r_val1 = p2->p_pid; 741 742 out: 743 u.u_r.r_val2 = 0; 744 } 745 746 /* 747 * break system call. 748 * -- bad planning: "break" is a dirty word in C. 749 */ 750 sbreak() 751 { 752 struct a { 753 char *nsiz; 754 }; 755 register int n, d; 756 757 /* 758 * set n to new data size 759 * set d to new-old 760 */ 761 762 n = btoc(((struct a *)u.u_ap)->nsiz); 763 if (!u.u_sep) 764 n -= ctos(u.u_tsize) * stoc(1); 765 if (n < 0) 766 n = 0; 767 d = clrnd(n - u.u_dsize); 768 if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) { 769 u.u_error = ENOMEM; 770 return; 771 } 772 if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) 773 return; 774 if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) 775 return; 776 expand(d, P0BR); 777 } 778