| 108 | } |
| 109 | |
| 110 | bool RunXDGOpen(const std::string& uri) |
| 111 | { |
| 112 | std::string xdgOpen = FindXDGOpen(); |
| 113 | |
| 114 | if (xdgOpen.empty()) |
| 115 | return false; |
| 116 | |
| 117 | pid_t pid = fork(); |
| 118 | |
| 119 | if (pid == -1) |
| 120 | return false; |
| 121 | |
| 122 | if (pid == 0) |
| 123 | { |
| 124 | // Fork again. This way OS is now responsible for cleaning up the |
| 125 | // (grand)child process. |
| 126 | int secondFork = fork(); |
| 127 | |
| 128 | if (secondFork < 0) |
| 129 | return false; |
| 130 | |
| 131 | if (secondFork == 0) |
| 132 | {// Close all file descriptors except stdin, stdout, stderr |
| 133 | struct rlimit rlim; |
| 134 | if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) |
| 135 | { |
| 136 | for (int fd = STDERR_FILENO + 1; fd < rlim.rlim_cur; ++fd) |
| 137 | close(fd); |
| 138 | } |
| 139 | |
| 140 | // Open /dev/null as stdin, stdout, stderr |
| 141 | int fd = open("/dev/null", O_RDWR); |
| 142 | |
| 143 | if (fd != -1) |
| 144 | { |
| 145 | dup2(fd, STDIN_FILENO); |
| 146 | dup2(fd, STDOUT_FILENO); |
| 147 | dup2(fd, STDERR_FILENO); |
| 148 | |
| 149 | if (fd > STDERR_FILENO) |
| 150 | close(fd); |
| 151 | } |
| 152 | |
| 153 | if(!ResetEnv()) |
| 154 | _exit(1); |
| 155 | |
| 156 | char* const args[] = { |
| 157 | const_cast<char*>(xdgOpen.c_str()), |
| 158 | const_cast<char*>(uri.c_str()), |
| 159 | nullptr |
| 160 | }; |
| 161 | // Run xdg-open |
| 162 | execv(xdgOpen.c_str(), args); |
| 163 | |
| 164 | // If we get here, something went wrong |
| 165 | _exit(1); |
| 166 | } |
| 167 | else |
no test coverage detected