diff --git a/Userland/profile.cpp b/Userland/profile.cpp index 1503155583..cff8a5b7b8 100644 --- a/Userland/profile.cpp +++ b/Userland/profile.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -31,25 +32,63 @@ int main(int argc, char** argv) { - if (argc != 3) { - printf("usage: profile \n"); + Core::ArgsParser args_parser; + + const char* pid_argument = nullptr; + const char* cmd_argument = nullptr; + bool enable = false; + bool disable = false; + + args_parser.add_option(pid_argument, "Target PID", nullptr, 'p', "PID"); + args_parser.add_option(enable, "Enable", nullptr, 'e'); + args_parser.add_option(disable, "Disable", nullptr, 'd'); + args_parser.add_option(cmd_argument, "Command", nullptr, 'c', "command"); + + args_parser.parse(argc, argv); + + if (!pid_argument && !cmd_argument) { + args_parser.print_usage(stdout, argv[0]); return 0; } - pid_t pid = atoi(argv[1]); - bool enabled = !strcmp(argv[2], "on"); - - if (enabled) { - if (profiling_enable(pid) < 0) { - perror("profiling_enable"); + if (pid_argument) { + if (!(enable ^ disable)) { + fprintf(stderr, "-p requires -e xor -d.\n"); return 1; } + + pid_t pid = atoi(pid_argument); + + if (enable) { + if (profiling_enable(pid) < 0) { + perror("profiling_enable"); + return 1; + } + return 0; + } + + if (profiling_disable(pid) < 0) { + perror("profiling_disable"); + return 1; + } + return 0; } - if (profiling_disable(pid) < 0) { - perror("profiling_disable"); + auto cmd_parts = String(cmd_argument).split(' '); + Vector cmd_argv; + + for (auto& part : cmd_parts) + cmd_argv.append(part.characters()); + + cmd_argv.append(nullptr); + + dbg() << "Enabling profiling for PID " << getpid(); + profiling_enable(getpid()); + if (execvp(cmd_argv[0], const_cast(cmd_argv.data())) < 0) { + perror("execv"); return 1; } + return 0; }