home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / trash / part03 / main.c < prev   
Encoding:
C/C++ Source or Header  |  1992-03-22  |  9.3 KB  |  523 lines

  1. #include    <stdio.h>
  2.  
  3. /*
  4.  * Simulate the execution of a process
  5.  * on a MIPS R[CS]3330 under RISC/os 4.52.
  6.  */
  7.  
  8. #define    DEFAULT_OUTNAME    "<stderr>"
  9. #define    DEFAULT_OUTFP    stderr
  10.  
  11. #define    toggle(f)    (f) = 1 - (f)
  12.  
  13. extern int        fd_init();
  14. extern int        hist_init();
  15. extern void        histo_dump();
  16. extern void        hist_dump();
  17. extern char        *strdup();
  18. extern int        getopt();
  19. extern void        usage();
  20. extern int        load();
  21. extern int        go();
  22. extern char        *execvpath();
  23. extern int        setobuf();
  24.  
  25. extern int        optind;
  26. extern char        *optarg;
  27.  
  28. char            **gargv;
  29. char            **genvp;
  30. char            *usage_args    = " [-ABCFHILMNPRSTVW] [-a argc] [-d fd] [-f executable ] [-h history_length] [-o outfile] [-v] [command ..]";
  31. char            *getopt_args    =    "ABCFHILMNPRSTVWa:d:f:h:o:v";
  32. int            Aflag;        /* show read/write/execve args    */
  33. int            Bflag;        /* print page no.s        */
  34. int            Cflag;        /* C-like trace format        */
  35. int            Fflag;        /* follow across execvp        */
  36. int            Hflag;        /* emit an execution histogram    */
  37. int            Iflag;        /* show instructions        */
  38. int            Lflag    = 1;    /* line buffer output        */
  39. int            Mflag;        /* show memory accesses        */
  40. int            Nflag;        /* show instrn counts        */
  41. int            Pflag;        /* show syscalls before        */
  42. int            Rflag;        /* show register accesses    */
  43. int            Sflag    = 1;    /* show syscalls after        */
  44. int            Tflag;        /* show system time        */
  45. int            Vflag;        /* be verbose            */
  46. int            Wflag    = 1;    /* truncate outfile b4 writing    */
  47. FILE            *outfp    = DEFAULT_OUTFP;
  48. char            *adotout;    /* explicit executable        */
  49. int            nargc    = -1;    /* # of argv's before env's    */
  50.  
  51. unsigned long        instruction_count;
  52. unsigned long        instruction_count_since_last_syscall;
  53.  
  54. static char        *version_string    = "Version 5";
  55. static int        output_file_has_been_specified;
  56. static char        *default_argv[]    =
  57. {
  58.     "a.out",
  59.     (char *)0
  60. };
  61.  
  62. main(argc, argv, envp)
  63. int    argc;
  64. char    *argv[];
  65. char    *envp[];
  66. {
  67.     int    c;
  68.     char    *newoutfile;
  69.     int    newoutfd;
  70.     FILE    *newoutfp;
  71.     char    **app;
  72.     char    **epp;
  73.  
  74.     gargv = &argv[0];
  75.     genvp = &envp[0];
  76.  
  77.     newoutfile = (char *)0;
  78.     newoutfd = -1;
  79.  
  80.     while ((c = getopt(argc, argv, getopt_args)) != -1)
  81.     {
  82.         switch (c)
  83.         {
  84.         case 'A':
  85.             toggle(Aflag);
  86.             break;
  87.  
  88.         case 'B':
  89.             toggle(Bflag);
  90.             break;
  91.  
  92.         case 'C':
  93.             toggle(Cflag);
  94.             break;
  95.  
  96.         case 'F':
  97.             toggle(Fflag);
  98.             break;
  99.  
  100.         case 'H':
  101.             toggle(Hflag);
  102.             break;
  103.  
  104.         case 'I':
  105.             toggle(Iflag);
  106.             break;
  107.  
  108.         case 'L':
  109.             toggle(Lflag);
  110.             break;
  111.  
  112.         case 'M':
  113.             toggle(Mflag);
  114.             break;
  115.  
  116.         case 'N':
  117.             toggle(Nflag);
  118.             break;
  119.  
  120.         case 'P':
  121.             toggle(Pflag);
  122.             break;
  123.  
  124.         case 'R':
  125.             toggle(Rflag);
  126.             break;
  127.  
  128.         case 'S':
  129.             toggle(Sflag);
  130.             break;
  131.  
  132.         case 'T':
  133.             toggle(Tflag);
  134.             break;
  135.  
  136.         case 'V':
  137.             toggle(Vflag);
  138.             break;
  139.  
  140.         case 'W':
  141.             toggle(Wflag);
  142.             break;
  143.  
  144.         case 'a':
  145.             nargc = atoi(optarg);
  146.             break;
  147.  
  148.         case 'd':
  149.             newoutfd = atoi(optarg);
  150.             break;
  151.  
  152.         case 'f':
  153.             adotout = optarg;
  154.             break;
  155.  
  156.         case 'h':
  157.             if (hist_init(atoi(optarg)) == -1)
  158.                 exit(1);
  159.             break;
  160.  
  161.         case 'o':
  162.             newoutfile = optarg;
  163.             output_file_has_been_specified = 1;
  164.             break;
  165.  
  166.         case 'v':
  167.             printf("%s\n", version_string);
  168.             exit(0);
  169.             break;
  170.  
  171.         case '?':
  172.         default:
  173.             usage();
  174.             exit(1);
  175.         }
  176.     }
  177.  
  178.     /*
  179.      * Trailing arguments?
  180.      */
  181.     if (optind >= argc)
  182.     {
  183.         /*
  184.          * No -- use the default.
  185.          */
  186.         app = &default_argv[0];
  187.         epp = &envp[0];
  188.     }
  189.     else
  190.     {
  191.         /*
  192.          * Yes -- use them.
  193.          */
  194.         app = &argv[optind];
  195.         if (nargc == -1)
  196.             epp = &envp[0];
  197.         else
  198.         {
  199.             /*
  200.              * Overwrite the dummy argument
  201.              * to use it as an argument vector terminator.
  202.              * The environment will be got from
  203.              * the rest.
  204.              */
  205.             argv[optind + nargc] = (char *)0;
  206.             epp = &argv[optind + nargc + 1];
  207.         }
  208.     }
  209.  
  210.     if (adotout == (char *)0)
  211.     {
  212.         /*
  213.          * Find the executable.
  214.          */
  215.         if ((adotout = execvpath(*app)) == (char *)0)
  216.         {
  217.             couldnot("find executable \"%s\"", *app);
  218.             exit(1);
  219.         }
  220.     }
  221.  
  222.     if (fd_init(newoutfd) == -1)
  223.         exit(1);
  224.  
  225.     if (output_file_has_been_specified)
  226.     {
  227.         if (Wflag)
  228.         {
  229.             if ((newoutfp = fopen(newoutfile, "w")) == (FILE *)0)
  230.             {
  231.                 couldnot("fopen(\"%s\", \"w\")", newoutfile);
  232.                 exit(1);
  233.             }
  234.             (void)fclose(newoutfp);
  235.         }
  236.  
  237.         if ((newoutfp = fopen(newoutfile, "a")) == (FILE *)0)
  238.         {
  239.             couldnot("fopen(\"%s\", \"a\")", newoutfile);
  240.             exit(1);
  241.         }
  242.     }
  243.     else
  244.     {
  245.         if (newoutfd == -1)
  246.         {
  247.             if ((newoutfd = dup(1)) == -1)
  248.             {
  249.                 couldnot("dup(1)");
  250.                 exit(1);
  251.             }
  252.         }
  253.  
  254.         if ((newoutfp = fdopen(newoutfd, "a")) == (FILE *)0)
  255.         {
  256.             couldnot("fdopen(%d, \"a\")", newoutfd);
  257.             exit(1);
  258.         }
  259.     }
  260.  
  261.     outfp = newoutfp;
  262.  
  263.     if (setobuf() == -1)
  264.         exit(1);
  265.  
  266.     if (load(adotout, app, epp) == -1)
  267.         exit(1);
  268.  
  269.     if (go() == -1)
  270.     {
  271.         histo_dump();
  272.         hist_dump();
  273.         exit(1);
  274.     }
  275.  
  276.     histo_dump();
  277.     hist_dump();
  278.  
  279.     exit(0);
  280. }
  281.  
  282. int
  283. setobuf()
  284. {
  285.     if (Lflag)
  286.     {
  287.         static char    obuf[4096];
  288.  
  289.         if (setvbuf(outfp, &obuf[0], _IOLBF, sizeof(obuf)) != 0)
  290.         {
  291.             couldnot("set line buffering on output file");
  292.             return -1;
  293.         }
  294.     }
  295.  
  296.     return 0;
  297. }
  298.  
  299. static
  300. char    *
  301. itoa(i)
  302. int    i;
  303. {
  304.     static char    result[16];
  305.  
  306.     (void)sprintf(&result[0], "%d", i);
  307.  
  308.     return &result[0];
  309. }
  310.  
  311. #define    duplicate(f,cp,l)    { if (f) *cp++ = l; }
  312. #define    negate(f,cp,l)        duplicate(!(f), (cp), (l))
  313.  
  314. /*
  315.  * We are given a (filename,argument,environment) vector that
  316.  * looks like this:
  317.  *
  318.  *    filename,
  319.  *    arg[0], arg[1], ..., arg[N-1]
  320.  *    env[0], env[1], ..., env[M-1]
  321.  *
  322.  * while our arguments are gargv[0], ..., gargv[A-1].
  323.  * and our environment is genv[0], ..., genv[G-1].
  324.  *
  325.  * We make the (filename,argument,environment) vector look
  326.  * like this:
  327.  *
  328.  *    execvpath(gargv[0])
  329.  *    execvpath(gargv[0]), -d, fd, -myflags, -f, filename, -a, N, --, argv[0], argv[1], ..., argv[N-1], E, env[0], env[1], ..., env[E-1]
  330.  *    genv[0], genv[1], ..., genv[G-1]
  331.  *
  332.  * and we leave our environment as is.
  333.  *
  334.  * e.g.
  335.  *
  336.  *    /bin/sh
  337.  *    -sh
  338.  *    PATH=...
  339.  *
  340.  * might become
  341.  *
  342.  *    /usr/local/bin/trash
  343.  *    /usr/local/bin/trash -d 18 -ABFT -f /bin/sh -a 1 -- -sh 23 PATH=...
  344.  *    HOME=...
  345.  */
  346. int
  347. augment_execve_args(fp, appp, eppp)
  348. char    **fp;
  349. char    ***appp;
  350. char    ***eppp;
  351. {
  352.     char    flagsbuf[128];
  353.     int    argc;
  354.     char    **argp;
  355.     int    envc;
  356.     char    **envp;
  357.     int    newargc;
  358.     char    *result_filename;
  359.     char    **result_argp;
  360.     char    **result_envp;
  361.     int    argi;
  362.     int    i;
  363.     char    *cp;
  364.  
  365.     /*
  366.      * The new filename.
  367.      */
  368.     if ((result_filename = strdup(execvpath(gargv[0]))) == (char *)0)
  369.     {
  370.         vcouldnot("allocate enough memory for pre-execve filename");
  371.         return -1;
  372.     }
  373.  
  374.     /*
  375.      * The new arg vector.
  376.      */
  377.     for (argp = *appp, argc = 0; argp[argc] != (char *)0; argc++)
  378.         ;
  379.  
  380.     for (envp = *eppp, envc = 0; envp[envc] != (char *)0; envc++)
  381.         ;
  382.  
  383.     newargc = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + argc + 1 + envc + 1;
  384.  
  385.     if ((result_argp = (char **)malloc(newargc * sizeof(char *))) == (char **)0)
  386.     {
  387.         vcouldnot("allocate enough memory for %d pre-execve arguments", newargc);
  388.         return -1;
  389.     }
  390.  
  391.     argi = 0;
  392.     if ((result_argp[argi++] = strdup(result_filename)) == (char *)0)
  393.     {
  394.         vcouldnot("allocate enough memory for pre-execve argv[0]");
  395.         return -1;
  396.     }
  397.  
  398. {
  399.     if ((result_argp[argi++] = strdup("-d")) == (char *)0)
  400.     {
  401.         vcouldnot("allocate enough memory for pre-execve -d");
  402.         return -1;
  403.     }
  404.     if ((result_argp[argi++] = strdup(itoa(fileno(outfp)))) == (char *)0)
  405.     {
  406.         vcouldnot("allocate enough memory for pre-execve fd");
  407.         return -1;
  408.     }
  409. }
  410.  
  411.     /*
  412.      * Calculate the new flags.
  413.      */
  414.     cp = &flagsbuf[0];
  415.     *cp++ = '-';
  416.  
  417.     duplicate(Aflag, cp, 'A');
  418.     duplicate(Bflag, cp, 'B');
  419.     duplicate(Cflag, cp, 'C');
  420.     duplicate(Fflag, cp, 'F');
  421.     duplicate(Iflag, cp, 'I');
  422.     negate(Lflag, cp, 'L');
  423.     duplicate(Mflag, cp, 'M');
  424.     duplicate(Nflag, cp, 'N');
  425.     duplicate(Pflag, cp, 'P');
  426.     duplicate(Rflag, cp, 'R');
  427.     negate(Sflag, cp, 'S');
  428.     duplicate(Tflag, cp, 'T');
  429.     duplicate(Vflag, cp, 'V');
  430.  
  431.     *cp++ = 'W';
  432.     *cp = '\0';
  433.  
  434.     if ((result_argp[argi++] = strdup(&flagsbuf[0])) == (char *)0)
  435.     {
  436.         vcouldnot("allocate enough memory for pre-execve flagsbuf");
  437.         return -1;
  438.     }
  439.  
  440.     if ((result_argp[argi++] = strdup("-f")) == (char *)0)
  441.     {
  442.         vcouldnot("allocate enough memory for pre-execve -f");
  443.         return -1;
  444.     }
  445.     result_argp[argi++] = *fp;
  446.  
  447.     if ((result_argp[argi++] = strdup("-a")) == (char *)0)
  448.     {
  449.         vcouldnot("allocate enough memory for pre-execve -a");
  450.         return -1;
  451.     }
  452.     if ((result_argp[argi++] = strdup(itoa(argc))) == (char *)0)
  453.     {
  454.         vcouldnot("allocate enough memory for pre-execve argc");
  455.         return -1;
  456.     }
  457.     if ((result_argp[argi++] = strdup("--")) == (char *)0)
  458.     {
  459.         vcouldnot("allocate enough memory for pre-execve --");
  460.         return -1;
  461.     }
  462.     for (i = 0; i < argc; i++)
  463.         result_argp[argi++] = argp[i];
  464.     if ((result_argp[argi++] = strdup(itoa(envc))) == (char *)0)
  465.     {
  466.         vcouldnot("allocate enough memory for pre-execve envc");
  467.         return -1;
  468.     }
  469.     for (i = 0; i < envc; i++)
  470.         result_argp[argi++] = envp[i];
  471.     result_argp[argi] = (char *)0;
  472.  
  473.     /*
  474.      * The new env vector.
  475.      */
  476.     for (envc = 0; genvp[envc] != (char *)0; envc++)
  477.         ;
  478.  
  479.     if ((result_envp = (char **)malloc((envc + 1) * sizeof(char *))) == (char **)0)
  480.     {
  481.         vcouldnot("allocate enough memory for %d pre-execve environment strings", envc + 1);
  482.         return -1;
  483.     }
  484.  
  485.     for (i = 0; i < envc; i++)
  486.     {
  487.         if ((result_envp[i] = strdup(genvp[i])) == (char *)0)
  488.         {
  489.             vcouldnot("allocate enough memory for pre-execve env string");
  490.             return -1;
  491.         }
  492.     }
  493.     result_envp[i] = (char *)0;
  494.  
  495.     /*
  496.      * Assign the results.
  497.      */
  498.     *fp = result_filename;
  499.     *appp = result_argp;
  500.     *eppp = result_envp;
  501.  
  502.     /*
  503.      * Free up the left-overs.
  504.      */
  505.     (void)free(argp);
  506.     (void)free(envp);
  507.  
  508.     if (Vflag)
  509.     {
  510.         char    **cp;
  511.  
  512.         fprintf(outfp, "execve'(filename=\"%s\",argv={", *fp);
  513.         for (cp = *appp; *cp != (char *)0; cp++)
  514.             fprintf(outfp, "\"%s\",", *cp);
  515.         fprintf(outfp, "},envp={");
  516.         for (cp = *eppp; *cp != (char *)0; cp++)
  517.             fprintf(outfp, "\"%s\",", *cp);
  518.         fprintf(outfp, "}\n");
  519.     }
  520.  
  521.     return 0;
  522. }
  523.