diff options
Diffstat (limited to 'Userland/strace.cpp')
-rw-r--r-- | Userland/strace.cpp | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/Userland/strace.cpp b/Userland/strace.cpp index 374ac1cf80..bd8b9cf61b 100644 --- a/Userland/strace.cpp +++ b/Userland/strace.cpp @@ -1,22 +1,58 @@ #include <stdio.h> #include <unistd.h> #include <stdlib.h> +#include <string.h> +#include <signal.h> #include <AK/Assertions.h> #include <AK/Types.h> #include <Kernel/Syscall.h> +static int usage() +{ + printf("usage: strace [-p PID] [command...]\n"); + return 0; +} + int main(int argc, char** argv) { - if (argc < 2) - return 1; + if (argc == 1) + return usage(); + + pid_t pid = -1; + bool pid_is_child = false; + + if (!strcmp(argv[1], "-p")) { + if (argc != 3) + return usage(); + pid = atoi(argv[2]); + } else { + pid_is_child = true; + pid = fork(); + if (!pid) { + kill(getpid(), SIGSTOP); + int rc = execvp(argv[1], &argv[1]); + if (rc < 0) { + perror("execvp"); + exit(1); + } + ASSERT_NOT_REACHED(); + } + } - int pid = atoi(argv[1]); int fd = systrace(pid); if (fd < 0) { perror("systrace"); return 1; } + if (pid_is_child) { + int rc = kill(pid, SIGCONT); + if (rc < 0) { + perror("kill(pid, SIGCONT)"); + return 1; + } + } + for (;;) { dword call[5]; int nread = read(fd, &call, sizeof(call)); @@ -27,7 +63,7 @@ int main(int argc, char** argv) return 1; } ASSERT(nread == sizeof(call)); - printf("%s(%#x, %#x, %#x) = %#x\n", Syscall::to_string((Syscall::Function)call[0]), call[1], call[2], call[3], call[4]); + fprintf(stderr, "%s(%#x, %#x, %#x) = %#x\n", Syscall::to_string((Syscall::Function)call[0]), call[1], call[2], call[3], call[4]); } int rc = close(fd); |