|
|
1.1 ! root 1: /* $Header: /src386/STREAMS/coh.386/RCS/exec.c,v 2.3 93/08/09 13:35:18 bin Exp Locker: bin $ */ ! 2: /* ! 3: * Processing of the exec () system call. ! 4: * ! 5: * $Log: exec.c,v $ ! 6: * Revision 2.3 93/08/09 13:35:18 bin ! 7: * Kernel 82 changes ! 8: * ! 9: * Revision 2.2 93/07/26 15:22:36 nigel ! 10: * Nigel's R80 ! 11: * ! 12: * Revision 2.3 93/07/26 14:47:30 nigel ! 13: * Nigel's R80 ! 14: * ! 15: */ ! 16: ! 17: #include <common/_gregset.h> ! 18: #include <common/_tricks.h> ! 19: #include <kernel/sigproc.h> ! 20: ! 21: #include <sys/coherent.h> ! 22: #include <sys/acct.h> ! 23: #include <sys/buf.h> ! 24: #include <canon.h> ! 25: #include <sys/con.h> ! 26: #include <sys/errno.h> ! 27: #include <fcntl.h> ! 28: #include <sys/filsys.h> ! 29: #include <sys/ino.h> ! 30: #include <sys/inode.h> ! 31: #include <sys/file.h> ! 32: #include <a.out.h> ! 33: #include <l.out.h> ! 34: #include <sys/proc.h> ! 35: #include <sys/sched.h> ! 36: #include <sys/seg.h> ! 37: #include <signal.h> ! 38: #include <sys/stat.h> ! 39: #include <sys/fd.h> ! 40: ! 41: /* ! 42: * Round section and segment start address to nearest lower click boundary. ! 43: */ ! 44: ! 45: static void ! 46: xecrnd(xsp) ! 47: struct xecseg * xsp; ! 48: { ! 49: int diff; ! 50: ! 51: diff = xsp->fbase & (NBPC - 1); ! 52: xsp->mbase -= diff; ! 53: xsp->fbase -= diff; ! 54: xsp->size += diff; ! 55: } ! 56: ! 57: /* ! 58: * Pass control to an image in a file. ! 59: * Make sure the format is acceptable. Release ! 60: * the old segments. Read in the new ones. Some special ! 61: * care is taken so that shared and (more important) shared ! 62: * and separated images can be run on the 8086. ! 63: */ ! 64: ! 65: pexece(np, argp, envp, regsetp) ! 66: char * np; ! 67: char * argp []; ! 68: char * envp []; ! 69: gregset_t * regsetp; ! 70: { ! 71: struct xechdr head; ! 72: register INODE *ip; /* Load file INODE */ ! 73: register PROC *pp; /* A cheap copy of SELF */ ! 74: register SEG *segp; ! 75: SEG *ssegp; ! 76: register int i; /* For looping over segments*/ ! 77: int roundup; ! 78: int shrdsize; ! 79: struct xecnode * xlist = NULL; /* list head */ ! 80: struct xecnode * xp; ! 81: struct xecseg tempseg; ! 82: unsigned int textSize; ! 83: struct direct dir; ! 84: ! 85: pp = SELF; ! 86: memset (& head, 0, sizeof (head)); ! 87: if ((ip = exlopen (& head, np, & shrdsize, & xlist, & dir)) == NULL) ! 88: goto done; ! 89: ! 90: roundup = shrdsize & 0xf; ! 91: ssegp = exstack (& head, argp, envp, ! 92: __xmode_286 (regsetp) ? sizeof (short) : ! 93: sizeof (int)); ! 94: ! 95: if (! ssegp) { ! 96: idetach(ip); ! 97: goto done; ! 98: } ! 99: ! 100: /* Release shared memory. */ ! 101: shmAllDt (); ! 102: ! 103: /* ! 104: * At this point the file has been ! 105: * validated as an object module, and the ! 106: * argument list has been built. Release all of ! 107: * the original segments. At this point we have ! 108: * committed to the new image. A "sys exec" that ! 109: * gets an I/O error is doomed. ! 110: * NOTE: User-area segment is NOT released. ! 111: * Segment pointer in proc is erased BEFORE invoking sfree(). ! 112: */ ! 113: ! 114: for (i = 1 ; i < NUSEG ; ++ i) { ! 115: if ((segp = pp->p_segp [i]) != NULL) { ! 116: pp->p_segp [i] = NULL; ! 117: sfree (segp); ! 118: } ! 119: } ! 120: pp->p_segp [SISTACK] = ssegp; ! 121: ! 122: /* ! 123: * Read in the loadable segments. ! 124: */ ! 125: ! 126: switch (head.magic) { ! 127: case XMAGIC (I286MAGIC, I_MAGIC): ! 128: if ((segp = ssalloc (ip, SFTEXT, ! 129: head.segs [SISTEXT].size)) == NULL) ! 130: goto out; ! 131: pp->p_segp [SISTEXT] = segp; ! 132: ! 133: if (! exsread (segp, ip, & head.segs [SISTEXT], 0)) ! 134: goto out; ! 135: ! 136: if ((segp = ssalloc (ip, 0, roundup + ! 137: head.segs [SIPDATA].size + ! 138: head.segs [SIBSS].size)) == NULL) ! 139: goto out; ! 140: pp->p_segp [SIPDATA] = segp; ! 141: ! 142: if (! exsread(segp, ip, & head.segs [SIPDATA], shrdsize)) { ! 143: goto out; ! 144: } ! 145: head.segs [SIPDATA].size += roundup; ! 146: break; ! 147: ! 148: case XMAGIC (I386MAGIC, Z_MAGIC): ! 149: /* ! 150: * Round segment address down to nearest click boundary. ! 151: * Ciaran did this. I'm not sure why, but will preserve ! 152: * it for now. -hws- ! 153: */ ! 154: ! 155: tempseg = head.segs [SISTEXT]; /* save pre-rounding value */ ! 156: xecrnd (head.segs + SISTEXT); ! 157: xecrnd (head.segs + SIPDATA); ! 158: ! 159: /* ! 160: * Compute text segment size by taking highest address ! 161: * seen in any text section. ! 162: */ ! 163: ! 164: textSize = head.segs [SISTEXT].size + ! 165: head.segs [SISTEXT].mbase; ! 166: for (xp = xlist ; xp ; xp = xp->xn) { ! 167: unsigned int tmpSize; ! 168: if (xp->segtype != SISTEXT) ! 169: continue; ! 170: tmpSize = xp->xseg.size + xp->xseg.mbase; ! 171: if (tmpSize > textSize) ! 172: textSize = tmpSize; ! 173: } ! 174: ! 175: /* Entry point must be within text segment. */ ! 176: if (head.entry >= textSize) ! 177: goto out; ! 178: ! 179: if ((segp = ssalloc (ip, SFTEXT | SFSHRX, ! 180: textSize)) == NULL) ! 181: goto out; ! 182: ! 183: pp->p_segp [SISTEXT] = segp; ! 184: ! 185: if (segp->s_ip == 0) { ! 186: if (! exsread (segp, ip, & tempseg, 0)) ! 187: goto out; ! 188: ! 189: /* load additional text sections, if any */ ! 190: for (xp = xlist ; xp ; xp = xp->xn) { ! 191: if (xp->segtype != SISTEXT) ! 192: continue; ! 193: if (! exsread (segp, ip, & xlist->xseg, 0)) ! 194: goto out; ! 195: } ! 196: ! 197: segp->s_ip = ip; ! 198: ip->i_refc ++; ! 199: } ! 200: if ((segp = ssalloc (ip, 0, head.segs [SIPDATA].size + ! 201: head.segs[SIBSS].size)) == NULL) ! 202: goto out; ! 203: ! 204: pp->p_segp [SIPDATA] = segp; ! 205: ! 206: if (segp->s_ip == 0 && ! 207: ! exsread (segp, ip, & head.segs [SIPDATA], 0)) ! 208: goto out; ! 209: ! 210: /* Deallocate nodes hooked into xlist by exlopen. */ ! 211: while (xlist != NULL) { ! 212: struct xecnode * tmp = xlist->xn; ! 213: kfree (xlist); ! 214: xlist = tmp; ! 215: } ! 216: break; ! 217: ! 218: default: ! 219: panic("pexece"); ! 220: } ! 221: ! 222: if (sproto (& head) == 0) ! 223: goto out; ! 224: ! 225: /* ! 226: * At this point, and no earlier, we can modify the user register ! 227: * image for the new process because now we are committed to executing ! 228: * the new image. ! 229: * ! 230: * As a general security thing, we begin by zeroing out the user-level ! 231: * register image. ! 232: */ ! 233: ! 234: memset (regsetp, 0, sizeof (* regsetp)); ! 235: ! 236: switch (head.magic) { ! 237: case XMAGIC (I286MAGIC, I_MAGIC): ! 238: regsetp->_i286._cs = SEG_286_UII | R_USR; ! 239: regsetp->_i286._ss = regsetp->_i286._es = ! 240: regsetp->_i286._ds = SEG_286_UD | R_USR; ! 241: regsetp->_i286._ip = head.entry; ! 242: regsetp->_i286._usp = head.initsp; ! 243: break; ! 244: ! 245: case XMAGIC (I386MAGIC, Z_MAGIC): ! 246: regsetp->_i386._cs = SEG_386_UI | R_USR; ! 247: regsetp->_i386._ss = regsetp->_i386._es = ! 248: regsetp->_i386._ds = SEG_386_UD | R_USR; ! 249: regsetp->_i386._eip = head.entry; ! 250: regsetp->_i386._uesp = head.initsp; ! 251: break; ! 252: } ! 253: ! 254: ! 255: /* ! 256: * The new image is read in ! 257: * and mapped. Perform the final grunge ! 258: * (set-uid stuff, accounting, loading up ! 259: * registers, etc). ! 260: */ ! 261: ! 262: u.u_flag &= ~AFORK; ! 263: ! 264: memcpy (u.u_comm, dir.d_name, sizeof (u.u_comm)); ! 265: ! 266: if (iaccess (ip, IPR) == 0) { /* Can't read ? no dump or trace */ ! 267: pp->p_flags |= PFNDMP; ! 268: pp->p_flags &= ~PFTRAC; ! 269: } ! 270: ! 271: ! 272: /* ! 273: * Norm says Frank says we need to drop this for db to work. ! 274: */ ! 275: #if 0 ! 276: if (iaccess(ip, IPW) == 0) { /* Can't write ? no trace */ ! 277: pp->p_flags &= ~PFTRAC; ! 278: printf("Can't write - no trace! "); ! 279: u.u_error = 0; ! 280: } ! 281: #endif ! 282: ! 283: if ((ip->i_mode & ISUID) != 0) { /* Set user id ? no trace */ ! 284: pp->p_uid = u.u_uid = u.u_euid = ip->i_uid; ! 285: pp->p_flags &= ~PFTRAC; ! 286: } ! 287: ! 288: if ((ip->i_mode & ISGID) != 0) { /* Set group id ? no trace */ ! 289: u.u_egid = u.u_gid = ip->i_gid; ! 290: pp->p_flags &= ~PFTRAC; ! 291: } ! 292: ! 293: for (i = 0 ; i < NOFILE; i ++) { ! 294: int j = fdgetflags (i); ! 295: if (j != -1 && (j & FD_CLOEXEC) != 0) ! 296: fdclose (i); /* close fd on exec bit set */ ! 297: } ! 298: ! 299: ! 300: /* ! 301: * Default every signal that is not ignored. ! 302: */ ! 303: ! 304: for (i = 1 ; i <= NSIG ; ++ i) { ! 305: __sigaction_t act; ! 306: ! 307: curr_signal_action (i, NULL, & act); ! 308: if (act.sa_handler != SIG_IGN) { ! 309: act.sa_handler = SIG_DFL; ! 310: act.sa_flags = 0; ! 311: __SIGSET_EMPTY (act.sa_mask); ! 312: curr_signal_action (i, & act, NULL); ! 313: } ! 314: } ! 315: ! 316: if (pp->p_flags & PFTRAC) /* Being traced */ ! 317: sendsig (SIGTRAP, pp); ! 318: idetach (ip); ! 319: ! 320: /* initialize u area ndp fields */ ! 321: ndpNewProc (); ! 322: ! 323: segload (); ! 324: goto done; ! 325: ! 326: ! 327: /* ! 328: * Alas, exec() has failed.. ! 329: */ ! 330: out: ! 331: /* Deallocate nodes hooked into xlist by exlopen. */ ! 332: while (xlist != NULL) { ! 333: struct xecnode * tmp = xlist->xn; ! 334: kfree (xlist); ! 335: xlist = tmp; ! 336: } ! 337: ! 338: /* Release the INODE for the load file. */ ! 339: idetach (ip); ! 340: ! 341: /* If we allocated a text segment, let it go. */ ! 342: if ((segp = pp->p_segp [SISTEXT]) != NULL) { ! 343: pp->p_segp [SISTEXT] = NULL; ! 344: sfree (segp); ! 345: } ! 346: ! 347: /* If we allocated a data segment, let it go. */ ! 348: if ((segp = pp->p_segp[SIPDATA]) != NULL) { ! 349: pp->p_segp [SIPDATA] = NULL; ! 350: sfree (segp); ! 351: } ! 352: ! 353: /* ! 354: * Return through the "sys exit" code with a "SIGSYS", or with the ! 355: * signal actually received if we are aborting due to interrupted exec. ! 356: */ ! 357: ! 358: pexit (u.u_error == EINTR ? curr_signal_pending () : SIGSYS); ! 359: ! 360: done: ! 361: return 0; ! 362: } ! 363: ! 364: ! 365: /* ! 366: * Open a file, make sure it is l.out, coff, or v86 as well as ! 367: * executable. ! 368: * ! 369: * "xhp" points to a cleared xechdr supplied by the caller. ! 370: * "np" is the file name. ! 371: * "shrds" points to an int that will be written by exlopen(). ! 372: * *shrds is set nonzero only for shared l.out. ! 373: * ! 374: * If file is COFF, there may be multiple text (or data?) sections. ! 375: * Use "xlist" linked structure to keep track of variably many sections ! 376: * after the first text and data sections. ! 377: * ! 378: * return NULL if failure, else return inode pointer for the file. ! 379: */ ! 380: ! 381: INODE * ! 382: exlopen(xhp, np, shrds, xlist, dirent) ! 383: register struct xechdr *xhp; ! 384: char *np; ! 385: int *shrds; ! 386: struct xecnode ** xlist; ! 387: struct direct * dirent; ! 388: { ! 389: register INODE *ip; ! 390: int i, nscn, hdrsize; ! 391: register BUF *bp; ! 392: unsigned short magic; ! 393: struct ldheader head; ! 394: struct filehdr fhead; ! 395: struct aouthdr ahead; ! 396: struct scnhdr scnhdr; ! 397: IO io; ! 398: ! 399: /* ! 400: * Make sure the file is executable and read the header. Note that ! 401: * this about the only case of ftoi () with mode 'r' that actually ! 402: * uses the resulting filename information. ! 403: */ ! 404: ! 405: if (ftoi (np, 'r', & io, dirent)) ! 406: return NULL; ! 407: ! 408: ip = u.u_cdiri; ! 409: if (iaccess (ip, IPE) == 0) { ! 410: idetach (ip); ! 411: return NULL; ! 412: } ! 413: ! 414: if ((ip->i_mode & (IPE | (IPE << 3) | (IPE << 6))) == 0 || ! 415: (ip->i_mode & IFMT) != IFREG) { ! 416: u.u_error = EACCES; ! 417: idetach (ip); ! 418: return NULL; ! 419: } ! 420: ! 421: if ((bp = vread (ip, (daddr_t) 0)) == NULL) { ! 422: u.u_error = ENOEXEC; ! 423: idetach (ip); ! 424: return NULL; ! 425: } ! 426: ! 427: ! 428: /* ! 429: * Copy everything we need from the l.out header and check magic ! 430: * number and machine type. ! 431: */ ! 432: ! 433: * shrds = 0; ! 434: magic = * (unsigned short *) bp->b_vaddr; ! 435: canint (magic); ! 436: ! 437: switch (magic) { ! 438: case L_MAGIC: /* Coherent 286 format */ ! 439: memcpy (& head, bp->b_vaddr, sizeof (struct ldheader)); ! 440: ! 441: canint (head.l_machine); ! 442: if (head.l_machine != M_8086) ! 443: goto bad; ! 444: ! 445: for (i = 0 ; i < NXSEG ; i ++) ! 446: cansize (head.l_ssize [i]); ! 447: ! 448: canint (head.l_flag); ! 449: canvaddr (head.l_entry); ! 450: ! 451: /* ! 452: * If a shared and separated image ! 453: * has stuff in segments that makes it impossible ! 454: * to share, give an error immediately so that we don't ! 455: * lose the parent. ! 456: */ ! 457: head.l_flag &= LF_SHR | LF_SEP | LF_KER; ! 458: ! 459: if ((head.l_flag & LF_SEP) == 0 || ! 460: (head.l_flag & LF_KER) != 0 || ! 461: head.l_ssize [L_PRVI] || head.l_ssize [L_BSSI]) ! 462: goto bad; ! 463: ! 464: xhp->magic = XMAGIC (I286MAGIC,I_MAGIC); ! 465: xhp->entry = head.l_entry; ! 466: ! 467: xhp->segs [SISTEXT].fbase = sizeof (struct ldheader); ! 468: xhp->segs [SISTEXT].mbase = NBPS; ! 469: xhp->segs [SISTEXT].size = head.l_ssize [L_SHRI]; ! 470: ! 471: xhp->segs [SIPDATA].fbase = sizeof (struct ldheader) + ! 472: xhp->segs [SISTEXT].size; ! 473: xhp->segs [SIPDATA].mbase = 0; ! 474: xhp->segs [SIPDATA].size = head.l_ssize [L_SHRD] + ! 475: head.l_ssize [L_PRVD]; ! 476: if (head.l_flag & LF_SHR) ! 477: * shrds = head.l_ssize [L_SHRD]; ! 478: ! 479: xhp->segs [SIBSS].fbase = 0; ! 480: xhp->segs [SIBSS].mbase = xhp->segs [SIPDATA].size; ! 481: xhp->segs [SIBSS].size = head.l_ssize [L_BSSD]; ! 482: ! 483: xhp->segs [SISTACK].mbase = ISP_286; /* size 0, fbase 0 */ ! 484: brelease (bp); ! 485: return ip; ! 486: ! 487: case I386MAGIC: /* ... COFF */ ! 488: memcpy (& fhead, bp->b_vaddr, sizeof (struct filehdr)); ! 489: hdrsize = sizeof (ahead) + sizeof (fhead); ! 490: ! 491: if (fhead.f_opthdr != sizeof (ahead) || ! 492: (fhead.f_flags & F_EXEC) == 0 || ! 493: fhead.f_nscns * sizeof (scnhdr) > BSIZE) ! 494: goto bad; ! 495: ! 496: memcpy (& ahead, bp->b_vaddr + sizeof (fhead), ! 497: sizeof (ahead)); ! 498: if (ahead.magic != Z_MAGIC) ! 499: goto bad; ! 500: ! 501: xhp->magic = XMAGIC (I386MAGIC, ahead.magic); ! 502: xhp->entry = ahead.entry; ! 503: ! 504: for (i = 0 ; i < fhead.f_nscns ; i ++) { ! 505: memcpy (& scnhdr, ! 506: bp->b_vaddr + hdrsize + sizeof (scnhdr) * i, ! 507: sizeof (scnhdr)); ! 508: ! 509: switch ((int) (scnhdr.s_flags)) { ! 510: case STYP_INFO: ! 511: continue; ! 512: ! 513: case STYP_BSS: ! 514: nscn = SIBSS; ! 515: break; ! 516: ! 517: case STYP_TEXT: ! 518: nscn = SISTEXT; ! 519: break; ! 520: ! 521: case STYP_DATA: ! 522: nscn = SIPDATA; ! 523: break; ! 524: ! 525: default: ! 526: goto bad; ! 527: } ! 528: ! 529: /* Text/data shouldn't collide with stack. */ ! 530: if ((unsigned) scnhdr.s_vaddr >= ISP_386) ! 531: goto bad; ! 532: ! 533: /* Have we already seen a segment of this type? */ ! 534: if (xhp->segs [nscn].size) { ! 535: struct xecnode * tmp; ! 536: ! 537: if (nscn != SISTEXT) ! 538: goto bad; ! 539: ! 540: /* insert new node at head of "xlist" */ ! 541: tmp = (struct xecnode *) ! 542: kalloc (sizeof (struct xecnode)); ! 543: ! 544: if (tmp == NULL) { ! 545: printf ("can't kalloc(xecnode)\n"); ! 546: goto bad; ! 547: } ! 548: ! 549: tmp->xn = * xlist; ! 550: * xlist = tmp; ! 551: tmp->segtype = nscn; ! 552: tmp->xseg.mbase = scnhdr.s_vaddr; ! 553: tmp->xseg.fbase = scnhdr.s_scnptr; ! 554: tmp->xseg.size = scnhdr.s_size; ! 555: } else { ! 556: xhp->segs [nscn].mbase = scnhdr.s_vaddr; ! 557: xhp->segs [nscn].fbase = scnhdr.s_scnptr; ! 558: xhp->segs [nscn].size = scnhdr.s_size; ! 559: } ! 560: } ! 561: ! 562: /* Text and data segments must both be nonempty. */ ! 563: if (! xhp->segs [SISTEXT].size || ! xhp->segs [SIPDATA].size) ! 564: goto bad; ! 565: ! 566: xhp->entry = ahead.entry; ! 567: ! 568: xhp->segs [SISTACK].mbase = ISP_386; /* size 0, fbase 0 */ ! 569: xhp->magic = XMAGIC (I386MAGIC, ahead.magic); ! 570: brelease (bp); ! 571: return ip; ! 572: default: ! 573: bad: ! 574: brelease (bp); ! 575: u.u_error = ENOEXEC; ! 576: idetach (ip); ! 577: return NULL; ! 578: } ! 579: } ! 580: ! 581: static SEG * ! 582: exsread(sp, ip, xsp, shrdSz) ! 583: register SEG *sp; ! 584: INODE *ip; ! 585: struct xecseg *xsp; ! 586: int shrdSz; ! 587: { ! 588: register int sa, so; ! 589: IO io; ! 590: ! 591: sa = xsp->fbase; ! 592: so = xsp->mbase & (NBPC - 1); ! 593: ! 594: io.io_seg = IOPHY; ! 595: io.io_seek = sa; ! 596: io.io.pbase = MAPIO (sp->s_vmem, so); ! 597: io.io_flag = 0; ! 598: ! 599: if (shrdSz) { /* shared l.out? */ ! 600: ! 601: /* Load SHRD. */ ! 602: io.io_ioc = shrdSz; ! 603: sp->s_lrefc ++; ! 604: iread (ip, & io); ! 605: sp->s_lrefc --; ! 606: ! 607: if ((io.io_ioc = xsp->size - shrdSz) != 0) { ! 608: ! 609: /* Advance file and RAM offsets past SHRD. */ ! 610: sa += shrdSz; ! 611: so += shrdSz; ! 612: ! 613: /* Advance RAM offset to next 16-byte boundary. */ ! 614: so = (so + 15) & ~ 15; /* round up */ ! 615: ! 616: /* Load PRVD. */ ! 617: io.io_seg = IOPHY; ! 618: io.io_seek = sa; ! 619: io.io.pbase = MAPIO (sp->s_vmem, so); ! 620: io.io_flag = 0; ! 621: ! 622: sp->s_lrefc ++; ! 623: iread (ip, & io); ! 624: sp->s_lrefc --; ! 625: } ! 626: } else { /* NOT shared l.out */ ! 627: io.io_ioc = xsp->size; ! 628: ! 629: sp->s_lrefc ++; ! 630: iread (ip, & io); ! 631: sp->s_lrefc --; ! 632: } ! 633: ! 634: /* ! 635: * NIGEL: This perturbs me. This check seems to really belong ! 636: * somewhere at the top-level, and/or from testing the return values ! 637: * from the read calls. Why isn't the residual from the read tested? ! 638: */ ! 639: ! 640: if (curr_signal_pending ()) ! 641: u.u_error = EINTR; ! 642: ! 643: if (u.u_error == 0) ! 644: return sp; ! 645: return NULL; ! 646: } ! 647: ! 648: ! 649: struct adata { /* Storage for arg and env data */ ! 650: int np; /* Number of pointers in vector */ ! 651: int nc; /* Number of characters in strings */ ! 652: }; ! 653: ! 654: ! 655: /* ! 656: * Given a pointer to a list of arguments and a pointer to a list of ! 657: * environments, return a stack with the arguments and environments on it. ! 658: */ ! 659: ! 660: SEG * ! 661: exstack(xhp, argp, envp, wdin) ! 662: register struct xechdr *xhp; ! 663: caddr_t argp, envp; ! 664: { ! 665: register SEG *sp; /* Stack segment pointer */ ! 666: struct sdata { /* To keep segment pointers */ ! 667: caddr_t vp; /* Argv[i], envp[i] pointer */ ! 668: caddr_t cp; /* Argv[i][j], envp[i][j] pointer */ ! 669: } stk; ! 670: struct adata arg, env; ! 671: int chrsz, vecsz, stksz, wdmask, wdout, stkoff, stktop; ! 672: int stkenvp; ! 673: register int i; ! 674: ! 675: /* Validate and evaluate size of args and envs */ ! 676: if (! excount (argp, & arg, wdin) || ! excount (envp, & env, wdin)) ! 677: return NULL; ! 678: ! 679: /* Calculate stack size and allocate it */ ! 680: chrsz = __ROUND_UP_TO_MULTIPLE (arg.nc + env.nc, sizeof (int)); ! 681: vecsz = (arg.np + 1 + env.np + 1) * sizeof (long); ! 682: stksz = __ROUND_UP_TO_MULTIPLE (vecsz + chrsz + ISTSIZE, NBPC); ! 683: ! 684: if (stksz > MADSIZE || (sp = salloc (stksz, SFDOWN)) == NULL) { ! 685: u.u_error = E2BIG; ! 686: return NULL; ! 687: } ! 688: ! 689: /* Set up target stack */ ! 690: stktop = xhp->segs [SISTACK].mbase; ! 691: stk.cp = stktop - chrsz; ! 692: stk.vp = stktop - chrsz - vecsz; ! 693: stkoff = MAPIO (sp->s_vmem, stksz - stktop); ! 694: u.u_argc = arg.np; ! 695: u.u_argp = stk.vp; ! 696: wdmask = -1; ! 697: if (wdin == sizeof (short)) ! 698: wdmask = (unsigned short) wdmask; ! 699: ! 700: switch (stktop) { ! 701: ! 702: case ISP_386: ! 703: wdout = sizeof (long); ! 704: xhp->initsp = stk.vp - sizeof (long); ! 705: dmaout (sizeof (long), xhp->initsp + stkoff, & arg.np); ! 706: break; ! 707: ! 708: case ISP_286: ! 709: wdout = sizeof (short); ! 710: xhp->initsp = stk.vp - 3 * sizeof (short); ! 711: stkenvp = stk.vp + (arg.np + 1) * sizeof (short); ! 712: dmaout (sizeof (short), xhp->initsp + stkoff, & arg.np); ! 713: dmaout (sizeof (short), xhp->initsp + sizeof (short) + stkoff, ! 714: & stk.vp); ! 715: dmaout (sizeof (short), xhp->initsp + 2 * sizeof (short) + ! 716: stkoff, & stkenvp); ! 717: break; ! 718: ! 719: default: ! 720: panic("exstack"); ! 721: ! 722: } ! 723: ! 724: /* Arguments */ ! 725: for (i = 0 ; i < arg.np ; i ++, argp += wdin, stk.vp += wdout) { ! 726: dmaout (wdout, stk.vp + stkoff, & stk.cp); ! 727: stk.cp += exarg (stk.cp + stkoff, getupd (argp) & wdmask); ! 728: } ! 729: ! 730: /* skip null word after arguments */ ! 731: stk.vp += wdout; ! 732: ! 733: /* Environments */ ! 734: for (i = 0; i < env.np ; i ++, envp += wdin, stk.vp += wdout) { ! 735: dmaout (wdout, stk.vp + stkoff, & stk.cp); ! 736: stk.cp += exarg (stk.cp + stkoff, getupd (envp) & wdmask); ! 737: } ! 738: ! 739: return sp; ! 740: } ! 741: ! 742: exarg(out, in) ! 743: caddr_t in, out; ! 744: { ! 745: char c; ! 746: caddr_t init_in; ! 747: ! 748: init_in = in; ! 749: do { ! 750: c = getubd (in ++); ! 751: dmaout (sizeof (char), out ++, & c); ! 752: } while (c); ! 753: return in - init_in; ! 754: } ! 755: ! 756: /* ! 757: * Given a pointer to a list of arguments, a pointer to an argument count ! 758: * and a pointer to a byte count, count the #characters/#strings ! 759: * in the arguments ! 760: */ ! 761: excount(usrvp, adp, wdin) ! 762: register caddr_t usrvp; ! 763: struct adata *adp; ! 764: { ! 765: register caddr_t usrcp; ! 766: register int c; ! 767: register unsigned nb; ! 768: register unsigned na; ! 769: int wdmask; ! 770: ! 771: wdmask = -1; ! 772: if (wdin == sizeof (short)) ! 773: wdmask = (unsigned short) wdmask; ! 774: na = nb = 0; ! 775: if (usrvp != NULL) { ! 776: for (;;) { ! 777: usrcp = getupd (usrvp) & wdmask; ! 778: usrvp += wdin; ! 779: if (u.u_error) ! 780: return 0; ! 781: if (usrcp == NULL) ! 782: break; ! 783: na ++; ! 784: for (;;) { ! 785: c = getubd (usrcp ++); ! 786: if (u.u_error) ! 787: return 0; ! 788: nb ++; ! 789: if (c == '\0') ! 790: break; ! 791: } ! 792: } ! 793: } ! 794: adp->np = na; ! 795: adp->nc = nb; ! 796: return 1; ! 797: } ! 798: ! 799: /* ! 800: * Round up a size to a paragraph ! 801: * (mod 16) boundry. ! 802: * This is really mod 512 to make swapping work ! 803: */ ! 804: off_t ! 805: exround(s) ! 806: off_t s; ! 807: { ! 808: return (s + 15) & ~ 0x0F; ! 809: } ! 810: ! 811: pload(np) ! 812: char * np; ! 813: { ! 814: return -1; ! 815: ! 816: } ! 817: /* ! 818: * Set up the first process, a small program which will exec ! 819: * the init program. ! 820: */ ! 821: extern char aicodep[]; ! 822: ! 823: eveinit() ! 824: { ! 825: SEG *sp; ! 826: register PROC *pp; ! 827: SELF = pp = eprocp; ! 828: /* static struct xechdr xecinit[NUSEG+1] = { {0},{0},{0},{ISP_386}}; */ ! 829: ! 830: /* ! 831: * Allocate, record, initialize code segment, make it executable. ! 832: */ ! 833: if ((sp = salloc (__ROUND_UP_TO_MULTIPLE (icodes, NBPC), 0)) == NULL) ! 834: panic ("eveinit(code)"); ! 835: pp->p_segp [SIPDATA] = sp; ! 836: ! 837: /* ! 838: * Start process. ! 839: */ ! 840: u.u_argp = 0; ! 841: if (sproto (0) == 0) ! 842: panic ("eveinit()"); ! 843: segload (); ! 844: setspace (SEG_386_UD | R_USR); ! 845: kucopy (aicodep, 0, icodes); ! 846: } ! 847: ! 848: /* ! 849: * Given a major number, undo the previous function. ! 850: */ ! 851: puload(m) ! 852: int m; ! 853: { ! 854: register CON *cp; ! 855: register DRV *dp; ! 856: ! 857: dp = & drvl [m]; ! 858: ! 859: if (m >= drvn || (cp = dp->d_conp) == NULL) { ! 860: u.u_error = ENXIO; ! 861: goto ret; ! 862: } ! 863: (* cp->c_uload) (); ! 864: if (! u.u_error) ! 865: dp->d_conp = NULL; ! 866: ret: ! 867: return 0; ! 868: } ! 869:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.