| ... | ... | @@ -203,15 +203,11 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { |
| 203 | 203 | /// This function must allocate memory to add a null terminating bytes on path and each arg. |
| 204 | 204 | /// It must also convert to KEY=VALUE\0 format for environment variables, and include null |
| 205 | 205 | /// pointers after the args and after the environment variables. |
| 206 | | /// Also make the first arg equal to path. |
| 207 | | pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const BufMap, |
| 208 | | allocator: &Allocator) -> %usize |
| 206 | /// Also make the first arg equal to exe_path. |
| 207 | /// This function also uses the PATH environment variable to get the full path to the executable. |
| 208 | pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &const BufMap, |
| 209 | allocator: &Allocator) -> %void |
| 209 | 210 | { |
| 210 | | const path_buf = %return allocator.alloc(u8, path.len + 1); |
| 211 | | defer allocator.free(path_buf); |
| 212 | | @memcpy(&path_buf[0], &path[0], path.len); |
| 213 | | path_buf[path.len] = 0; |
| 214 | | |
| 215 | 211 | const argv_buf = %return allocator.alloc(?&const u8, argv.len + 2); |
| 216 | 212 | mem.set(?&const u8, argv_buf, null); |
| 217 | 213 | defer { |
| ... | ... | @@ -222,10 +218,10 @@ pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const B |
| 222 | 218 | allocator.free(argv_buf); |
| 223 | 219 | } |
| 224 | 220 | { |
| 225 | | // Add path to the first argument. |
| 226 | | const arg_buf = %return allocator.alloc(u8, path.len + 1); |
| 227 | | @memcpy(&arg_buf[0], path.ptr, path.len); |
| 228 | | arg_buf[path.len] = 0; |
| 221 | // Add exe_path to the first argument. |
| 222 | const arg_buf = %return allocator.alloc(u8, exe_path.len + 1); |
| 223 | @memcpy(&arg_buf[0], exe_path.ptr, exe_path.len); |
| 224 | arg_buf[exe_path.len] = 0; |
| 229 | 225 | |
| 230 | 226 | argv_buf[0] = arg_buf.ptr; |
| 231 | 227 | } |
| ... | ... | @@ -266,7 +262,58 @@ pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const B |
| 266 | 262 | } |
| 267 | 263 | envp_buf[envp_count] = null; |
| 268 | 264 | |
| 269 | | return posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr); |
| 265 | |
| 266 | if (mem.indexOfScalar(u8, exe_path, '/') != null) { |
| 267 | // +1 for the null terminating byte |
| 268 | const path_buf = %return allocator.alloc(u8, exe_path.len + 1); |
| 269 | defer allocator.free(path_buf); |
| 270 | @memcpy(&path_buf[0], &exe_path[0], exe_path.len); |
| 271 | path_buf[exe_path.len] = 0; |
| 272 | return posixExecveErrnoToErr(posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr))); |
| 273 | } |
| 274 | |
| 275 | const PATH = getEnv("PATH") ?? ([]const u8)("/usr/local/bin:/bin/:/usr/bin"); // TODO issue #299 |
| 276 | // PATH.len because it is >= the largest search_path |
| 277 | // +1 for the / to join the search path and exe_path |
| 278 | // +1 for the null terminating byte |
| 279 | const path_buf = %return allocator.alloc(u8, PATH.len + exe_path.len + 2); |
| 280 | defer allocator.free(path_buf); |
| 281 | var it = mem.split(PATH, ':'); |
| 282 | var seen_eacces = false; |
| 283 | var err: usize = undefined; |
| 284 | while (true) { |
| 285 | const search_path = it.next() ?? break; |
| 286 | mem.copy(u8, path_buf, search_path); |
| 287 | path_buf[search_path.len] = '/'; |
| 288 | mem.copy(u8, path_buf[search_path.len + 1 ...], exe_path); |
| 289 | path_buf[search_path.len + exe_path.len + 2] = 0; |
| 290 | err = posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr)); |
| 291 | assert(err > 0); |
| 292 | if (err == errno.EACCES) { |
| 293 | seen_eacces = true; |
| 294 | } else if (err != errno.ENOENT) { |
| 295 | return posixExecveErrnoToErr(err); |
| 296 | } |
| 297 | } |
| 298 | if (seen_eacces) { |
| 299 | err = errno.EACCES; |
| 300 | } |
| 301 | return posixExecveErrnoToErr(err); |
| 302 | } |
| 303 | |
| 304 | fn posixExecveErrnoToErr(err: usize) -> error { |
| 305 | assert(err > 0); |
| 306 | return switch (err) { |
| 307 | errno.EFAULT => unreachable, |
| 308 | errno.E2BIG, errno.EMFILE, errno.ENAMETOOLONG, errno.ENFILE, errno.ENOMEM => error.SysResources, |
| 309 | errno.EACCES, errno.EPERM => error.AccessDenied, |
| 310 | errno.EINVAL, errno.ENOEXEC => error.InvalidExe, |
| 311 | errno.EIO, errno.ELOOP => error.FileSystem, |
| 312 | errno.EISDIR => error.IsDir, |
| 313 | errno.ENOENT, errno.ENOTDIR => error.FileNotFound, |
| 314 | errno.ETXTBSY => error.FileBusy, |
| 315 | else => error.Unexpected, |
| 316 | }; |
| 270 | 317 | } |
| 271 | 318 | |
| 272 | 319 | pub var environ_raw: []&u8 = undefined; |