int main(int argc, char **argv) { pid_t pid; if (argc < 2) { printf("Usage: ./strace [-p] <pid | executable>\n"); return (EXIT_SUCCESS); } if (is_attach(argc, argv) == -1) { if ((pid = fork()) == 0) { xptrace(PTRACE_TRACEME, 0, NULL, 0); xexecvp(argv[1], &argv[1]); } else if (pid != -1) { print_execve_arg(argc, argv); strace(pid, 1); } else fprintf(stderr, "Error: fork failed\n"); } return (0); }
/* * Execute the program supplied on the command line. If restart was set * then send the child process SIGTERM and restart it. */ void run_utility(char *argv[]) { int pid; int i, m; int ret, status; struct timespec delay = { 0, 1000000 }; char **new_argv; char *p, *arg_buf; int argc; if (restart_opt == 1) terminate_utility(); /* clone argv on each invocation to make the implementation of more * complex subsitution rules possible and easy */ for (argc=0; argv[argc]; argc++); arg_buf = malloc(ARG_MAX); new_argv = calloc(argc+1, sizeof(char *)); for (m=0, i=0, p=arg_buf; i<argc; i++) { new_argv[i] = p; if ((m < 1) && (strcmp(argv[i], "/_")) == 0) { p += strlen(xrealpath(leading_edge->fn, p)); m++; } else p += strlcpy(p, argv[i], ARG_MAX - (p - arg_buf)); p++; } pid = xfork(); if (pid == -1) err(1, "can't fork"); if (pid == 0) { if (clear_opt == 1) (void) system("/usr/bin/clear"); /* Set process group so subprocess can be signaled */ if (restart_opt == 1) setpgid(0, getpid()); /* wait up to 1 seconds for each file to become available */ for (i=0; i < 10; i++) { ret = xexecvp(new_argv[0], new_argv); if (errno == ETXTBSY) nanosleep(&delay, NULL); else break; } if (ret != 0) err(1, "exec %s", new_argv[0]); } child_pid = pid; if (restart_opt == 0) xwaitpid(pid, &status, 0); xfree(arg_buf); xfree(new_argv); }