| ... | ... | @@ -1122,6 +1122,7 @@ const Syscall = struct { |
| 1122 | 1122 | |
| 1123 | 1123 | const max_iovecs_len = 8; |
| 1124 | 1124 | const splat_buffer_size = 64; |
| 1125 | const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; |
| 1125 | 1126 | |
| 1126 | 1127 | comptime { |
| 1127 | 1128 | if (@TypeOf(posix.IOV_MAX) != void) assert(max_iovecs_len <= posix.IOV_MAX); |
| ... | ... | @@ -12765,12 +12766,37 @@ fn scanEnviron(t: *Threaded) void { |
| 12765 | 12766 | } |
| 12766 | 12767 | |
| 12767 | 12768 | fn processReplace(userdata: ?*anyopaque, options: process.ReplaceOptions) process.ReplaceError { |
| 12768 | | _ = userdata; |
| 12769 | | _ = options; |
| 12770 | | @panic("TODO processReplace"); |
| 12769 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12770 | |
| 12771 | if (!process.can_replace) return error.OperationUnsupported; |
| 12772 | |
| 12773 | t.scanEnviron(); // for PATH |
| 12774 | const PATH = t.environ.string.PATH orelse default_PATH; |
| 12775 | |
| 12776 | var arena_allocator = std.heap.ArenaAllocator.init(t.allocator); |
| 12777 | defer arena_allocator.deinit(); |
| 12778 | const arena = arena_allocator.allocator(); |
| 12779 | |
| 12780 | const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null); |
| 12781 | for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr; |
| 12782 | |
| 12783 | const envp: [*:null]const ?[*:0]const u8 = m: { |
| 12784 | const prog_fd: i32 = -1; |
| 12785 | if (options.environ_map) |environ_map| { |
| 12786 | break :m (try environ_map.createBlockPosix(arena, .{ |
| 12787 | .zig_progress_fd = prog_fd, |
| 12788 | })).ptr; |
| 12789 | } |
| 12790 | break :m (try process.Environ.createBlockPosix(t.environ.process_environ, arena, .{ |
| 12791 | .zig_progress_fd = prog_fd, |
| 12792 | })).ptr; |
| 12793 | }; |
| 12794 | |
| 12795 | return posixExecv(options.expand_arg0, argv_buf.ptr[0].?, argv_buf.ptr, envp, PATH); |
| 12771 | 12796 | } |
| 12772 | 12797 | |
| 12773 | 12798 | fn processReplacePath(userdata: ?*anyopaque, dir: Dir, options: process.ReplaceOptions) process.ReplaceError { |
| 12799 | if (!process.can_replace) return error.OperationUnsupported; |
| 12774 | 12800 | _ = userdata; |
| 12775 | 12801 | _ = dir; |
| 12776 | 12802 | _ = options; |
| ... | ... | @@ -12778,6 +12804,7 @@ fn processReplacePath(userdata: ?*anyopaque, dir: Dir, options: process.ReplaceO |
| 12778 | 12804 | } |
| 12779 | 12805 | |
| 12780 | 12806 | fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptions) process.SpawnError!process.Child { |
| 12807 | if (!process.can_spawn) return error.OperationUnsupported; |
| 12781 | 12808 | _ = userdata; |
| 12782 | 12809 | _ = dir; |
| 12783 | 12810 | _ = options; |
| ... | ... | @@ -12903,7 +12930,7 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp |
| 12903 | 12930 | errdefer destroyPipe(err_pipe); |
| 12904 | 12931 | |
| 12905 | 12932 | t.scanEnviron(); // for PATH |
| 12906 | | const PATH = t.environ.string.PATH orelse "/usr/local/bin:/bin/:/usr/bin"; |
| 12933 | const PATH = t.environ.string.PATH orelse default_PATH; |
| 12907 | 12934 | |
| 12908 | 12935 | const pid_result = try posix.fork(); |
| 12909 | 12936 | if (pid_result == 0) { |
| ... | ... | @@ -12954,7 +12981,7 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp |
| 12954 | 12981 | } |
| 12955 | 12982 | } |
| 12956 | 12983 | |
| 12957 | | const err = execvpeZ_expandArg0(options.expand_arg0, argv_buf.ptr[0].?, argv_buf.ptr, envp, PATH); |
| 12984 | const err = posixExecv(options.expand_arg0, argv_buf.ptr[0].?, argv_buf.ptr, envp, PATH); |
| 12958 | 12985 | forkBail(err_pipe[1], err); |
| 12959 | 12986 | } |
| 12960 | 12987 | |
| ... | ... | @@ -14361,7 +14388,7 @@ fn testArgvToCommandLineWindows(argv: []const []const u8, expected_cmd_line: []c |
| 14361 | 14388 | try std.testing.expectEqualStrings(expected_cmd_line, cmd_line); |
| 14362 | 14389 | } |
| 14363 | 14390 | |
| 14364 | | fn execvpeZ_expandArg0( |
| 14391 | fn posixExecv( |
| 14365 | 14392 | arg0_expand: process.ArgExpansion, |
| 14366 | 14393 | file: [*:0]const u8, |
| 14367 | 14394 | child_argv: [*:null]?[*:0]const u8, |
| ... | ... | @@ -14369,10 +14396,10 @@ fn execvpeZ_expandArg0( |
| 14369 | 14396 | PATH: []const u8, |
| 14370 | 14397 | ) process.ReplaceError { |
| 14371 | 14398 | const file_slice = std.mem.sliceTo(file, 0); |
| 14372 | | if (std.mem.findScalar(u8, file_slice, '/') != null) return execveZ(file, child_argv, envp); |
| 14399 | if (std.mem.findScalar(u8, file_slice, '/') != null) return posixExecvPath(file, child_argv, envp); |
| 14373 | 14400 | |
| 14374 | 14401 | // Use of PATH_MAX here is valid as the path_buf will be passed |
| 14375 | | // directly to the operating system in execveZ. |
| 14402 | // directly to the operating system in posixExecvPath. |
| 14376 | 14403 | var path_buf: [posix.PATH_MAX]u8 = undefined; |
| 14377 | 14404 | var it = std.mem.tokenizeScalar(u8, PATH, ':'); |
| 14378 | 14405 | var seen_eacces = false; |
| ... | ... | @@ -14397,7 +14424,7 @@ fn execvpeZ_expandArg0( |
| 14397 | 14424 | .expand => child_argv[0] = full_path, |
| 14398 | 14425 | .no_expand => {}, |
| 14399 | 14426 | } |
| 14400 | | err = execveZ(full_path, child_argv, envp); |
| 14427 | err = posixExecvPath(full_path, child_argv, envp); |
| 14401 | 14428 | switch (err) { |
| 14402 | 14429 | error.AccessDenied => seen_eacces = true, |
| 14403 | 14430 | error.FileNotFound, error.NotDir => {}, |
| ... | ... | @@ -14408,8 +14435,8 @@ fn execvpeZ_expandArg0( |
| 14408 | 14435 | return err; |
| 14409 | 14436 | } |
| 14410 | 14437 | |
| 14411 | | /// This function ignores PATH environment variable. See `execvpeZ` for that. |
| 14412 | | pub fn execveZ( |
| 14438 | /// This function ignores PATH environment variable. |
| 14439 | pub fn posixExecvPath( |
| 14413 | 14440 | path: [*:0]const u8, |
| 14414 | 14441 | child_argv: [*:null]const ?[*:0]const u8, |
| 14415 | 14442 | envp: [*:null]const ?[*:0]const u8, |
| ... | ... | @@ -14447,17 +14474,6 @@ pub fn execveZ( |
| 14447 | 14474 | } |
| 14448 | 14475 | } |
| 14449 | 14476 | |
| 14450 | | /// This function also uses the PATH environment variable to get the full path to the executable. |
| 14451 | | /// If `file` is an absolute path, this is the same as `execveZ`. |
| 14452 | | pub fn execvpeZ( |
| 14453 | | file: [*:0]const u8, |
| 14454 | | argv_ptr: [*:null]const ?[*:0]const u8, |
| 14455 | | envp: [*:null]const ?[*:0]const u8, |
| 14456 | | PATH: []const u8, |
| 14457 | | ) process.ReplaceError { |
| 14458 | | return execvpeZ_expandArg0(.no_expand, file, argv_ptr, envp, PATH); |
| 14459 | | } |
| 14460 | | |
| 14461 | 14477 | fn windowsMakePipeIn(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { |
| 14462 | 14478 | var rd_h: windows.HANDLE = undefined; |
| 14463 | 14479 | var wr_h: windows.HANDLE = undefined; |