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