feat: add option for custom shell
This commit is contained in:
parent
5c20bd47f2
commit
d295666572
5 changed files with 62 additions and 14 deletions
|
@ -107,6 +107,13 @@ Colours can be configured individually in the \fBcolours\fR section.
|
|||
Defaults to default.
|
||||
.RE
|
||||
.
|
||||
.P
|
||||
\fBshell\fR = <shell command>;
|
||||
.RS
|
||||
The shell command used to execute commands. Defaults to /bin/sh -c.
|
||||
The value is treated as space-separated argv for the shell.
|
||||
Must be an absolut path, no $PATH-lookups are performed.
|
||||
.RE
|
||||
.
|
||||
.SH SECTION: keybinds
|
||||
.P
|
||||
|
|
|
@ -347,6 +347,7 @@ size_format: SizeFormat = .iec,
|
|||
navmode: NavMode = .descend,
|
||||
mouse_support: bool = false,
|
||||
theme: Theme = themes.default,
|
||||
shell: []const [:0]const u8 = &.{ "/bin/sh", "-c" },
|
||||
|
||||
pub fn init(self: *Self) !void {
|
||||
// This arena will hold all configuration values. Note that we don't need
|
||||
|
@ -587,6 +588,37 @@ fn assignMain(self: *Self, variable: []const u8, value: []const u8, path: []cons
|
|||
}
|
||||
log.err("{s}:{}: Unknown theme: '{s}'", .{ path, line, value });
|
||||
return error.BadConfig;
|
||||
} else if (mem.eql(u8, variable, "shell")) {
|
||||
// We do simple split-based parsing of the arguments here, this should be good
|
||||
// enough for the shell command. This employs an appraoch where the split is performed
|
||||
// twice to count the number of elements for allocation.
|
||||
|
||||
// count args
|
||||
var arg_count: usize = 0;
|
||||
{
|
||||
var iter = mem.tokenize(u8, value, " ");
|
||||
while (iter.next()) |_| {
|
||||
arg_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_count == 0 or arg_count > 32) {
|
||||
log.err("{s}:{}: 'shell' option must not be empty or have more than 32 arguments", .{ path, line });
|
||||
return error.BadConfig;
|
||||
}
|
||||
|
||||
const args = try arena.alloc([:0]const u8, arg_count);
|
||||
|
||||
// collect args
|
||||
{
|
||||
var iter = mem.tokenize(u8, value, " ");
|
||||
var i: usize = 0;
|
||||
while (iter.next()) |arg| : (i += 1) {
|
||||
args[i] = try arena.dupeZ(u8, arg);
|
||||
}
|
||||
}
|
||||
|
||||
self.shell = args;
|
||||
} else {
|
||||
// TODO maybe try to find the closes approximation and recommend it to the user?
|
||||
log.err("{s}:{}: No variable '{s}' in section 'main'", .{ path, line, variable });
|
||||
|
|
|
@ -212,7 +212,7 @@ pub fn run(self: *Self, command: [:0]const u8, comptime name: []const u8) !void
|
|||
|
||||
try self.ui.stop();
|
||||
|
||||
const ret = system.execForeground(command);
|
||||
const ret = system.execForeground(self.config.shell, command);
|
||||
|
||||
self.titlebar.setNormal();
|
||||
try self.ui.start();
|
||||
|
@ -253,7 +253,7 @@ pub fn open(self: *Self, dir: []const u8, file: []const u8) !void {
|
|||
}
|
||||
const cmd = try fmt.allocPrintZ(self.alloc, "{s} \"{s}/{s}\"", .{ self.config.opener.?, dir, file });
|
||||
defer self.alloc.free(cmd);
|
||||
try system.execBackground(cmd);
|
||||
try system.execBackground(self.config.shell, cmd);
|
||||
}
|
||||
|
||||
/// Return the name of the item currently selected with the cursor, if any.
|
||||
|
@ -556,11 +556,11 @@ fn handleReturnUserInput(self: *Self) !void {
|
|||
.command => {
|
||||
if (self.titlebar.getSelectedHistoryItem()) |cmd| {
|
||||
try self.titlebar.appendHistoryItem(cmd);
|
||||
try self.run(cmd, "/bin/sh or subprocess");
|
||||
try self.run(cmd, "shell or subprocess");
|
||||
} else if (user_input.buffer.toOwnedSliceZ()) |cmd| {
|
||||
defer self.alloc.free(cmd);
|
||||
try self.titlebar.appendHistoryItem(cmd);
|
||||
try self.run(cmd, "/bin/sh or subprocess");
|
||||
try self.run(cmd, "shell or subprocess");
|
||||
}
|
||||
},
|
||||
.search, .select, .keep, .discard => {
|
||||
|
|
|
@ -86,9 +86,9 @@ fn run(op: *const KeyOperation, foreground: bool) !void {
|
|||
const cmd = (try getFormattedBuffer(op)) orelse return;
|
||||
defer context.alloc.free(cmd);
|
||||
if (foreground) {
|
||||
try context.run(cmd, "/bin/sh or subprocess");
|
||||
try context.run(cmd, "shell or subprocess");
|
||||
} else {
|
||||
try system.execBackground(cmd);
|
||||
try system.execBackground(context.config.shell, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,14 +71,19 @@ fn handleSigWinch(_: c_int) callconv(.C) void {
|
|||
context.ui.render() catch {};
|
||||
}
|
||||
|
||||
/// Wrapper around a single fork exec of /bin/sh. Will wait until the forked
|
||||
/// Wrapper around a single fork exec of the given shell. Will wait until the forked
|
||||
/// process terminates before returning.
|
||||
pub fn execForeground(cmd: [:0]const u8) !void {
|
||||
pub fn execForeground(shell: []const [:0]const u8, cmd: [:0]const u8) !void {
|
||||
log.debug("running foreground command: '{s}'", .{cmd});
|
||||
const args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmd, null };
|
||||
var args = [_:null]?[*:0]const u8{null} ** 64;
|
||||
|
||||
for (shell, 0..) |arg , i|
|
||||
args[i] = arg.ptr;
|
||||
args[shell.len] = cmd.ptr;
|
||||
|
||||
const pid = std.posix.fork() catch try std.posix.fork();
|
||||
if (pid == 0) {
|
||||
std.posix.execveZ("/bin/sh", &args, @as([*:null]?[*:0]u8, @ptrCast(os.environ.ptr))) catch std.posix.exit(1);
|
||||
std.posix.execveZ(shell[0].ptr, &args, @as([*:null]?[*:0]u8, @ptrCast(os.environ.ptr))) catch std.posix.exit(1);
|
||||
unreachable;
|
||||
} else {
|
||||
child_pid = pid;
|
||||
|
@ -93,10 +98,14 @@ pub fn execForeground(cmd: [:0]const u8) !void {
|
|||
}
|
||||
}
|
||||
|
||||
/// Wrapper around a daemonized exec of /bin/sh.
|
||||
pub fn execBackground(cmd: [:0]const u8) !void {
|
||||
/// Wrapper around a daemonized exec of the given shell.
|
||||
pub fn execBackground(shell: []const [:0]const u8, cmd: [:0]const u8) !void {
|
||||
log.debug("running background command: '{s}'", .{cmd});
|
||||
const args = [_:null]?[*:0]const u8{ "/bin/sh", "-c", cmd, null };
|
||||
var args = [_:null]?[*:0]const u8{null} ** 64;
|
||||
|
||||
for (shell, 0..) |arg, i|
|
||||
args[i] = arg.ptr;
|
||||
args[shell.len] = cmd;
|
||||
|
||||
// Create first child.
|
||||
const pid = std.posix.fork() catch try std.posix.fork();
|
||||
|
@ -124,7 +133,7 @@ pub fn execBackground(cmd: [:0]const u8) !void {
|
|||
}
|
||||
|
||||
// Execute the command, or die should we fail.
|
||||
std.posix.execveZ("/bin/sh", &args, @as([*:null]?[*:0]u8, @ptrCast(os.environ.ptr))) catch std.posix.exit(1);
|
||||
std.posix.execveZ(shell[0].ptr, &args, @as([*:null]?[*:0]u8, @ptrCast(os.environ.ptr))) catch std.posix.exit(1);
|
||||
unreachable;
|
||||
} else {
|
||||
// Exit first child immediately.
|
||||
|
|
Loading…
Reference in a new issue