flatpak: use host-spawn to find default shell

This commit is contained in:
Mitchell Hashimoto
2023-02-25 21:56:51 -08:00
parent 3c81287ffd
commit 6b23dbb169
3 changed files with 65 additions and 7 deletions

View File

@ -41,6 +41,26 @@ modules:
only-arches: only-arches:
- aarch64 - aarch64
# We use this to get a proper PTY on our host spawn. We should eventually
# replace this with using dbus directly.
- name: host-spawn
buildsystem: simple
build-commands:
- mkdir -p /app/bin
- mv ./host-spawn-* /app/bin/host-spawn
- chmod +x /app/bin/host-spawn
sources:
- type: file
url: https://github.com/1player/host-spawn/releases/download/1.4.1/host-spawn-x86_64
sha256: d81bb6125ec73a9a2e26266c48787367fbcb665d67c2e7fb42217f0981106cf7
only-arches:
- x86_64
- type: file
url: https://github.com/1player/host-spawn/releases/download/1.4.1/host-spawn-aarch64
sha256: 29bff846d72e37093b3fdf7859bae16addd64acc98087f8c059548df3c2273c4
only-arches:
- aarch64
- name: ghostty - name: ghostty
buildsystem: simple buildsystem: simple
build-commands: build-commands:

View File

@ -344,14 +344,18 @@ pub const Config = struct {
if (self.command == null or wd_home) command: { if (self.command == null or wd_home) command: {
const alloc = self._arena.?.allocator(); const alloc = self._arena.?.allocator();
// First look up the command using the SHELL env var. // We don't do this in flatpak because SHELL in Flatpak is
if (std.process.getEnvVarOwned(alloc, "SHELL")) |value| { // always set to /bin/sh
log.debug("default shell source=env value={s}", .{value}); if (!internal_os.isFlatpak()) {
self.command = value; // First look up the command using the SHELL env var.
if (std.process.getEnvVarOwned(alloc, "SHELL")) |value| {
log.debug("default shell source=env value={s}", .{value});
self.command = value;
// If we don't need the working directory, then we can exit now. // If we don't need the working directory, then we can exit now.
if (!wd_home) break :command; if (!wd_home) break :command;
} else |_| {} } else |_| {}
}
// We need the passwd entry for the remainder // We need the passwd entry for the remainder
const pw = try passwd.get(alloc); const pw = try passwd.get(alloc);

View File

@ -2,6 +2,7 @@ const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator; const ArenaAllocator = std.heap.ArenaAllocator;
const internal_os = @import("os/main.zig");
const log = std.log.scoped(.passwd); const log = std.log.scoped(.passwd);
@ -45,6 +46,39 @@ pub fn get(alloc: Allocator) !Entry {
var result: Entry = .{}; var result: Entry = .{};
// If we're in flatpak then our entry is always empty so we grab it
// by shelling out to the host. note that we do HAVE an entry in the
// sandbox but only the username is correct.
//
// Note: we wrap our getent call in a /bin/sh login shell because
// some operating systems (NixOS tested) don't set the PATH for various
// utilities properly until we get a login shell.
if (internal_os.isFlatpak()) {
log.info("flatpak detected, will use host-spawn to get our entry", .{});
const exec = try std.ChildProcess.exec(.{
.allocator = alloc,
.argv = &[_][]const u8{
"/app/bin/host-spawn",
"-pty",
"/bin/sh",
"-l",
"-c",
try std.fmt.allocPrint(
alloc,
"getent passwd {s}",
.{std.mem.sliceTo(pw.pw_name, 0)},
),
},
});
if (exec.term == .Exited) {
// Shell and home are the last two entries
var it = std.mem.splitBackwards(u8, exec.stdout, ":");
result.shell = it.next() orelse null;
result.home = it.next() orelse null;
return result;
}
}
if (pw.pw_shell) |ptr| { if (pw.pw_shell) |ptr| {
const source = std.mem.sliceTo(ptr, 0); const source = std.mem.sliceTo(ptr, 0);
const sh = try alloc.alloc(u8, source.len); const sh = try alloc.alloc(u8, source.len);