command: stylistic changes

This commit is contained in:
Mitchell Hashimoto
2023-11-05 18:03:22 -08:00
parent c9b7439354
commit 1a846597b1

View File

@ -112,145 +112,153 @@ pub fn start(self: *Command, alloc: Allocator) !void {
defer arena_allocator.deinit(); defer arena_allocator.deinit();
const arena = arena_allocator.allocator(); const arena = arena_allocator.allocator();
if (builtin.os.tag == .windows) { switch (builtin.os.tag) {
const application_w = try std.unicode.utf8ToUtf16LeWithNull(arena, self.path); .windows => try self.startWindows(arena),
const cwd_w = if (self.cwd) |cwd| try std.unicode.utf8ToUtf16LeWithNull(arena, cwd) else null; else => try self.startPosix(arena),
const command_line_w = if (self.args.len > 0) b: { }
const command_line = try windowsCreateCommandLine(arena, self.args); }
break :b try std.unicode.utf8ToUtf16LeWithNull(arena, command_line);
} else null;
const env_w = if (self.env) |env_map| try createWindowsEnvBlock(arena, env_map) else null;
const any_null_fd = self.stdin == null or self.stdout == null or self.stderr == null; fn startPosix(self: *Command, arena: Allocator) !void {
const null_fd = if (any_null_fd) try windows.OpenFile( // Null-terminate all our arguments
&[_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' }, const pathZ = try arena.dupeZ(u8, self.path);
.{ const argsZ = try arena.allocSentinel(?[*:0]u8, self.args.len, null);
.access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, for (self.args, 0..) |arg, i| argsZ[i] = (try arena.dupeZ(u8, arg)).ptr;
.share_access = windows.FILE_SHARE_READ,
.creation = windows.OPEN_EXISTING,
.io_mode = .blocking,
},
) else null;
defer if (null_fd) |fd| std.os.close(fd);
// TODO: In the case of having FDs instead of pty, need to set up attributes such that the // Determine our env vars
// child process only inherits these handles, then set bInheritsHandles below. const envp = if (self.env) |env_map|
(try createNullDelimitedEnvMap(arena, env_map)).ptr
else if (builtin.link_libc)
std.c.environ
else
@compileError("missing env vars");
const attribute_list, const stdin, const stdout, const stderr = if (self.pseudo_console) |pseudo_console| b: { // Fork
var attribute_list_size: usize = undefined; const pid = try std.os.fork();
_ = windows.exp.kernel32.InitializeProcThreadAttributeList( if (pid != 0) {
null, // Parent, return immediately.
1, self.pid = @intCast(pid);
0, return;
&attribute_list_size, }
);
const attribute_list_buf = try arena.alloc(u8, attribute_list_size); // We are the child.
if (windows.exp.kernel32.InitializeProcThreadAttributeList(
attribute_list_buf.ptr,
1,
0,
&attribute_list_size,
) == 0) return windows.unexpectedError(windows.kernel32.GetLastError());
if (windows.exp.kernel32.UpdateProcThreadAttribute( // Setup our file descriptors for std streams.
attribute_list_buf.ptr, if (self.stdin) |f| try setupFd(f.handle, os.STDIN_FILENO);
0, if (self.stdout) |f| try setupFd(f.handle, os.STDOUT_FILENO);
windows.exp.PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, if (self.stderr) |f| try setupFd(f.handle, os.STDERR_FILENO);
pseudo_console,
@sizeOf(windows.exp.HPCON),
null,
null,
) == 0) return windows.unexpectedError(windows.kernel32.GetLastError());
break :b .{ attribute_list_buf.ptr, null, null, null }; // Setup our working directory
} else b: { if (self.cwd) |cwd| try os.chdir(cwd);
const stdin = if (self.stdin) |f| f.handle else null_fd.?;
const stdout = if (self.stdout) |f| f.handle else null_fd.?;
const stderr = if (self.stderr) |f| f.handle else null_fd.?;
break :b .{ null, stdin, stdout, stderr };
};
var startup_info_ex = windows.exp.STARTUPINFOEX{ // If the user requested a pre exec callback, call it now.
.StartupInfo = .{ if (self.pre_exec) |f| f(self);
.cb = if (attribute_list != null) @sizeOf(windows.exp.STARTUPINFOEX) else @sizeOf(windows.STARTUPINFOW),
.hStdError = stderr,
.hStdOutput = stdout,
.hStdInput = stdin,
.dwFlags = windows.STARTF_USESTDHANDLES,
.lpReserved = null,
.lpDesktop = null,
.lpTitle = null,
.dwX = 0,
.dwY = 0,
.dwXSize = 0,
.dwYSize = 0,
.dwXCountChars = 0,
.dwYCountChars = 0,
.dwFillAttribute = 0,
.wShowWindow = 0,
.cbReserved2 = 0,
.lpReserved2 = null,
},
.lpAttributeList = attribute_list,
};
var flags: windows.DWORD = windows.exp.CREATE_UNICODE_ENVIRONMENT; // Finally, replace our process.
if (attribute_list != null) flags |= windows.exp.EXTENDED_STARTUPINFO_PRESENT; _ = std.os.execveZ(pathZ, argsZ, envp) catch null;
}
var process_information: windows.PROCESS_INFORMATION = undefined; fn startWindows(self: *Command, arena: Allocator) !void {
if (windows.exp.kernel32.CreateProcessW( const application_w = try std.unicode.utf8ToUtf16LeWithNull(arena, self.path);
application_w.ptr, const cwd_w = if (self.cwd) |cwd| try std.unicode.utf8ToUtf16LeWithNull(arena, cwd) else null;
if (command_line_w) |w| w.ptr else null, const command_line_w = if (self.args.len > 0) b: {
const command_line = try windowsCreateCommandLine(arena, self.args);
break :b try std.unicode.utf8ToUtf16LeWithNull(arena, command_line);
} else null;
const env_w = if (self.env) |env_map| try createWindowsEnvBlock(arena, env_map) else null;
const any_null_fd = self.stdin == null or self.stdout == null or self.stderr == null;
const null_fd = if (any_null_fd) try windows.OpenFile(
&[_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' },
.{
.access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
.share_access = windows.FILE_SHARE_READ,
.creation = windows.OPEN_EXISTING,
.io_mode = .blocking,
},
) else null;
defer if (null_fd) |fd| std.os.close(fd);
// TODO: In the case of having FDs instead of pty, need to set up
// attributes such that the child process only inherits these handles,
// then set bInheritsHandles below.
const attribute_list, const stdin, const stdout, const stderr = if (self.pseudo_console) |pseudo_console| b: {
var attribute_list_size: usize = undefined;
_ = windows.exp.kernel32.InitializeProcThreadAttributeList(
null, null,
null, 1,
windows.TRUE, 0,
flags, &attribute_list_size,
if (env_w) |w| w.ptr else null, );
if (cwd_w) |w| w.ptr else null,
@ptrCast(&startup_info_ex.StartupInfo), const attribute_list_buf = try arena.alloc(u8, attribute_list_size);
&process_information, if (windows.exp.kernel32.InitializeProcThreadAttributeList(
attribute_list_buf.ptr,
1,
0,
&attribute_list_size,
) == 0) return windows.unexpectedError(windows.kernel32.GetLastError()); ) == 0) return windows.unexpectedError(windows.kernel32.GetLastError());
self.pid = process_information.hProcess; if (windows.exp.kernel32.UpdateProcThreadAttribute(
} else { attribute_list_buf.ptr,
// Null-terminate all our arguments 0,
const pathZ = try arena.dupeZ(u8, self.path); windows.exp.PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
const argsZ = try arena.allocSentinel(?[*:0]u8, self.args.len, null); pseudo_console,
for (self.args, 0..) |arg, i| argsZ[i] = (try arena.dupeZ(u8, arg)).ptr; @sizeOf(windows.exp.HPCON),
null,
null,
) == 0) return windows.unexpectedError(windows.kernel32.GetLastError());
// Determine our env vars break :b .{ attribute_list_buf.ptr, null, null, null };
const envp = if (self.env) |env_map| } else b: {
(try createNullDelimitedEnvMap(arena, env_map)).ptr const stdin = if (self.stdin) |f| f.handle else null_fd.?;
else if (builtin.link_libc) const stdout = if (self.stdout) |f| f.handle else null_fd.?;
std.c.environ const stderr = if (self.stderr) |f| f.handle else null_fd.?;
else break :b .{ null, stdin, stdout, stderr };
@compileError("missing env vars"); };
// Fork var startup_info_ex = windows.exp.STARTUPINFOEX{
const pid = try std.os.fork(); .StartupInfo = .{
if (pid != 0) { .cb = if (attribute_list != null) @sizeOf(windows.exp.STARTUPINFOEX) else @sizeOf(windows.STARTUPINFOW),
// Parent, return immediately. .hStdError = stderr,
self.pid = @intCast(pid); .hStdOutput = stdout,
return; .hStdInput = stdin,
} .dwFlags = windows.STARTF_USESTDHANDLES,
.lpReserved = null,
.lpDesktop = null,
.lpTitle = null,
.dwX = 0,
.dwY = 0,
.dwXSize = 0,
.dwYSize = 0,
.dwXCountChars = 0,
.dwYCountChars = 0,
.dwFillAttribute = 0,
.wShowWindow = 0,
.cbReserved2 = 0,
.lpReserved2 = null,
},
.lpAttributeList = attribute_list,
};
// We are the child. var flags: windows.DWORD = windows.exp.CREATE_UNICODE_ENVIRONMENT;
if (attribute_list != null) flags |= windows.exp.EXTENDED_STARTUPINFO_PRESENT;
// Setup our file descriptors for std streams. var process_information: windows.PROCESS_INFORMATION = undefined;
if (self.stdin) |f| try setupFd(f.handle, os.STDIN_FILENO); if (windows.exp.kernel32.CreateProcessW(
if (self.stdout) |f| try setupFd(f.handle, os.STDOUT_FILENO); application_w.ptr,
if (self.stderr) |f| try setupFd(f.handle, os.STDERR_FILENO); if (command_line_w) |w| w.ptr else null,
null,
null,
windows.TRUE,
flags,
if (env_w) |w| w.ptr else null,
if (cwd_w) |w| w.ptr else null,
@ptrCast(&startup_info_ex.StartupInfo),
&process_information,
) == 0) return windows.unexpectedError(windows.kernel32.GetLastError());
// Setup our working directory self.pid = process_information.hProcess;
if (self.cwd) |cwd| try os.chdir(cwd);
// If the user requested a pre exec callback, call it now.
if (self.pre_exec) |f| f(self);
// Finally, replace our process.
_ = std.os.execveZ(pathZ, argsZ, envp) catch null;
}
} }
fn setupFd(src: File.Handle, target: i32) !void { fn setupFd(src: File.Handle, target: i32) !void {