| ... | @@ -1122,6 +1122,7 @@ const Syscall = struct { | ... | @@ -1122,6 +1122,7 @@ const Syscall = struct { |
| 1122 | | 1122 | |
| 1123 | const max_iovecs_len = 8; | 1123 | const max_iovecs_len = 8; |
| 1124 | const splat_buffer_size = 64; | 1124 | const splat_buffer_size = 64; |
| | 1125 | const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; |
| 1125 | | 1126 | |
| 1126 | comptime { | 1127 | comptime { |
| 1127 | if (@TypeOf(posix.IOV_MAX) != void) assert(max_iovecs_len <= posix.IOV_MAX); | 1128 | if (@TypeOf(posix.IOV_MAX) != void) assert(max_iovecs_len <= posix.IOV_MAX); |
| ... | @@ -12765,12 +12766,37 @@ fn scanEnviron(t: *Threaded) void { | ... | @@ -12765,12 +12766,37 @@ fn scanEnviron(t: *Threaded) void { |
| 12765 | } | 12766 | } |
| 12766 | | 12767 | |
| 12767 | fn processReplace(userdata: ?*anyopaque, options: process.ReplaceOptions) process.ReplaceError { | 12768 | fn processReplace(userdata: ?*anyopaque, options: process.ReplaceOptions) process.ReplaceError { |
| 12768 | _ = userdata; | 12769 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12769 | _ = options; | 12770 | |
| 12770 | @panic("TODO processReplace"); | 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 | fn processReplacePath(userdata: ?*anyopaque, dir: Dir, options: process.ReplaceOptions) process.ReplaceError { | 12798 | fn processReplacePath(userdata: ?*anyopaque, dir: Dir, options: process.ReplaceOptions) process.ReplaceError { |
| | 12799 | if (!process.can_replace) return error.OperationUnsupported; |
| 12774 | _ = userdata; | 12800 | _ = userdata; |
| 12775 | _ = dir; | 12801 | _ = dir; |
| 12776 | _ = options; | 12802 | _ = options; |
| ... | @@ -12778,6 +12804,7 @@ fn processReplacePath(userdata: ?*anyopaque, dir: Dir, options: process.ReplaceO | ... | @@ -12778,6 +12804,7 @@ fn processReplacePath(userdata: ?*anyopaque, dir: Dir, options: process.ReplaceO |
| 12778 | } | 12804 | } |
| 12779 | | 12805 | |
| 12780 | fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptions) process.SpawnError!process.Child { | 12806 | fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptions) process.SpawnError!process.Child { |
| | 12807 | if (!process.can_spawn) return error.OperationUnsupported; |
| 12781 | _ = userdata; | 12808 | _ = userdata; |
| 12782 | _ = dir; | 12809 | _ = dir; |
| 12783 | _ = options; | 12810 | _ = options; |
| ... | @@ -12903,7 +12930,7 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp | ... | @@ -12903,7 +12930,7 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp |
| 12903 | errdefer destroyPipe(err_pipe); | 12930 | errdefer destroyPipe(err_pipe); |
| 12904 | | 12931 | |
| 12905 | t.scanEnviron(); // for PATH | 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 | const pid_result = try posix.fork(); | 12935 | const pid_result = try posix.fork(); |
| 12909 | if (pid_result == 0) { | 12936 | if (pid_result == 0) { |
| ... | @@ -12954,7 +12981,7 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp | ... | @@ -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 | forkBail(err_pipe[1], err); | 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,7 +14388,7 @@ fn testArgvToCommandLineWindows(argv: []const []const u8, expected_cmd_line: []c |
| 14361 | try std.testing.expectEqualStrings(expected_cmd_line, cmd_line); | 14388 | try std.testing.expectEqualStrings(expected_cmd_line, cmd_line); |
| 14362 | } | 14389 | } |
| 14363 | | 14390 | |
| 14364 | fn execvpeZ_expandArg0( | 14391 | fn posixExecv( |
| 14365 | arg0_expand: process.ArgExpansion, | 14392 | arg0_expand: process.ArgExpansion, |
| 14366 | file: [*:0]const u8, | 14393 | file: [*:0]const u8, |
| 14367 | child_argv: [*:null]?[*:0]const u8, | 14394 | child_argv: [*:null]?[*:0]const u8, |
| ... | @@ -14369,10 +14396,10 @@ fn execvpeZ_expandArg0( | ... | @@ -14369,10 +14396,10 @@ fn execvpeZ_expandArg0( |
| 14369 | PATH: []const u8, | 14396 | PATH: []const u8, |
| 14370 | ) process.ReplaceError { | 14397 | ) process.ReplaceError { |
| 14371 | const file_slice = std.mem.sliceTo(file, 0); | 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 | // Use of PATH_MAX here is valid as the path_buf will be passed | 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 | var path_buf: [posix.PATH_MAX]u8 = undefined; | 14403 | var path_buf: [posix.PATH_MAX]u8 = undefined; |
| 14377 | var it = std.mem.tokenizeScalar(u8, PATH, ':'); | 14404 | var it = std.mem.tokenizeScalar(u8, PATH, ':'); |
| 14378 | var seen_eacces = false; | 14405 | var seen_eacces = false; |
| ... | @@ -14397,7 +14424,7 @@ fn execvpeZ_expandArg0( | ... | @@ -14397,7 +14424,7 @@ fn execvpeZ_expandArg0( |
| 14397 | .expand => child_argv[0] = full_path, | 14424 | .expand => child_argv[0] = full_path, |
| 14398 | .no_expand => {}, | 14425 | .no_expand => {}, |
| 14399 | } | 14426 | } |
| 14400 | err = execveZ(full_path, child_argv, envp); | 14427 | err = posixExecvPath(full_path, child_argv, envp); |
| 14401 | switch (err) { | 14428 | switch (err) { |
| 14402 | error.AccessDenied => seen_eacces = true, | 14429 | error.AccessDenied => seen_eacces = true, |
| 14403 | error.FileNotFound, error.NotDir => {}, | 14430 | error.FileNotFound, error.NotDir => {}, |
| ... | @@ -14408,8 +14435,8 @@ fn execvpeZ_expandArg0( | ... | @@ -14408,8 +14435,8 @@ fn execvpeZ_expandArg0( |
| 14408 | return err; | 14435 | return err; |
| 14409 | } | 14436 | } |
| 14410 | | 14437 | |
| 14411 | /// This function ignores PATH environment variable. See `execvpeZ` for that. | 14438 | /// This function ignores PATH environment variable. |
| 14412 | pub fn execveZ( | 14439 | pub fn posixExecvPath( |
| 14413 | path: [*:0]const u8, | 14440 | path: [*:0]const u8, |
| 14414 | child_argv: [*:null]const ?[*:0]const u8, | 14441 | child_argv: [*:null]const ?[*:0]const u8, |
| 14415 | envp: [*:null]const ?[*:0]const u8, | 14442 | envp: [*:null]const ?[*:0]const u8, |
| ... | @@ -14447,17 +14474,6 @@ pub fn execveZ( | ... | @@ -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 | fn windowsMakePipeIn(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { | 14477 | fn windowsMakePipeIn(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const windows.SECURITY_ATTRIBUTES) !void { |
| 14462 | var rd_h: windows.HANDLE = undefined; | 14478 | var rd_h: windows.HANDLE = undefined; |
| 14463 | var wr_h: windows.HANDLE = undefined; | 14479 | var wr_h: windows.HANDLE = undefined; |