home *** CD-ROM | disk | FTP | other *** search
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/immu.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdio.h>
- #include "register.h"
- #include "symtab.h"
- #include "diblock.h"
- #include "instrn.h"
- #include "process.h"
-
- #if 0
- #define LOAD_DEBUG 1
- #endif /* 0 */
-
- extern int get_interpreter_data();
- extern int fd_hold();
- extern int fd_release();
-
- extern int errno;
-
- extern FILE *outfp;
- extern int Vflag;
-
- static int init_stack();
-
- /*
- * Create a new process environment
- * and initialise its components.
- */
- int
- load(adotout, argp, envp)
- char *adotout;
- char **argp;
- char **envp;
- {
- char *interpreter_name;
- char *interpreter_arg;
- char **cp;
-
- if (Vflag)
- {
- fprintf(outfp, "load(adotout=\"%s\",argp={", adotout);
- for (cp = argp; *cp != (char *)0; cp++)
- fprintf(outfp, "\"%s\",", *cp);
- fprintf(outfp, "},envp={");
- for (cp = envp; *cp != (char *)0; cp++)
- fprintf(outfp, "\"%s\",", *cp);
- fprintf(outfp, "})\n");
- }
-
- interpreter_name = (char *)0;
- interpreter_arg = (char *)0;
-
- if (get_interpreter_data(adotout, &interpreter_name, &interpreter_arg) == 0)
- {
- char **nargp;
-
- /*
- * It's an executable interpreter script.
- */
- for (cp = argp; *cp != (char *)0; cp++)
- ;
-
- cp++;
-
- cp++;
-
- if (interpreter_arg != (char *)0)
- cp++;
-
- if ((nargp = (char **)malloc((cp - argp) * sizeof(*cp))) == (char **)0)
- {
- vcouldnot("allocate space for duplicate argv: load()");
- return -1;
- }
-
- cp = nargp;
-
- *cp++ = argp[0];
-
- if (interpreter_arg != (char *)0)
- *cp++ = interpreter_arg;
-
- *cp++ = adotout;
-
- {
- int argi;
-
- for (argi = 1; argp[argi] != (char *)0; argi++)
- *cp++ = argp[argi];
-
- *cp = (char *)0;
- }
-
- adotout = interpreter_name;
- argp = nargp;
-
- if (Vflag)
- {
- fprintf(outfp, "load'(adotout=\"%s\",argp={", adotout);
- for (cp = argp; *cp != (char *)0; cp++)
- fprintf(outfp, "\"%s\",", *cp);
- fprintf(outfp, "},envp={");
- for (cp = envp; *cp != (char *)0; cp++)
- fprintf(outfp, "\"%s\",", *cp);
- fprintf(outfp, "})\n");
- }
- }
-
- if (fd_release() == -1)
- return -1;
-
- /*
- * Create a new process execution
- * environment.
- */
- if (procopen(adotout) == -1)
- {
- (void)fd_hold();
- return -1;
- }
-
- if (fd_hold() == -1)
- return -1;
-
- #if defined(LOAD_DEBUG)
- fprintf(outfp, "procopen'd\n");
- #endif /* defined(LOAD_DEBUG) */
-
- /*
- * Initialise the stack (arguments, environment and SP).
- */
- if (init_stack(argp, envp) == -1)
- return -1;
-
- return 0;
- }
-
- static
- int
- rpushi(i)
- int i;
- {
- unsigned long sp;
-
- if (quiet_procsget(R_SP, &sp) == -1)
- return -1;
-
- if (quiet_procmput(GLOBALdipc, sp, (char *)&i, sizeof(i)) == -1)
- return -1;
-
- sp += sizeof(i);
-
- if (quiet_procsput(R_SP, sp) == -1)
- return -1;
-
- return 0;
- }
-
- #define STRINGS_START (USERSTACK - (EA_SIZE + NCARGS))
-
- static
- int
- init_stack(argv, envp)
- char **argv;
- char **envp;
- {
- int argc;
- int envc;
- int argi;
- int envi;
- unsigned long eventual_sp;
- unsigned long stringsp;
-
- /*
- * We make the stack look like this:
-
- USERSTACK(0x7ffff000) -> |_______________| ___
- | | ^
- | Software FP | |
- | emulation save| | EA_SIZE
- | area (32bytes)| |
- |_______________| _v_
- | | ^
- | WASTED SPACE | |
- | | |
- | "e_strn\0" | |
- | *** | |
- | "e_str0\0" | | NCARGS
- | "a_strn\0" | |
- | *** | |
- | "a_str0\0" | |
- STRINGS_START -> |_______________| _v_
- | 0 |
- | env[n] | ^
- | ... | |
- | env[0] | |
- | 0 | |
- | argv[n] | |
- | ... | | 2*NCARGS
- | argv[0] | |
- SP -> | argc | |
- | | |
- | | |
- | | |
- | | |
- | | |
- |_______________| v
- *
- */
-
- /*
- * Count the argument strings.
- */
- argc = 0;
- if (argv != (char **)0)
- {
- while (argv[argc] != (char *)0)
- argc++;
- }
-
- /*
- * Count the environment strings.
- */
- envc = 0;
- if (envp != (char **)0)
- {
- while (envp[envc] != (char *)0)
- envc++;
- }
-
- stringsp = STRINGS_START;
- eventual_sp = STRINGS_START - (1 + envc + 1 + argc + 1) * NBPW;
- eventual_sp &= ~0xF; /* Quadword align the stack. */
-
- if (quiet_procsput(R_SP, eventual_sp) == -1)
- return -1;
-
- /*
- * Push argc.
- */
- if (rpushi(argc) == -1)
- return -1;
-
- /*
- * Push the argument strings and their pointers.
- */
- for (argi = 0; argi < argc; argi++)
- {
- int length;
-
- if (rpushi(stringsp) == -1)
- return -1;
-
- #if defined(LOAD_DEBUG)
- fprintf(outfp, "done an rpushi\n");
- #endif /* defined(LOAD_DEBUG) */
-
- length = strlen(argv[argi]) + 1;
- if (quiet_procmput(GLOBALdipc, stringsp, argv[argi], length) == -1)
- return -1;
-
- #if defined(LOAD_DEBUG)
- fprintf(outfp, "done a quiet_procmput\n");
- #endif /* defined(LOAD_DEBUG) */
-
- stringsp += length;
- }
-
- /*
- * Push a null word.
- */
- if (rpushi(0) == -1)
- return -1;
-
- /*
- * Push the environment strings and their pointers.
- */
- for (envi = 0; envi < envc; envi++)
- {
- int length;
-
- if (rpushi(stringsp) == -1)
- return -1;
-
- length = strlen(envp[envi]) + 1;
- if (quiet_procmput(GLOBALdipc, stringsp, envp[envi], length) == -1)
- return -1;
-
- stringsp += length;
- }
-
- /*
- * Push a null word.
- */
- if (rpushi(0) == -1)
- return -1;
-
- /*
- * Reinitialise the stack pointer.
- */
- if (quiet_procsput(R_SP, eventual_sp) == -1)
- return -1;
-
- return 0;
- }
-