home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
-
- /*
- * Simulate the execution of a process
- * on a MIPS R[CS]3330 under RISC/os 4.52.
- */
-
- #define DEFAULT_OUTNAME "<stderr>"
- #define DEFAULT_OUTFP stderr
-
- #define toggle(f) (f) = 1 - (f)
-
- extern int fd_init();
- extern int hist_init();
- extern void histo_dump();
- extern void hist_dump();
- extern char *strdup();
- extern int getopt();
- extern void usage();
- extern int load();
- extern int go();
- extern char *execvpath();
- extern int setobuf();
-
- extern int optind;
- extern char *optarg;
-
- char **gargv;
- char **genvp;
- char *usage_args = " [-ABCFHILMNPRSTVW] [-a argc] [-d fd] [-f executable ] [-h history_length] [-o outfile] [-v] [command ..]";
- char *getopt_args = "ABCFHILMNPRSTVWa:d:f:h:o:v";
- int Aflag; /* show read/write/execve args */
- int Bflag; /* print page no.s */
- int Cflag; /* C-like trace format */
- int Fflag; /* follow across execvp */
- int Hflag; /* emit an execution histogram */
- int Iflag; /* show instructions */
- int Lflag = 1; /* line buffer output */
- int Mflag; /* show memory accesses */
- int Nflag; /* show instrn counts */
- int Pflag; /* show syscalls before */
- int Rflag; /* show register accesses */
- int Sflag = 1; /* show syscalls after */
- int Tflag; /* show system time */
- int Vflag; /* be verbose */
- int Wflag = 1; /* truncate outfile b4 writing */
- FILE *outfp = DEFAULT_OUTFP;
- char *adotout; /* explicit executable */
- int nargc = -1; /* # of argv's before env's */
-
- unsigned long instruction_count;
- unsigned long instruction_count_since_last_syscall;
-
- static char *version_string = "Version 5";
- static int output_file_has_been_specified;
- static char *default_argv[] =
- {
- "a.out",
- (char *)0
- };
-
- main(argc, argv, envp)
- int argc;
- char *argv[];
- char *envp[];
- {
- int c;
- char *newoutfile;
- int newoutfd;
- FILE *newoutfp;
- char **app;
- char **epp;
-
- gargv = &argv[0];
- genvp = &envp[0];
-
- newoutfile = (char *)0;
- newoutfd = -1;
-
- while ((c = getopt(argc, argv, getopt_args)) != -1)
- {
- switch (c)
- {
- case 'A':
- toggle(Aflag);
- break;
-
- case 'B':
- toggle(Bflag);
- break;
-
- case 'C':
- toggle(Cflag);
- break;
-
- case 'F':
- toggle(Fflag);
- break;
-
- case 'H':
- toggle(Hflag);
- break;
-
- case 'I':
- toggle(Iflag);
- break;
-
- case 'L':
- toggle(Lflag);
- break;
-
- case 'M':
- toggle(Mflag);
- break;
-
- case 'N':
- toggle(Nflag);
- break;
-
- case 'P':
- toggle(Pflag);
- break;
-
- case 'R':
- toggle(Rflag);
- break;
-
- case 'S':
- toggle(Sflag);
- break;
-
- case 'T':
- toggle(Tflag);
- break;
-
- case 'V':
- toggle(Vflag);
- break;
-
- case 'W':
- toggle(Wflag);
- break;
-
- case 'a':
- nargc = atoi(optarg);
- break;
-
- case 'd':
- newoutfd = atoi(optarg);
- break;
-
- case 'f':
- adotout = optarg;
- break;
-
- case 'h':
- if (hist_init(atoi(optarg)) == -1)
- exit(1);
- break;
-
- case 'o':
- newoutfile = optarg;
- output_file_has_been_specified = 1;
- break;
-
- case 'v':
- printf("%s\n", version_string);
- exit(0);
- break;
-
- case '?':
- default:
- usage();
- exit(1);
- }
- }
-
- /*
- * Trailing arguments?
- */
- if (optind >= argc)
- {
- /*
- * No -- use the default.
- */
- app = &default_argv[0];
- epp = &envp[0];
- }
- else
- {
- /*
- * Yes -- use them.
- */
- app = &argv[optind];
- if (nargc == -1)
- epp = &envp[0];
- else
- {
- /*
- * Overwrite the dummy argument
- * to use it as an argument vector terminator.
- * The environment will be got from
- * the rest.
- */
- argv[optind + nargc] = (char *)0;
- epp = &argv[optind + nargc + 1];
- }
- }
-
- if (adotout == (char *)0)
- {
- /*
- * Find the executable.
- */
- if ((adotout = execvpath(*app)) == (char *)0)
- {
- couldnot("find executable \"%s\"", *app);
- exit(1);
- }
- }
-
- if (fd_init(newoutfd) == -1)
- exit(1);
-
- if (output_file_has_been_specified)
- {
- if (Wflag)
- {
- if ((newoutfp = fopen(newoutfile, "w")) == (FILE *)0)
- {
- couldnot("fopen(\"%s\", \"w\")", newoutfile);
- exit(1);
- }
- (void)fclose(newoutfp);
- }
-
- if ((newoutfp = fopen(newoutfile, "a")) == (FILE *)0)
- {
- couldnot("fopen(\"%s\", \"a\")", newoutfile);
- exit(1);
- }
- }
- else
- {
- if (newoutfd == -1)
- {
- if ((newoutfd = dup(1)) == -1)
- {
- couldnot("dup(1)");
- exit(1);
- }
- }
-
- if ((newoutfp = fdopen(newoutfd, "a")) == (FILE *)0)
- {
- couldnot("fdopen(%d, \"a\")", newoutfd);
- exit(1);
- }
- }
-
- outfp = newoutfp;
-
- if (setobuf() == -1)
- exit(1);
-
- if (load(adotout, app, epp) == -1)
- exit(1);
-
- if (go() == -1)
- {
- histo_dump();
- hist_dump();
- exit(1);
- }
-
- histo_dump();
- hist_dump();
-
- exit(0);
- }
-
- int
- setobuf()
- {
- if (Lflag)
- {
- static char obuf[4096];
-
- if (setvbuf(outfp, &obuf[0], _IOLBF, sizeof(obuf)) != 0)
- {
- couldnot("set line buffering on output file");
- return -1;
- }
- }
-
- return 0;
- }
-
- static
- char *
- itoa(i)
- int i;
- {
- static char result[16];
-
- (void)sprintf(&result[0], "%d", i);
-
- return &result[0];
- }
-
- #define duplicate(f,cp,l) { if (f) *cp++ = l; }
- #define negate(f,cp,l) duplicate(!(f), (cp), (l))
-
- /*
- * We are given a (filename,argument,environment) vector that
- * looks like this:
- *
- * filename,
- * arg[0], arg[1], ..., arg[N-1]
- * env[0], env[1], ..., env[M-1]
- *
- * while our arguments are gargv[0], ..., gargv[A-1].
- * and our environment is genv[0], ..., genv[G-1].
- *
- * We make the (filename,argument,environment) vector look
- * like this:
- *
- * execvpath(gargv[0])
- * 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]
- * genv[0], genv[1], ..., genv[G-1]
- *
- * and we leave our environment as is.
- *
- * e.g.
- *
- * /bin/sh
- * -sh
- * PATH=...
- *
- * might become
- *
- * /usr/local/bin/trash
- * /usr/local/bin/trash -d 18 -ABFT -f /bin/sh -a 1 -- -sh 23 PATH=...
- * HOME=...
- */
- int
- augment_execve_args(fp, appp, eppp)
- char **fp;
- char ***appp;
- char ***eppp;
- {
- char flagsbuf[128];
- int argc;
- char **argp;
- int envc;
- char **envp;
- int newargc;
- char *result_filename;
- char **result_argp;
- char **result_envp;
- int argi;
- int i;
- char *cp;
-
- /*
- * The new filename.
- */
- if ((result_filename = strdup(execvpath(gargv[0]))) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve filename");
- return -1;
- }
-
- /*
- * The new arg vector.
- */
- for (argp = *appp, argc = 0; argp[argc] != (char *)0; argc++)
- ;
-
- for (envp = *eppp, envc = 0; envp[envc] != (char *)0; envc++)
- ;
-
- newargc = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + argc + 1 + envc + 1;
-
- if ((result_argp = (char **)malloc(newargc * sizeof(char *))) == (char **)0)
- {
- vcouldnot("allocate enough memory for %d pre-execve arguments", newargc);
- return -1;
- }
-
- argi = 0;
- if ((result_argp[argi++] = strdup(result_filename)) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve argv[0]");
- return -1;
- }
-
- {
- if ((result_argp[argi++] = strdup("-d")) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve -d");
- return -1;
- }
- if ((result_argp[argi++] = strdup(itoa(fileno(outfp)))) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve fd");
- return -1;
- }
- }
-
- /*
- * Calculate the new flags.
- */
- cp = &flagsbuf[0];
- *cp++ = '-';
-
- duplicate(Aflag, cp, 'A');
- duplicate(Bflag, cp, 'B');
- duplicate(Cflag, cp, 'C');
- duplicate(Fflag, cp, 'F');
- duplicate(Iflag, cp, 'I');
- negate(Lflag, cp, 'L');
- duplicate(Mflag, cp, 'M');
- duplicate(Nflag, cp, 'N');
- duplicate(Pflag, cp, 'P');
- duplicate(Rflag, cp, 'R');
- negate(Sflag, cp, 'S');
- duplicate(Tflag, cp, 'T');
- duplicate(Vflag, cp, 'V');
-
- *cp++ = 'W';
- *cp = '\0';
-
- if ((result_argp[argi++] = strdup(&flagsbuf[0])) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve flagsbuf");
- return -1;
- }
-
- if ((result_argp[argi++] = strdup("-f")) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve -f");
- return -1;
- }
- result_argp[argi++] = *fp;
-
- if ((result_argp[argi++] = strdup("-a")) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve -a");
- return -1;
- }
- if ((result_argp[argi++] = strdup(itoa(argc))) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve argc");
- return -1;
- }
- if ((result_argp[argi++] = strdup("--")) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve --");
- return -1;
- }
- for (i = 0; i < argc; i++)
- result_argp[argi++] = argp[i];
- if ((result_argp[argi++] = strdup(itoa(envc))) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve envc");
- return -1;
- }
- for (i = 0; i < envc; i++)
- result_argp[argi++] = envp[i];
- result_argp[argi] = (char *)0;
-
- /*
- * The new env vector.
- */
- for (envc = 0; genvp[envc] != (char *)0; envc++)
- ;
-
- if ((result_envp = (char **)malloc((envc + 1) * sizeof(char *))) == (char **)0)
- {
- vcouldnot("allocate enough memory for %d pre-execve environment strings", envc + 1);
- return -1;
- }
-
- for (i = 0; i < envc; i++)
- {
- if ((result_envp[i] = strdup(genvp[i])) == (char *)0)
- {
- vcouldnot("allocate enough memory for pre-execve env string");
- return -1;
- }
- }
- result_envp[i] = (char *)0;
-
- /*
- * Assign the results.
- */
- *fp = result_filename;
- *appp = result_argp;
- *eppp = result_envp;
-
- /*
- * Free up the left-overs.
- */
- (void)free(argp);
- (void)free(envp);
-
- if (Vflag)
- {
- char **cp;
-
- fprintf(outfp, "execve'(filename=\"%s\",argv={", *fp);
- for (cp = *appp; *cp != (char *)0; cp++)
- fprintf(outfp, "\"%s\",", *cp);
- fprintf(outfp, "},envp={");
- for (cp = *eppp; *cp != (char *)0; cp++)
- fprintf(outfp, "\"%s\",", *cp);
- fprintf(outfp, "}\n");
- }
-
- return 0;
- }
-