mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-05-04 12:54:41 +00:00
core: add function to get process info from the surface
This adds a function to the core surface to get process information about the process(es) running in the terminal. Currently supported is the PID of the foreground process and the name of the slave PTY. If there is an error retrieving the information, or the platform does not support retieving that information `null` is returned. This will be useful in exposing the foreground PID and slave PTY name to AppleScript or other APIs.
This commit is contained in:
@@ -6342,6 +6342,31 @@ fn testMouseSelectionIsNull(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that currently controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal
|
||||||
|
/// buffer so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => [:0]const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) running within the surface. Returns
|
||||||
|
/// `null` if there was an error getting the information or the information is
|
||||||
|
/// not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(self: *Surface, comptime info: ProcessInfo) ?ProcessInfo.Type(info) {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => self.io.getProcessInfo(.foreground_pid),
|
||||||
|
.tty_name => self.io.getProcessInfo(.tty_name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
test "Surface: selection logic" {
|
test "Surface: selection logic" {
|
||||||
// We disable format to make these easier to
|
// We disable format to make these easier to
|
||||||
// read by pairing sets of coordinates per line.
|
// read by pairing sets of coordinates per line.
|
||||||
|
|||||||
@@ -135,6 +135,35 @@ pub fn add(
|
|||||||
// Every exe needs the terminal options
|
// Every exe needs the terminal options
|
||||||
self.config.terminalOptions().add(b, step.root_module);
|
self.config.terminalOptions().add(b, step.root_module);
|
||||||
|
|
||||||
|
// C imports needed to manage/create PTYs
|
||||||
|
switch (target.result.os.tag) {
|
||||||
|
.freebsd => {
|
||||||
|
const c = b.addTranslateC(.{
|
||||||
|
.root_source_file = b.path("src/pty/freebsd.c"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
step.root_module.addImport("pty-c", c.createModule());
|
||||||
|
},
|
||||||
|
.linux => {
|
||||||
|
const c = b.addTranslateC(.{
|
||||||
|
.root_source_file = b.path("src/pty/linux.c"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
step.root_module.addImport("pty-c", c.createModule());
|
||||||
|
},
|
||||||
|
.macos => {
|
||||||
|
const c = b.addTranslateC(.{
|
||||||
|
.root_source_file = b.path("src/pty/macos.c"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
step.root_module.addImport("pty-c", c.createModule());
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
// Freetype. We always include this even if our font backend doesn't
|
// Freetype. We always include this even if our font backend doesn't
|
||||||
// use it because Dear Imgui uses Freetype.
|
// use it because Dear Imgui uses Freetype.
|
||||||
_ = b.systemIntegrationOption("freetype", .{}); // Shows it in help
|
_ = b.systemIntegrationOption("freetype", .{}); // Shows it in help
|
||||||
|
|||||||
174
src/pty.zig
174
src/pty.zig
@@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const windows = @import("os/main.zig").windows;
|
const windows = @import("os/main.zig").windows;
|
||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
|
const assert = @import("quirks.zig").inlineAssert;
|
||||||
|
|
||||||
const log = std.log.scoped(.pty);
|
const log = std.log.scoped(.pty);
|
||||||
|
|
||||||
@@ -78,36 +79,39 @@ const NullPty = struct {
|
|||||||
pub fn childPreExec(self: Pty) ChildPreExecError!void {
|
pub fn childPreExec(self: Pty) ChildPreExecError!void {
|
||||||
_ = self;
|
_ = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal buffer
|
||||||
|
/// so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => [:0]const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) attached to the PTY. Returns
|
||||||
|
/// `null` if there was an error getting the information or the information
|
||||||
|
/// is not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(_: *Pty, comptime info: ProcessInfo) ?ProcessInfo.Type(info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Linux PTY creation and management. This is just a thin layer on top
|
/// Posix PTY creation and management. This is just a thin layer on top
|
||||||
/// of Linux syscalls. The caller is responsible for detail-oriented handling
|
/// of Posix syscalls. The caller is responsible for detail-oriented handling
|
||||||
/// of the returned file handles.
|
/// of the returned file handles.
|
||||||
const PosixPty = struct {
|
const PosixPty = struct {
|
||||||
pub const Error = OpenError || GetModeError || GetSizeError || SetSizeError || ChildPreExecError;
|
pub const Error = OpenError || GetModeError || GetSizeError || SetSizeError || ChildPreExecError;
|
||||||
|
|
||||||
pub const Fd = posix.fd_t;
|
pub const Fd = posix.fd_t;
|
||||||
|
|
||||||
// https://github.com/ziglang/zig/issues/13277
|
const c = @import("pty-c");
|
||||||
// Once above is fixed, use `c.TIOCSCTTY`
|
|
||||||
const TIOCSCTTY = if (builtin.os.tag == .macos) 536900705 else c.TIOCSCTTY;
|
|
||||||
const TIOCSWINSZ = if (builtin.os.tag == .macos) 2148037735 else c.TIOCSWINSZ;
|
|
||||||
const TIOCGWINSZ = if (builtin.os.tag == .macos) 1074295912 else c.TIOCGWINSZ;
|
|
||||||
extern "c" fn setsid() std.c.pid_t;
|
|
||||||
const c = switch (builtin.os.tag) {
|
|
||||||
.macos => @cImport({
|
|
||||||
@cInclude("sys/ioctl.h"); // ioctl and constants
|
|
||||||
@cInclude("util.h"); // openpty()
|
|
||||||
}),
|
|
||||||
.freebsd => @cImport({
|
|
||||||
@cInclude("termios.h"); // ioctl and constants
|
|
||||||
@cInclude("libutil.h"); // openpty()
|
|
||||||
}),
|
|
||||||
else => @cImport({
|
|
||||||
@cInclude("sys/ioctl.h"); // ioctl and constants
|
|
||||||
@cInclude("pty.h");
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The file descriptors for the master and slave side of the pty.
|
/// The file descriptors for the master and slave side of the pty.
|
||||||
/// The slave side is never closed automatically by this struct
|
/// The slave side is never closed automatically by this struct
|
||||||
@@ -116,6 +120,14 @@ const PosixPty = struct {
|
|||||||
master: Fd,
|
master: Fd,
|
||||||
slave: Fd,
|
slave: Fd,
|
||||||
|
|
||||||
|
/// Buffer for storage of slave tty name so that we don't have to recompute
|
||||||
|
/// it every time we need it.
|
||||||
|
tty_name_buf: [std.fs.max_path_bytes:0]u8 = undefined,
|
||||||
|
/// The name of slave tty. If `null` it has not yet been computed or
|
||||||
|
/// may not be available. Should not be accessed directly, but through
|
||||||
|
/// `self.getProcessInfo(.tty_name)`
|
||||||
|
tty_name: ?[:0]const u8 = null,
|
||||||
|
|
||||||
pub const OpenError = error{OpenptyFailed};
|
pub const OpenError = error{OpenptyFailed};
|
||||||
|
|
||||||
/// Open a new PTY with the given initial size.
|
/// Open a new PTY with the given initial size.
|
||||||
@@ -141,15 +153,15 @@ const PosixPty = struct {
|
|||||||
// Set CLOEXEC on the master fd, only the slave fd should be inherited
|
// Set CLOEXEC on the master fd, only the slave fd should be inherited
|
||||||
// by the child process (shell/command).
|
// by the child process (shell/command).
|
||||||
cloexec: {
|
cloexec: {
|
||||||
const flags = std.posix.fcntl(master_fd, std.posix.F.GETFD, 0) catch |err| {
|
const flags = posix.fcntl(master_fd, posix.F.GETFD, 0) catch |err| {
|
||||||
log.warn("error getting flags for master fd err={}", .{err});
|
log.warn("error getting flags for master fd err={}", .{err});
|
||||||
break :cloexec;
|
break :cloexec;
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = std.posix.fcntl(
|
_ = posix.fcntl(
|
||||||
master_fd,
|
master_fd,
|
||||||
std.posix.F.SETFD,
|
posix.F.SETFD,
|
||||||
flags | std.posix.FD_CLOEXEC,
|
flags | posix.FD_CLOEXEC,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
log.warn("error setting CLOEXEC on master fd err={}", .{err});
|
log.warn("error setting CLOEXEC on master fd err={}", .{err});
|
||||||
break :cloexec;
|
break :cloexec;
|
||||||
@@ -168,6 +180,8 @@ const PosixPty = struct {
|
|||||||
return .{
|
return .{
|
||||||
.master = master_fd,
|
.master = master_fd,
|
||||||
.slave = slave_fd,
|
.slave = slave_fd,
|
||||||
|
.tty_name_buf = undefined,
|
||||||
|
.tty_name = null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +208,7 @@ const PosixPty = struct {
|
|||||||
/// Return the size of the pty.
|
/// Return the size of the pty.
|
||||||
pub fn getSize(self: Pty) GetSizeError!winsize {
|
pub fn getSize(self: Pty) GetSizeError!winsize {
|
||||||
var ws: winsize = undefined;
|
var ws: winsize = undefined;
|
||||||
if (c.ioctl(self.master, TIOCGWINSZ, @intFromPtr(&ws)) < 0)
|
if (c.ioctl(self.master, c.TIOCGWINSZ, @intFromPtr(&ws)) < 0)
|
||||||
return error.IoctlFailed;
|
return error.IoctlFailed;
|
||||||
|
|
||||||
return ws;
|
return ws;
|
||||||
@@ -204,7 +218,7 @@ const PosixPty = struct {
|
|||||||
|
|
||||||
/// Set the size of the pty.
|
/// Set the size of the pty.
|
||||||
pub fn setSize(self: *Pty, size: winsize) SetSizeError!void {
|
pub fn setSize(self: *Pty, size: winsize) SetSizeError!void {
|
||||||
if (c.ioctl(self.master, TIOCSWINSZ, @intFromPtr(&size)) < 0)
|
if (c.ioctl(self.master, c.TIOCSWINSZ, @intFromPtr(&size)) < 0)
|
||||||
return error.IoctlFailed;
|
return error.IoctlFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,10 +248,10 @@ const PosixPty = struct {
|
|||||||
posix.sigaction(posix.SIG.QUIT, &sa, null);
|
posix.sigaction(posix.SIG.QUIT, &sa, null);
|
||||||
|
|
||||||
// Create a new process group
|
// Create a new process group
|
||||||
if (setsid() < 0) return error.ProcessGroupFailed;
|
if (c.setsid() < 0) return error.ProcessGroupFailed;
|
||||||
|
|
||||||
// Set controlling terminal
|
// Set controlling terminal
|
||||||
switch (posix.errno(c.ioctl(self.slave, TIOCSCTTY, @as(c_ulong, 0)))) {
|
switch (posix.errno(c.ioctl(self.slave, c.TIOCSCTTY, @as(c_ulong, 0)))) {
|
||||||
.SUCCESS => {},
|
.SUCCESS => {},
|
||||||
else => |err| {
|
else => |err| {
|
||||||
log.err("error setting controlling terminal errno={}", .{err});
|
log.err("error setting controlling terminal errno={}", .{err});
|
||||||
@@ -249,6 +263,77 @@ const PosixPty = struct {
|
|||||||
posix.close(self.slave);
|
posix.close(self.slave);
|
||||||
posix.close(self.master);
|
posix.close(self.master);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that currently controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal buffer
|
||||||
|
/// so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => [:0]const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) attached to the PTY. Returns
|
||||||
|
/// `null` if there was an error getting the information or the information
|
||||||
|
/// is not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(self: *PosixPty, comptime info: ProcessInfo) ?ProcessInfo.Type(info) {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => {
|
||||||
|
switch (builtin.os.tag) {
|
||||||
|
.linux => {
|
||||||
|
const linux = std.os.linux;
|
||||||
|
var pgrp: i32 = undefined;
|
||||||
|
const rc = linux.tcgetpgrp(self.master, &pgrp);
|
||||||
|
switch (linux.E.init(rc)) {
|
||||||
|
.SUCCESS => return @intCast(pgrp),
|
||||||
|
else => return null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
const rc = c.tcgetpgrp(self.master);
|
||||||
|
if (rc < 0) return null;
|
||||||
|
return @intCast(rc);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.tty_name => {
|
||||||
|
if (self.tty_name) |tty_name| return tty_name;
|
||||||
|
|
||||||
|
switch (builtin.os.tag) {
|
||||||
|
.macos => {
|
||||||
|
// The macOS TIOCPTYGNAME ioctl does not allow us to
|
||||||
|
// specify the length of the buffer passed to it, but
|
||||||
|
// expects it to be at least 128 bytes long.
|
||||||
|
assert(self.tty_name_buf.len >= 128);
|
||||||
|
switch (posix.errno(c.ioctl(self.master, c.TIOCPTYGNAME, @intFromPtr(&self.tty_name_buf)))) {
|
||||||
|
.SUCCESS => {
|
||||||
|
const tty_name: [:0]const u8 = std.mem.sliceTo(&self.tty_name_buf, 0);
|
||||||
|
self.tty_name = tty_name;
|
||||||
|
return tty_name;
|
||||||
|
},
|
||||||
|
else => |err| {
|
||||||
|
log.err("error getting name of slave PTY errno={t}", .{err});
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.linux => {
|
||||||
|
if (c.ptsname_r(self.master, &self.tty_name_buf, self.tty_name_buf.len) != 0) return null;
|
||||||
|
const tty_name: [:0]const u8 = std.mem.sliceTo(&self.tty_name_buf, 0);
|
||||||
|
self.tty_name = tty_name;
|
||||||
|
return tty_name;
|
||||||
|
},
|
||||||
|
else => return null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Windows PTY creation and management.
|
/// Windows PTY creation and management.
|
||||||
@@ -398,6 +483,28 @@ const WindowsPty = struct {
|
|||||||
if (result != windows.S_OK) return error.ResizeFailed;
|
if (result != windows.S_OK) return error.ResizeFailed;
|
||||||
self.size = size;
|
self.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that currently controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal
|
||||||
|
/// buffer so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => []const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) attached to the PTY. Returns
|
||||||
|
/// `null` if there was an error getting the information or the information
|
||||||
|
/// is not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(_: *WindowsPty, comptime info: ProcessInfo) ?ProcessInfo.Type(info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test {
|
test {
|
||||||
@@ -419,4 +526,11 @@ test {
|
|||||||
ws.ws_row *= 2;
|
ws.ws_row *= 2;
|
||||||
try pty.setSize(ws);
|
try pty.setSize(ws);
|
||||||
try testing.expectEqual(ws, try pty.getSize());
|
try testing.expectEqual(ws, try pty.getSize());
|
||||||
|
|
||||||
|
switch (builtin.os.tag) {
|
||||||
|
.freebsd => try testing.expect(std.mem.startsWith(u8, pty.getProcessInfo(.tty_name).?, "/dev/")),
|
||||||
|
.linux => try testing.expect(std.mem.startsWith(u8, pty.getProcessInfo(.tty_name).?, "/dev/pts/")),
|
||||||
|
.macos => try testing.expect(std.mem.startsWith(u8, pty.getProcessInfo(.tty_name).?, "/dev/")),
|
||||||
|
else => try testing.expect(pty.getProcessInfo(.tty_name) == null),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/pty/freebsd.c
Normal file
4
src/pty/freebsd.c
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include <termios.h> // ioctl and constants
|
||||||
|
#include <libutil.h> // openpty
|
||||||
|
#include <stdlib.h> // ptsname_r
|
||||||
|
#include <unistd.h> // tcgetpgrp
|
||||||
5
src/pty/linux.c
Normal file
5
src/pty/linux.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#define _GNU_SOURCE // ptsname_r
|
||||||
|
#include <pty.h> // openpty
|
||||||
|
#include <stdlib.h> // ptsname_r
|
||||||
|
#include <sys/ioctl.h> // ioctl and constants
|
||||||
|
#include <unistd.h> // tcgetpgrp, setsid
|
||||||
17
src/pty/macos.c
Normal file
17
src/pty/macos.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include <sys/ioctl.h> // ioctl and constants
|
||||||
|
#include <sys/ttycom.h> // ioctl and constants for TIOCPTYGNAME
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h> // tcgetpgrp
|
||||||
|
#include <util.h> // openpty
|
||||||
|
|
||||||
|
#ifndef TIOCSCTTY
|
||||||
|
#define TIOCSCTTY 536900705
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TIOCSWINSZ
|
||||||
|
#define TIOCSWINSZ 2148037735
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TIOCGWINSZ
|
||||||
|
#define TIOCGWINSZ 1074295912
|
||||||
|
#endif
|
||||||
@@ -1226,6 +1226,32 @@ const Subprocess = struct {
|
|||||||
fn killCommandFlatpak(command: *FlatpakHostCommand) !void {
|
fn killCommandFlatpak(command: *FlatpakHostCommand) !void {
|
||||||
try command.signal(c.SIGHUP, true);
|
try command.signal(c.SIGHUP, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that currently controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal
|
||||||
|
/// buffer so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: Subprocess.ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => [:0]const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) running within the subprocess.
|
||||||
|
/// Returns `null` if there was an error getting the information or the
|
||||||
|
/// information is not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(self: *Subprocess, comptime info: Subprocess.ProcessInfo) ?Subprocess.ProcessInfo.Type(info) {
|
||||||
|
const pty = &(self.pty orelse return null);
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => pty.getProcessInfo(.foreground_pid),
|
||||||
|
.tty_name => pty.getProcessInfo(.tty_name),
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The read thread sits in a loop doing the following pseudo code:
|
/// The read thread sits in a loop doing the following pseudo code:
|
||||||
@@ -1580,6 +1606,31 @@ fn execCommand(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that currently controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal
|
||||||
|
/// buffer so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => [:0]const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) running within the backend. Returns
|
||||||
|
/// `null` if there was an error getting the information or the information is
|
||||||
|
/// not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(self: *Exec, comptime info: ProcessInfo) ?ProcessInfo.Type(info) {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => self.subprocess.getProcessInfo(.foreground_pid),
|
||||||
|
.tty_name => self.subprocess.getProcessInfo(.tty_name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
test "execCommand darwin: shell command" {
|
test "execCommand darwin: shell command" {
|
||||||
if (comptime !builtin.os.tag.isDarwin()) return error.SkipZigTest;
|
if (comptime !builtin.os.tag.isDarwin()) return error.SkipZigTest;
|
||||||
|
|
||||||
|
|||||||
@@ -764,3 +764,28 @@ pub const ThreadData = struct {
|
|||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that currently controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal
|
||||||
|
/// buffer so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => [:0]const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) attached to the backend. Returns
|
||||||
|
/// `null` if there was an error getting the information or the information is
|
||||||
|
/// not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(self: *Termio, comptime info: ProcessInfo) ?ProcessInfo.Type(info) {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => self.backend.getProcessInfo(.foreground_pid),
|
||||||
|
.tty_name => self.backend.getProcessInfo(.tty_name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -100,6 +100,33 @@ pub const Backend = union(Kind) {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ProcessInfo = enum {
|
||||||
|
/// The PID of the process that currently controls the PTY.
|
||||||
|
foreground_pid,
|
||||||
|
/// Gets the name of the slave PTY. Returned name points to an internal
|
||||||
|
/// buffer so it should not be modified or freed.
|
||||||
|
tty_name,
|
||||||
|
|
||||||
|
pub fn Type(comptime info: ProcessInfo) type {
|
||||||
|
return switch (info) {
|
||||||
|
.foreground_pid => u64,
|
||||||
|
.tty_name => [:0]const u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get information about the process(es) attached to the backend. Returns
|
||||||
|
/// `null` if there was an error getting the information or the information
|
||||||
|
/// is not available on a particular platform.
|
||||||
|
pub fn getProcessInfo(self: *Backend, comptime info: ProcessInfo) ?ProcessInfo.Type(info) {
|
||||||
|
return switch (self.*) {
|
||||||
|
.exec => |*exec| switch (info) {
|
||||||
|
.foreground_pid => exec.getProcessInfo(.foreground_pid),
|
||||||
|
.tty_name => exec.getProcessInfo(.tty_name),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Termio thread data. See termio.ThreadData for docs.
|
/// Termio thread data. See termio.ThreadData for docs.
|
||||||
|
|||||||
Reference in New Issue
Block a user