Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export interface ITerminal {
*/
pid: number;

/**
* Gets the foreground process group ID, if available.
*/
readonly foregroundPid?: number;

/**
* Writes data to the socket.
* @param data The data to write.
Expand Down
1 change: 1 addition & 0 deletions src/native.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface IUnixNative {
fork(file: string, args: string[], parsedEnv: string[], cwd: string, cols: number, rows: number, uid: number, gid: number, useUtf8: boolean, helperPath: string, onExitCallback: (code: number, signal: number) => void): IUnixProcess;
open(cols: number, rows: number): IUnixOpenProcess;
process(fd: number, pty?: string): string;
foregroundPid(fd: number): number | undefined;
resize(fd: number, cols: number, rows: number, pixelWidth: number, pixelHeight: number): void;
}

Expand Down
26 changes: 26 additions & 0 deletions src/unix/pty.cc
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ Napi::Value PtyFork(const Napi::CallbackInfo& info);
Napi::Value PtyOpen(const Napi::CallbackInfo& info);
Napi::Value PtyResize(const Napi::CallbackInfo& info);
Napi::Value PtyGetProc(const Napi::CallbackInfo& info);
Napi::Value PtyGetForegroundPid(const Napi::CallbackInfo& info);

/**
* Functions
Expand Down Expand Up @@ -619,6 +620,30 @@ Napi::Value PtyGetProc(const Napi::CallbackInfo& info) {
return name_;
}

/**
* Foreground Process Group PID
*
* Returns the pid of the foreground process group attached to the pty
* referenced by `fd`, or undefined if the lookup fails. Cross-platform
* (Linux + macOS) — wraps tcgetpgrp(3), which is what `process` already
* calls internally to resolve the foreground process name.
*/
Napi::Value PtyGetForegroundPid(const Napi::CallbackInfo& info) {
Napi::Env env(info.Env());
Napi::HandleScope scope(env);

if (info.Length() != 1 || !info[0].IsNumber()) {
throw Napi::Error::New(env, "Usage: pty.foregroundPid(fd)");
}

int fd = info[0].As<Napi::Number>().Int32Value();
pid_t pgrp = tcgetpgrp(fd);
if (pgrp == -1) {
return env.Undefined();
}
return Napi::Number::New(env, static_cast<double>(pgrp));
}

/**
* Nonblocking FD
*/
Expand Down Expand Up @@ -869,6 +894,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
exports.Set("open", Napi::Function::New(env, PtyOpen));
exports.Set("resize", Napi::Function::New(env, PtyResize));
exports.Set("process", Napi::Function::New(env, PtyGetProc));
exports.Set("foregroundPid", Napi::Function::New(env, PtyGetForegroundPid));
return exports;
}

Expand Down
12 changes: 12 additions & 0 deletions src/unixTerminal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,18 @@ if (process.platform !== 'win32') {
}, 1000);
});
}
it('should return the foreground process group pid', (done) => {
const term = new UnixTerminal('node', ['-e', 'console.log("ready"); setTimeout(() => null, 200);']);
term.onData((data) => {
if (!data.includes('ready')) {
return;
}
assert.strictEqual(typeof term.foregroundPid, 'number');
assert.strictEqual(term.foregroundPid, term.pid);
term.on('exit', () => done());
term.kill();
});
});
if (process.platform === 'darwin') {
it('should return the name of the process', (done) => {
const term = new UnixTerminal('/bin/echo');
Expand Down
5 changes: 5 additions & 0 deletions src/unixTerminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ export class UnixTerminal extends Terminal {
/* Accessors */
get fd(): number { return this._fd; }
get ptsName(): string { return this._pty; }
/**
* Pid of the foreground process group attached to the pty, or undefined
* if the lookup fails (e.g. the pty has exited). Wraps tcgetpgrp(3).
*/
get foregroundPid(): number | undefined { return pty.foregroundPid(this._fd); }

/**
* openpty
Expand Down
5 changes: 5 additions & 0 deletions typings/node-pty.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ declare module 'node-pty' {
*/
readonly pid: number;

/**
* The foreground process group ID, if available.
*/
readonly foregroundPid?: number;

/**
* The column size in characters.
*/
Expand Down