home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / trash / part02 / load.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-22  |  5.3 KB  |  309 lines

  1. #include    <sys/param.h>
  2. #include    <sys/types.h>
  3. #include    <sys/immu.h>
  4. #include    <fcntl.h>
  5. #include    <unistd.h>
  6. #include    <stdio.h>
  7. #include    "register.h"
  8. #include    "symtab.h"
  9. #include    "diblock.h"
  10. #include    "instrn.h"
  11. #include    "process.h"
  12.  
  13. #if    0
  14. #define    LOAD_DEBUG    1
  15. #endif    /* 0 */
  16.  
  17. extern int    get_interpreter_data();
  18. extern int    fd_hold();
  19. extern int    fd_release();
  20.  
  21. extern int    errno;
  22.  
  23. extern FILE    *outfp;
  24. extern int    Vflag;
  25.  
  26. static int    init_stack();
  27.  
  28. /*
  29.  * Create a new process environment
  30.  * and initialise its components.
  31.  */
  32. int
  33. load(adotout, argp, envp)
  34. char    *adotout;
  35. char    **argp;
  36. char    **envp;
  37. {
  38.     char    *interpreter_name;
  39.     char    *interpreter_arg;
  40.     char    **cp;
  41.  
  42.     if (Vflag)
  43.     {
  44.         fprintf(outfp, "load(adotout=\"%s\",argp={", adotout);
  45.         for (cp = argp; *cp != (char *)0; cp++)
  46.             fprintf(outfp, "\"%s\",", *cp);
  47.         fprintf(outfp, "},envp={");
  48.         for (cp = envp; *cp != (char *)0; cp++)
  49.             fprintf(outfp, "\"%s\",", *cp);
  50.         fprintf(outfp, "})\n");
  51.     }
  52.  
  53.     interpreter_name = (char *)0;
  54.     interpreter_arg = (char *)0;
  55.  
  56.     if (get_interpreter_data(adotout, &interpreter_name, &interpreter_arg) == 0)
  57.     {
  58.         char    **nargp;
  59.  
  60.         /*
  61.          * It's an executable interpreter script.
  62.          */
  63.         for (cp = argp; *cp != (char *)0; cp++)
  64.             ;
  65.  
  66.         cp++;
  67.  
  68.         cp++;
  69.  
  70.         if (interpreter_arg != (char *)0)
  71.             cp++;
  72.  
  73.         if ((nargp = (char **)malloc((cp - argp) * sizeof(*cp))) == (char **)0)
  74.         {
  75.             vcouldnot("allocate space for duplicate argv: load()");
  76.             return -1;
  77.         }
  78.  
  79.         cp = nargp;
  80.  
  81.         *cp++ = argp[0];
  82.  
  83.         if (interpreter_arg != (char *)0)
  84.             *cp++ = interpreter_arg;
  85.  
  86.         *cp++ = adotout;
  87.  
  88.         {
  89.             int    argi;
  90.  
  91.             for (argi = 1; argp[argi] != (char *)0; argi++)
  92.                 *cp++ = argp[argi];
  93.  
  94.             *cp = (char *)0;
  95.         }
  96.  
  97.         adotout = interpreter_name;
  98.         argp = nargp;
  99.  
  100.         if (Vflag)
  101.         {
  102.             fprintf(outfp, "load'(adotout=\"%s\",argp={", adotout);
  103.             for (cp = argp; *cp != (char *)0; cp++)
  104.                 fprintf(outfp, "\"%s\",", *cp);
  105.             fprintf(outfp, "},envp={");
  106.             for (cp = envp; *cp != (char *)0; cp++)
  107.                 fprintf(outfp, "\"%s\",", *cp);
  108.             fprintf(outfp, "})\n");
  109.         }
  110.     }
  111.  
  112.     if (fd_release() == -1)
  113.         return -1;
  114.  
  115.     /*
  116.      * Create a new process execution
  117.      * environment.
  118.      */
  119.     if (procopen(adotout) == -1)
  120.     {
  121.         (void)fd_hold();
  122.         return -1;
  123.     }
  124.  
  125.     if (fd_hold() == -1)
  126.         return -1;
  127.  
  128. #if    defined(LOAD_DEBUG)
  129.     fprintf(outfp, "procopen'd\n");
  130. #endif    /* defined(LOAD_DEBUG) */
  131.  
  132.     /*
  133.      * Initialise the stack (arguments, environment and SP).
  134.      */
  135.     if (init_stack(argp, envp) == -1)
  136.         return -1;
  137.  
  138.     return 0;
  139. }
  140.  
  141. static
  142. int
  143. rpushi(i)
  144. int    i;
  145. {
  146.     unsigned long    sp;
  147.  
  148.     if (quiet_procsget(R_SP, &sp) == -1)
  149.         return -1;
  150.  
  151.     if (quiet_procmput(GLOBALdipc, sp, (char *)&i, sizeof(i)) == -1)
  152.         return -1;
  153.  
  154.     sp += sizeof(i);
  155.  
  156.     if (quiet_procsput(R_SP, sp) == -1)
  157.         return -1;
  158.  
  159.     return 0;
  160. }
  161.  
  162. #define    STRINGS_START    (USERSTACK - (EA_SIZE + NCARGS))
  163.  
  164. static
  165. int
  166. init_stack(argv, envp)
  167. char    **argv;
  168. char    **envp;
  169. {
  170.     int        argc;
  171.     int        envc;
  172.     int        argi;
  173.     int        envi;
  174.     unsigned long    eventual_sp;
  175.     unsigned long    stringsp;
  176.  
  177.     /*
  178.      * We make the stack look like this:
  179.  
  180.     USERSTACK(0x7ffff000)    ->    |_______________| ___
  181.                     |               |  ^
  182.                     | Software FP   |  |
  183.                     | emulation save|  | EA_SIZE
  184.                     | area (32bytes)|  |
  185.                      |_______________| _v_
  186.                     |               |  ^
  187.                     | WASTED SPACE  |  |
  188.                     |               |  |
  189.                     | "e_strn\0"    |  |
  190.                     |    ***        |  |
  191.                     | "e_str0\0"    |  | NCARGS
  192.                     | "a_strn\0"    |  |
  193.                     |    ***        |  |
  194.                     | "a_str0\0"    |  |
  195.     STRINGS_START        ->    |_______________| _v_
  196.                     | 0             |
  197.                     | env[n]        |  ^
  198.                     | ...           |  |
  199.                     | env[0]        |  |
  200.                     | 0             |  |
  201.                     | argv[n]       |  |
  202.                     | ...           |  | 2*NCARGS
  203.                     | argv[0]       |  |
  204.     SP            ->    | argc          |  |
  205.                     |               |  |
  206.                     |               |  |
  207.                     |               |  |
  208.                     |               |  |
  209.                     |               |  |
  210.                      |_______________|  v
  211.      *
  212.      */
  213.  
  214.     /*
  215.      * Count the argument strings.
  216.      */
  217.     argc = 0;
  218.     if (argv != (char **)0)
  219.     {
  220.         while (argv[argc] != (char *)0)
  221.             argc++;
  222.     }
  223.  
  224.     /*
  225.      * Count the environment strings.
  226.      */
  227.     envc = 0;
  228.     if (envp != (char **)0)
  229.     {
  230.         while (envp[envc] != (char *)0)
  231.             envc++;
  232.     }
  233.  
  234.     stringsp = STRINGS_START;
  235.     eventual_sp = STRINGS_START - (1 + envc + 1 + argc + 1) * NBPW;
  236.     eventual_sp &= ~0xF;    /* Quadword align the stack. */
  237.  
  238.     if (quiet_procsput(R_SP, eventual_sp) == -1)
  239.         return -1;
  240.  
  241.     /*
  242.      * Push argc.
  243.      */
  244.     if (rpushi(argc) == -1)
  245.         return -1;
  246.  
  247.     /*
  248.      * Push the argument strings and their pointers.
  249.      */
  250.     for (argi = 0; argi < argc; argi++)
  251.     {
  252.         int    length;
  253.  
  254.         if (rpushi(stringsp) == -1)
  255.             return -1;
  256.  
  257. #if    defined(LOAD_DEBUG)
  258.         fprintf(outfp, "done an rpushi\n");
  259. #endif    /* defined(LOAD_DEBUG) */
  260.  
  261.         length = strlen(argv[argi]) + 1;
  262.         if (quiet_procmput(GLOBALdipc, stringsp, argv[argi], length) == -1)
  263.             return -1;
  264.  
  265. #if    defined(LOAD_DEBUG)
  266.         fprintf(outfp, "done a quiet_procmput\n");
  267. #endif    /* defined(LOAD_DEBUG) */
  268.  
  269.         stringsp += length;
  270.     }
  271.  
  272.     /*
  273.      * Push a null word.
  274.      */
  275.     if (rpushi(0) == -1)
  276.         return -1;
  277.  
  278.     /*
  279.      * Push the environment strings and their pointers.
  280.      */
  281.     for (envi = 0; envi < envc; envi++)
  282.     {
  283.         int    length;
  284.  
  285.         if (rpushi(stringsp) == -1)
  286.             return -1;
  287.  
  288.         length = strlen(envp[envi]) + 1;
  289.         if (quiet_procmput(GLOBALdipc, stringsp, envp[envi], length) == -1)
  290.             return -1;
  291.  
  292.         stringsp += length;
  293.     }
  294.  
  295.     /*
  296.      * Push a null word.
  297.      */
  298.     if (rpushi(0) == -1)
  299.         return -1;
  300.  
  301.     /*
  302.      * Reinitialise the stack pointer.
  303.      */
  304.     if (quiet_procsput(R_SP, eventual_sp) == -1)
  305.         return -1;
  306.  
  307.     return 0;
  308. }
  309.