|
|
1.1 ! root 1: /* $Header: /kernel/kersrc/i286/RCS/exec.c,v 1.1 92/07/17 15:21:27 bin Exp Locker: bin $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * This file contains a special version ! 17: * of "sys exec" for the i8086. This version has ! 18: * no driver load code in it (save space) and has ! 19: * special load code so that the text of a shared ! 20: * and separated image can be shared. ! 21: * Loadable kernel processes are partially supported: ! 22: * the process text and data must be ld'ed with the system ! 23: * and the l.out executed must have no loadable or allocateable ! 24: * segments. ! 25: * ! 26: * $Log: exec.c,v $ ! 27: * Revision 1.1 92/07/17 15:21:27 bin ! 28: * Initial revision ! 29: * ! 30: * Revision 1.1 88/03/24 17:39:26 src ! 31: * Initial revision ! 32: * ! 33: * 88/01/21 Allan Cornish /usr/src/sys/i8086/src/exec.c ! 34: * Segments are now de-associated from processes before freeing the segment. ! 35: * ! 36: * 87/12/03 Allan Cornish /usr/src/sys/i8086/src/exec.c ! 37: * ld_start() now reverts to kernel mode [depth=0] from user mode [depth=1]. ! 38: * ! 39: * 87/11/25 Allan Cornish /usr/src/sys/i8086/src/exec.c ! 40: * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr. ! 41: * ! 42: * 87/11/14 Allan Cornish /usr/src/sys/i8086/src/exec.c ! 43: * Init code+data now split into icodep/icodes and idatap/idatas. ! 44: * ! 45: * 87/11/05 Allan Cornish /usr/src/sys/i8086/src/exec.c ! 46: * New seg struct now used to allow extended addressing. ! 47: * ! 48: * 87/10/09 Allan Cornish /usr/src/sys/i8086/src/exec.c ! 49: * pload() now handles new format [separate code] loadable device drivers. ! 50: * ! 51: * 87/10/08 Allan Cornish /usr/src/sys/i8086/src/exec.c ! 52: * Exsread() initializes the (IO).io_flag field to 0. ! 53: */ ! 54: #include <sys/coherent.h> ! 55: #include <acct.h> ! 56: #include <sys/buf.h> ! 57: #include <canon.h> ! 58: #include <sys/con.h> ! 59: #include <errno.h> ! 60: #include <sys/filsys.h> ! 61: #include <sys/ino.h> ! 62: #include <sys/inode.h> ! 63: #include <l.out.h> ! 64: #include <sys/proc.h> ! 65: #include <sys/sched.h> ! 66: #include <sys/seg.h> ! 67: #include <signal.h> ! 68: #include <sys/i8086.h> ! 69: ! 70: /* ! 71: * Sizes. ! 72: */ ! 73: #define sh ((fsize_t)sizeof(struct ldheader)) ! 74: #define si lssize[L_SHRI] ! 75: #define pi lssize[L_PRVI] ! 76: #define bi lssize[L_BSSI] ! 77: #define sd lssize[L_SHRD] ! 78: #define pd lssize[L_PRVD] ! 79: #define bd lssize[L_BSSD] ! 80: ! 81: /* ! 82: * Segments. ! 83: */ ! 84: #define upsp pp->p_segp[SIUSERP] ! 85: #define sssp pp->p_segp[SISTACK] ! 86: #define sisp pp->p_segp[SISTEXT] ! 87: #define pisp pp->p_segp[SIPTEXT] ! 88: #define pdsp pp->p_segp[SIPDATA] ! 89: ! 90: /* ! 91: * Loadable driver initiation point. ! 92: */ ! 93: static ! 94: ld_start() ! 95: { ! 96: register SEG * sp; ! 97: register int ret; ! 98: ! 99: /* ! 100: * Kernel processes start by default at user level. ! 101: * Revert to kernel level. ! 102: */ ! 103: if ( depth == 1 ) ! 104: depth--; ! 105: ! 106: /* ! 107: * Initialize memory references. ! 108: */ ! 109: u.u_btime = timer.t_time; ! 110: sproto(); ! 111: segload(); ! 112: ! 113: ! 114: /* ! 115: * Invoke the driver if it has a shared or private code segment. ! 116: */ ! 117: ret = 100; ! 118: if ( (sp = SELF->p_segp[SISTEXT]) || (sp = SELF->p_segp[SIPTEXT]) ) { ! 119: ret = ld_xcall( sp->s_faddr ); ! 120: } ! 121: ! 122: uexit( ret ); ! 123: } ! 124: ! 125: /* ! 126: * Set up the first process, a small programme which will exec ! 127: * the init programme. ! 128: */ ! 129: eveinit(sp) ! 130: SEG *sp; ! 131: { ! 132: register PROC *pp; ! 133: SELF = pp = eprocp; ! 134: ! 135: /* ! 136: * Record user area. ! 137: */ ! 138: pp->p_segp[SIUSERP] = sp; ! 139: ! 140: /* ! 141: * Allocate, record, initialize code segment, make it executable. ! 142: */ ! 143: if ((sp=salloc((fsize_t)icodes, 0)) == NULL) ! 144: panic("eveinit(code)"); ! 145: pp->p_segp[SIPTEXT] = sp; ! 146: kfcopy( icodep, sp->s_faddr, icodes ); ! 147: sp->s_flags |= SFTEXT; ! 148: vremap(sp); ! 149: ! 150: /* ! 151: * Allocate, record, and initialize data segment. ! 152: */ ! 153: if ((sp=salloc((fsize_t)idatas, 0)) == NULL) ! 154: panic("eveinit(data)"); ! 155: pp->p_segp[SIPDATA] = sp; ! 156: kfcopy( idatap, sp->s_faddr, idatas ); ! 157: ! 158: /* ! 159: * Allocate and record stack segment. ! 160: */ ! 161: if ((sp=salloc((fsize_t)UPASIZE, SFDOWN)) == NULL) ! 162: panic("eveinit()"); ! 163: pp->p_segp[SISTACK] = sp; ! 164: ! 165: /* ! 166: * Start process. ! 167: */ ! 168: u.u_argp = 0; ! 169: if (sproto() == 0) ! 170: panic("eveinit()"); ! 171: segload(); ! 172: } ! 173: ! 174: /* ! 175: * Load a driver which has already been linked into the system image. ! 176: */ ! 177: pload( np ) ! 178: char * np; ! 179: { ! 180: register INODE * ip; ! 181: register PROC * cpp; ! 182: struct seg * sp; ! 183: fsize_t lssize[NUSEG]; /* Segment sizes */ ! 184: int lflag; /* l_flags from l.out */ ! 185: vaddr_t pc; /* l_entry from l.out */ ! 186: int r; /* Flag for "exload" */ ! 187: int s; ! 188: extern char end[]; ! 189: ! 190: ! 191: if (super() == 0) { ! 192: return( -1 ); ! 193: } ! 194: ! 195: /* ! 196: * Coalesce memory BEFORE loading driver, since it can't be moved. ! 197: */ ! 198: krunch(10000); ! 199: ! 200: if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) { ! 201: return( -1 ); ! 202: } ! 203: ! 204: /* ! 205: * New format loadable drivers must have separate code/data. ! 206: * It must have executable code, but no initialized data. ! 207: * Uninitialized data must match the kernel data size. ! 208: */ ! 209: if ( ((lflag & (LF_KER|LF_SHR|LF_SEP)) != (LF_SEP|LF_KER)) ! 210: || (si==0) || (sd!=0) || (pd!=0) || (bd != (int)end) ) { ! 211: u.u_error = EBADFMT; ! 212: idetach(ip); ! 213: return( -1 ); ! 214: } ! 215: ! 216: /* ! 217: * Allocate and initialize driver code segment. ! 218: * NOTE: Must be system segment to prevent relocation. ! 219: */ ! 220: sp = ssalloc(&r, ip, SFTEXT|SFHIGH|SFNSWP|SFSYST, si+pi+bi, sh, si+pi); ! 221: ! 222: /* ! 223: * Release driver object file. ! 224: */ ! 225: idetach(ip); ! 226: ! 227: if ( r < 0 ) { ! 228: u.u_error = ENOMEM; ! 229: return( -1 ); ! 230: } ! 231: ! 232: /* ! 233: * Spawn kernel process to service driver. ! 234: */ ! 235: if ((cpp = process(ld_start)) == NULL ) { ! 236: u.u_error = ENOMEM; ! 237: sfree(sp); ! 238: return( -1 ); ! 239: } ! 240: ! 241: /* ! 242: * Record the basename of the loaded driver. ! 243: */ ! 244: kscopy( u.u_direct.d_name, cpp->p_segp[SIUSERP], ! 245: offset(uproc,u_comm[0]), sizeof(u.u_comm) ); ! 246: ! 247: /* ! 248: * Record the driver code segment in the process's private code. ! 249: */ ! 250: cpp->p_segp[SIPTEXT] = sp; ! 251: cpp->p_cval = CVCHILD; ! 252: cpp->p_sval = SVCHILD; ! 253: cpp->p_rval = RVCHILD; ! 254: cpp->p_ppid = 1; ! 255: ! 256: /* ! 257: * Make the process executable. ! 258: */ ! 259: s = sphi(); ! 260: setrun( cpp ); ! 261: spl( s ); ! 262: ! 263: /* ! 264: * Return driver process id. ! 265: */ ! 266: return( cpp->p_pid ); ! 267: } ! 268: ! 269: /* ! 270: * Given a major number, undo the previous function. ! 271: */ ! 272: puload(m) ! 273: int m; ! 274: { ! 275: register CON *cp; ! 276: register DRV *dp; ! 277: ! 278: dp = &drvl[m]; ! 279: lock(dp->d_gate); ! 280: if (m>=drvn || (cp=dp->d_conp)==NULL) { ! 281: u.u_error = ENXIO; ! 282: goto ret; ! 283: } ! 284: (*cp->c_uload)(); ! 285: if ( ! u.u_error) ! 286: dp->d_conp = NULL; ! 287: ret: ! 288: unlock(dp->d_gate); ! 289: return (0); ! 290: } ! 291: ! 292: /* ! 293: * Pass control to an image in a file. ! 294: * Make sure the format is acceptable. Release ! 295: * the old segments. Read in the new ones. Some special ! 296: * care is taken so that shared and (more important) shared ! 297: * and separated images can be run on the 8086. ! 298: */ ! 299: pexece(np, argp, envp) ! 300: char *np; ! 301: char *argp[]; ! 302: char *envp[]; ! 303: { ! 304: register INODE *ip; /* Load file INODE */ ! 305: register PROC *pp; /* A cheap copy of SELF */ ! 306: register SEG *ssp; /* New stack segment */ ! 307: register SEG *segp; ! 308: register fsize_t ss; /* Segment size temp. */ ! 309: register int i; /* For looping over segments */ ! 310: int r; /* Flag for "exload" */ ! 311: int lflag; /* l_flags from l.out */ ! 312: vaddr_t pc; /* l_entry from l.out */ ! 313: vaddr_t sp; /* Initial stack pointer */ ! 314: fsize_t lssize[NUSEG]; /* Segment sizes */ ! 315: fsize_t codsize; /* Total if CS segment */ ! 316: fsize_t datsize; /* Total of DS segment */ ! 317: extern fsize_t exround(); /* Paragraph rounder */ ! 318: ! 319: pp = SELF; ! 320: if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) { ! 321: return; ! 322: } ! 323: ! 324: if ( (lflag & LF_SEP) == 0 ) { ! 325: u.u_error = EBADFMT; ! 326: idetach(ip); ! 327: return; ! 328: } ! 329: ! 330: /* ! 331: * Kernel processes are now supported through the sload() system call. ! 332: * 87/10/09 Allan Cornish. ! 333: */ ! 334: if ((lflag&LF_KER) != 0) { ! 335: u.u_error = EBADFMT; ! 336: idetach(ip); ! 337: return; ! 338: } ! 339: ! 340: /* ! 341: * If a shared and separated image ! 342: * has stuff in segments that makes it impossible ! 343: * to share, give an error immediately so that we don't ! 344: * lose the parent. ! 345: */ ! 346: lflag &= LF_SHR|LF_SEP; ! 347: ! 348: if (lflag==(LF_SHR|LF_SEP) && (pi!=0 || bi!=0)) { ! 349: u.u_error = EBADFMT; ! 350: idetach(ip); ! 351: return; ! 352: } ! 353: ! 354: if ((ssp=exstack(&sp, argp, envp)) == NULL) { ! 355: idetach(ip); ! 356: return; ! 357: } ! 358: ! 359: switch (lflag) { ! 360: case LF_SEP: ! 361: codsize = si+pi+bi; ! 362: datsize = ssp->s_size+sd+pd+bd; ! 363: break; ! 364: case LF_SHR|LF_SEP: ! 365: codsize = si; ! 366: datsize = ssp->s_size+exround(sd)+pd+bd; ! 367: break; ! 368: } ! 369: codsize = (codsize+(BSIZE-1)) & ~(BSIZE-1); ! 370: datsize = (datsize+(BSIZE-1)) & ~(BSIZE-1); ! 371: if ( (codsize >= MAXU) || (datsize >= MAXU) ) { ! 372: u.u_error = E2BIG; ! 373: idetach(ip); ! 374: return; ! 375: } ! 376: ! 377: /* ! 378: * At this point the file has been ! 379: * validated as an object module, and the ! 380: * argument list has been built. Release all of ! 381: * the original segments. At this point we have ! 382: * committed to the new image. A "sys exec" that ! 383: * gets an I/O error is doomed. ! 384: * NOTE: User-area segment is NOT released. ! 385: * Segment pointer in proc is erased BEFORE invoking sfree(). ! 386: */ ! 387: for ( i = 1; i < NUSEG; ++i ) { ! 388: if ((segp = pp->p_segp[i]) != NULL) { ! 389: pp->p_segp[i] = NULL; ! 390: sfree(segp); ! 391: } ! 392: } ! 393: ! 394: /* ! 395: * Read in the loadable segments. ! 396: */ ! 397: sssp = ssp; ! 398: switch (lflag) { ! 399: case 0: ! 400: ss = si+pi+sd+pd; ! 401: pdsp = ssalloc(&r, ip, 0, ss+bi+bd, sh, ss); ! 402: if (r < 0) ! 403: goto out; ! 404: break; ! 405: ! 406: case LF_SHR: ! 407: ss = exround(si+sd); ! 408: pdsp = ssalloc(&r, ip, 0, ss+pi+pd+bi+bd, sh, si); ! 409: if (r < 0) ! 410: goto out; ! 411: if (exsread(pdsp, ip, sd, sh+si+pi, si) == NULL) ! 412: goto out; ! 413: if (exsread(pdsp, ip, pi, sh+si, ss) == NULL) ! 414: goto out; ! 415: if (exsread(pdsp, ip, pd, sh+si+pi+sd, ss+pi) == NULL) ! 416: goto out; ! 417: break; ! 418: ! 419: case LF_SEP: ! 420: pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi); ! 421: if (r < 0) ! 422: goto out; ! 423: pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+pi, sd+pd); ! 424: if (r < 0) ! 425: goto out; ! 426: break; ! 427: ! 428: case LF_SHR|LF_SEP: ! 429: /* pi=0, bi=0 */ ! 430: sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si); ! 431: if (r < 0) ! 432: goto out; ! 433: ss = exround(sd); ! 434: pdsp = ssalloc(&r, ip, 0, ss+pd+bd, sh+si, sd); ! 435: if (r<0 || exsread(pdsp, ip, pd, sh+si+sd, ss) == NULL) ! 436: goto out; ! 437: } ! 438: if (sproto() == 0) ! 439: goto out; ! 440: #if 0 ! 441: if ( (datsize != pdsp->s_size) || ! 442: ( (lflag==LF_SEP) && (codsize != pisp->s_size) ) || ! 443: ( (lflag==(LF_SEP|LF_SHR)) && (codsize != sisp->s_size) ) ) { ! 444: printf("\nExec ERROR: codsize: 0x%X datsize: 0x%X\n", ! 445: codsize, datsize); ! 446: printf( ! 447: "pdsp->s_size: 0x%X pisp->s_size: 0x%X sisp->s_size: 0x%X\n", ! 448: pdsp->s_size, pisp->s_size, sisp->s_size); ! 449: } ! 450: #endif ! 451: /* ! 452: * The new image is read in ! 453: * and mapped. Perform the final grunge ! 454: * (set-uid stuff, accounting, loading up ! 455: * registers, etc). ! 456: */ ! 457: u.u_flag &= ~AFORK; ! 458: kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm)); ! 459: if (iaccess(ip, IPR) == 0) { /* Can't read ? no dump or trace */ ! 460: pp->p_flags |= PFNDMP; ! 461: pp->p_flags &= ~PFTRAC; ! 462: } ! 463: if (iaccess(ip, IPW) == 0) /* Can't write ? no trace */ ! 464: pp->p_flags &= ~PFTRAC; ! 465: if ((ip->i_mode&ISUID) != 0) { /* Set user id ? no trace */ ! 466: pp->p_uid = u.u_uid = ip->i_uid; ! 467: pp->p_flags &= ~PFTRAC; ! 468: } ! 469: if ((ip->i_mode&ISGID) != 0) { /* Set group id ? no trace */ ! 470: u.u_gid = ip->i_gid; ! 471: pp->p_flags &= ~PFTRAC; ! 472: } ! 473: for (i=0; i<NSIG; ++i) ! 474: if (u.u_sfunc[i] != SIG_IGN) ! 475: u.u_sfunc[i] = SIG_DFL; ! 476: if ((pp->p_flags&PFTRAC) != 0) /* Being traced */ ! 477: sendsig(SIGTRAP, pp); ! 478: idetach(ip); ! 479: msetusr(pc, sp); ! 480: segload(); ! 481: return (0); ! 482: ! 483: /* ! 484: * We did not make it. ! 485: * Release the INODE for the load ! 486: * file, and return through the "sys exit" ! 487: * code with a "SIGSYS", or with the signal actually received ! 488: * if we are aborting due to interrupted exec. ! 489: */ ! 490: out: ! 491: idetach(ip); ! 492: if (u.u_error == EINTR) ! 493: pexit(nondsig()); ! 494: pexit(SIGSYS); ! 495: } ! 496: ! 497: /* ! 498: * Open an l.out, make sure it is an l.out and executable and return the ! 499: * appropriate information. ! 500: */ ! 501: INODE * ! 502: exlopen(np, ssizep, flagp, pcp) ! 503: char *np; ! 504: fsize_t *ssizep; ! 505: int *flagp; ! 506: vaddr_t *pcp; ! 507: { ! 508: register INODE *ip; ! 509: register struct ldheader *ldp; ! 510: register int n; ! 511: register BUF *bp; ! 512: int m; ! 513: ! 514: /* ! 515: * Make sure the file is really an executable l.out and read the ! 516: * header in. ! 517: */ ! 518: if (ftoi(np, 'r') != 0) ! 519: return (NULL); ! 520: ip = u.u_cdiri; ! 521: if (iaccess(ip, IPE) == 0) { ! 522: idetach(ip); ! 523: return (NULL); ! 524: } ! 525: if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) { ! 526: u.u_error = EACCES; ! 527: idetach(ip); ! 528: return (NULL); ! 529: } ! 530: if ((bp=vread(ip, (daddr_t)0)) == NULL) { ! 531: u.u_error = EBADFMT; ! 532: idetach(ip); ! 533: return (NULL); ! 534: } ! 535: ! 536: /* ! 537: * Copy everything we need from the l.out header and check magic ! 538: * number and machine type. ! 539: */ ! 540: ldp = FP_OFF(bp->b_faddr); ! 541: m = ldp->l_magic; ! 542: canint(m); ! 543: if (m != L_MAGIC) { ! 544: u.u_error = ENOEXEC; ! 545: brelease(bp); ! 546: idetach(ip); ! 547: return (NULL); ! 548: } ! 549: m = ldp->l_machine; ! 550: canint(m); ! 551: if (m != mactype) { ! 552: u.u_error = EBADFMT; ! 553: brelease(bp); ! 554: idetach(ip); ! 555: return (NULL); ! 556: } ! 557: kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(fsize_t)); ! 558: for (n=0; n<NXSEG; n++) ! 559: cansize(ssizep[n]); ! 560: *flagp = ldp->l_flag; ! 561: canint(*flagp); ! 562: *pcp = ldp->l_entry; ! 563: canvaddr(*pcp); ! 564: brelease(bp); ! 565: return (ip); ! 566: } ! 567: ! 568: /* ! 569: * Given a segment `sp', read `ss' bytes from the inode `ip' starting ! 570: * at seek address `sa' into offset `so' in the segment. ! 571: */ ! 572: SEG * ! 573: exsread(sp, ip, ss, sa, so) ! 574: register SEG *sp; ! 575: INODE *ip; ! 576: fsize_t ss; ! 577: fsize_t sa; ! 578: fsize_t so; ! 579: { ! 580: while (ss > 0) { ! 581: u.u_io.io_seg = IOPHY; ! 582: u.u_io.io_seek = sa; ! 583: u.u_io.io_phys = sp->s_paddr + so; ! 584: u.u_io.io_flag = 0; ! 585: if (ss >= 4096) { ! 586: u.u_io.io_ioc = 4096; ! 587: ss -= 4096; ! 588: } else { ! 589: u.u_io.io_ioc = ss; ! 590: ss = 0; ! 591: } ! 592: sp->s_lrefc++; ! 593: iread(ip, &u.u_io); ! 594: sp->s_lrefc--; ! 595: if (nondsig()) { ! 596: u.u_error = EINTR; ! 597: break; ! 598: } ! 599: sa += 4096; ! 600: so += 4096; ! 601: } ! 602: if (u.u_error == 0) ! 603: return (sp); ! 604: return (NULL); ! 605: } ! 606: ! 607: /* ! 608: * Given a pointer to a list of arguments and a pointer to a list of ! 609: * environments, return a stack with the arguments and environments on it. ! 610: */ ! 611: SEG * ! 612: exstack(iusp, argp, envp) ! 613: char **iusp; /* Back patch sp value */ ! 614: char *argp[]; /* Arguments for new process */ ! 615: char *envp[]; /* Environments for new process */ ! 616: { ! 617: SEG *sp; /* Stack segment pointer */ ! 618: struct adata { /* Storage for arg and env data */ ! 619: char **up; /* User vector pointer */ ! 620: int np; /* Number of pointers in vector */ ! 621: int nc; /* Number of characters in strings */ ! 622: } arg, env; ! 623: struct sdata { /* To keep segment pointers */ ! 624: vaddr_t base; /* Top of segment virtual */ ! 625: vaddr_t ap; /* Argc, argv, envp pointer */ ! 626: vaddr_t vp; /* Argv[i], envp[i] pointer */ ! 627: vaddr_t cp; /* Argv[i][j], envp[i][j] pointer */ ! 628: } aux, stk; ! 629: aold_t aold; /* Auxiliary map storage */ ! 630: register char **usrvp; /* Vector pointer into user seg */ ! 631: register char *usrcp; /* Character pointer into user seg */ ! 632: register int c; /* Character fetched from user */ ! 633: register int chrsz; /* Size of strings */ ! 634: register struct adata *adp; /* Arg and env scanner */ ! 635: register int vecsz; /* Size of vectors */ ! 636: register int stksz; /* Size of stack argument region */ ! 637: ! 638: /* Validate and evaluate size of args and envs */ ! 639: arg.up = argp; ! 640: env.up = envp; ! 641: chrsz = 0; ! 642: vecsz = 0; ! 643: for (adp = &arg; ; adp = &env) { ! 644: adp->np = 0; ! 645: adp->nc = 0; ! 646: if (excount(adp->up, &adp->np, &adp->nc) == 0) ! 647: return (NULL); ! 648: chrsz += adp->nc * sizeof(char); ! 649: vecsz += adp->np * sizeof(char *); ! 650: if (adp == &env) ! 651: break; ! 652: } ! 653: ! 654: /* Calculate stack size and allocate it */ ! 655: chrsz = roundu(chrsz, sizeof(int)); ! 656: stksz = sizeof(int) /* argc */ ! 657: + sizeof(char **) /* argv */ ! 658: + sizeof(char **) /* envp */ ! 659: + vecsz /* argv[i] and envp[i] */ ! 660: + chrsz /* *argv[i] and *envp[i] */ ! 661: + sizeof(int) /* Mystery zero word */ ! 662: + sizeof(char *) /* Splimit for z8000 */ ! 663: + sizeof(int); /* errno */ ! 664: stksz += ISTSIZE; ! 665: if (stksz > MADSIZE) { ! 666: u.u_error = E2BIG; ! 667: return (NULL); ! 668: } ! 669: if ((sp=salloc((fsize_t)stksz, SFDOWN)) == NULL) ! 670: return (NULL); ! 671: stksz -= ISTSIZE; ! 672: ! 673: /* ! 674: * Initialize segment data. ! 675: */ ! 676: asave(aold); ! 677: ! 678: abase(FP_SEL(sp->s_faddr)); ! 679: aux.base = sp->s_size; ! 680: aux.ap = aux.base - stksz; ! 681: aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **); ! 682: aux.cp = aux.vp + vecsz; ! 683: ! 684: stk.base = ISTVIRT; ! 685: stk.ap = stk.base - stksz; ! 686: stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **); ! 687: stk.cp = stk.vp + vecsz; ! 688: ! 689: /* ! 690: * Write argc. ! 691: */ ! 692: aputi((int *)aux.ap, arg.np-1); ! 693: aux.ap += sizeof(int); ! 694: ! 695: /* ! 696: * Arguments and environments. ! 697: */ ! 698: for (adp = &arg; ; adp = &env) { ! 699: ! 700: /* Write argv or envp */ ! 701: aputp((char ***)aux.ap, (char **)stk.vp); ! 702: aux.ap += sizeof(char **); ! 703: if ((usrvp = adp->up) != NULL) { ! 704: ! 705: /* Write argv[i] or envp[i] */ ! 706: while ((usrcp = getupd(usrvp++)) != NULL) { ! 707: aputp((char **)aux.vp, (char *)stk.cp); ! 708: aux.vp += sizeof(char *); ! 709: stk.vp += sizeof(char *); ! 710: ! 711: /* Write argv[i][j] or envp[i][j] */ ! 712: do { ! 713: c = getubd(usrcp++); ! 714: aputc((char *)aux.cp, c); ! 715: aux.cp += sizeof(char); ! 716: stk.cp += sizeof(char); ! 717: } while (c != '\0'); ! 718: } ! 719: } ! 720: ! 721: /* Write argv[argc] or envp[envc] */ ! 722: aputp((char **)aux.vp, NULL); ! 723: aux.vp += sizeof(char *); ! 724: stk.vp += sizeof(char *); ! 725: if (adp == &env) ! 726: break; ! 727: } ! 728: ! 729: /* ! 730: * Clear out the slop. ! 731: */ ! 732: aux.base -= sizeof(int); ! 733: aputi((int *) aux.base, 0); /* errno */ ! 734: aux.base -= sizeof(char *); ! 735: aputp((char **) aux.base, (char *)stk.base - sp->s_size + SOVSIZE); ! 736: aux.base -= sizeof(int); ! 737: aputi((int *) aux.base, 0); /* mystery word */ ! 738: ! 739: arest(aold); ! 740: ! 741: /* ! 742: * Patch some values and return. ! 743: */ ! 744: *iusp = stk.ap; /* Patch initial usp */ ! 745: u.u_argc = arg.np-1; ! 746: u.u_argp = stk.vp; /* Points after NULL of envs */ ! 747: return (sp); ! 748: } ! 749: ! 750: /* ! 751: * Given a pointer to a list of arguments, a pointer to an argument count ! 752: * and a pointer to a byte count, update incrementally the argument count ! 753: * and the byte count. ! 754: */ ! 755: excount(usrvp, nap, nbp) ! 756: register char **usrvp; ! 757: int *nap; ! 758: int *nbp; ! 759: { ! 760: register char *usrcp; ! 761: register int c; ! 762: register unsigned nb; ! 763: register unsigned na; ! 764: ! 765: na = 1; ! 766: nb = 0; ! 767: if (usrvp != NULL) { ! 768: for (;;) { ! 769: usrcp = getupd(usrvp++); ! 770: if (u.u_error) ! 771: return (0); ! 772: if (usrcp == NULL) ! 773: break; ! 774: na++; ! 775: for (;;) { ! 776: c = getubd(usrcp++); ! 777: if (u.u_error) ! 778: return (0); ! 779: nb++; ! 780: if (c == '\0') ! 781: break; ! 782: } ! 783: } ! 784: } ! 785: *nap += na; ! 786: *nbp += nb; ! 787: return (1); ! 788: } ! 789: ! 790: /* ! 791: * Round up a size to a paragraph ! 792: * (mod 16) boundry. ! 793: * This is really mod 512 to make swapping work ! 794: */ ! 795: fsize_t ! 796: exround(s) ! 797: fsize_t s; ! 798: { ! 799: return ((s+15)&~0x0F); ! 800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.