blob: 1ddf1cdc6dbefa28bd06eadec6ba8c510bf61287 [file] [log] [blame]
James Kuszmaulb13e13f2023-11-22 20:44:04 -08001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include <poll.h>
6#include <spawn.h>
7#include <sys/syscall.h>
8#include <sys/types.h>
9#include <unistd.h>
10
11#include <climits>
12#include <cstdio>
13#include <cstring>
14#include <filesystem>
15
16int main(int argc, char* argv[]) {
17 char path[PATH_MAX];
18 char dest[PATH_MAX];
19 std::memset(dest, 0, sizeof(dest)); // readlink does not null terminate!
20 pid_t pid = getpid();
21 std::snprintf(path, PATH_MAX, "/proc/%d/exe", pid);
22 int readlink_len = readlink(path, dest, PATH_MAX);
23 if (readlink_len < 0) {
24 std::perror("readlink");
25 return 1;
26 } else if (readlink_len == PATH_MAX) {
27 std::printf("Truncation occurred\n");
28 return 1;
29 }
30
31 std::filesystem::path exePath{dest};
32 if (exePath.empty()) {
33 return 1;
34 }
35
36 if (!exePath.has_stem()) {
37 return 1;
38 }
39
40 if (!exePath.has_parent_path()) {
41 return 1;
42 }
43
44 std::filesystem::path jarPath{exePath};
45 jarPath.replace_extension("jar");
46 std::filesystem::path parentPath{exePath.parent_path()};
47
48 if (!parentPath.has_parent_path()) {
49 return 1;
50 }
51 std::filesystem::path toolsFolder{parentPath.parent_path()};
52
53 std::filesystem::path Java = toolsFolder / "jdk" / "bin" / "java";
54
55 pid = 0;
56 std::string data = jarPath;
57 std::string jarArg = "-jar";
58 char* const arguments[] = {jarArg.data(), data.data(), nullptr};
59
60 int status =
61 posix_spawn(&pid, Java.c_str(), nullptr, nullptr, arguments, environ);
62 if (status != 0) {
63 char* home = std::getenv("JAVA_HOME");
64 std::string javaLocal = "java";
65 if (home != nullptr) {
66 std::filesystem::path javaHomePath{home};
67 javaHomePath /= "bin";
68 javaHomePath /= "java";
69 javaLocal = javaHomePath;
70 }
71
72 status = posix_spawn(&pid, javaLocal.c_str(), nullptr, nullptr, arguments,
73 environ);
74 if (status != 0) {
75 return 1;
76 }
77 }
78
79 int childPid = syscall(SYS_pidfd_open, pid, 0);
80 if (childPid <= 0) {
81 return 1;
82 }
83
84 struct pollfd pfd = {childPid, POLLIN, 0};
85 return poll(&pfd, 1, 3000);
86}