Recommended Free Tools
forkpty() is a BSD-style terminal utility function that allocates a pseudoterminal (PTY), forks the process, and configures the child to use the PTY slave as its controlling terminal and standard streams. The parent receives the PTY master descriptor and can use it to drive the child, much like a terminal emulator. On Linux, include <pty.h> and usually link with -lutil.
What forkpty() does
The Linux interface combines three operations:
openpty()allocates a PTY master/slave pair.fork(2)creates a parent and child process.login_tty()makes the child-side slave the controlling terminal and connects it to the child’s standard input, output, and error streams.
The Linux man-pages project describes it this way: “The forkpty() function combines openpty(), fork(2), and login_tty() to create a new process operating in a pseudoterminal.” The function does not choose a program for the child. After the call returns in the child, your code normally uses an exec function to start a shell or another terminal-oriented program.
Prototype, arguments, and return values
#include <pty.h>
int forkpty(int *amaster,
char *name,
const struct termios *termp,
const struct winsize *winp);
Arguments
amasterreceives the file descriptor for the PTY master in the parent.name, when non-NULL, receives the pathname of the PTY slave.termp, when non-NULL, supplies the initial terminal attributes for the slave.winp, when non-NULL, supplies the initial terminal window size.
The terminal and window arguments are optional: pass NULL when you want the system defaults. The documented size requirement for the name buffer is unspecified, so supplying a non-NULL buffer can be insecure. Unless you specifically need the slave pathname and have a platform-appropriate way to size the buffer, pass NULL.
What each process receives
| Process | Return from forkpty() |
PTY state |
|---|---|---|
| Parent | Child process ID (positive value) | *amaster is the usable master descriptor; the child is attached to the slave |
| Child | 0 |
The slave is its controlling terminal and is connected to standard input, output, and error |
| Failure | -1 |
No usable parent/child setup; errno identifies the failure |
In the parent, the return value is the child PID, not the master descriptor. Read from and write to the descriptor stored through amaster. In the child, close or replace inherited resources as appropriate and call an exec function.
#1 Best Overall
Minimal Linux example
#include <pty.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
int master;
pid_t child = forkpty(&master, NULL, NULL, NULL);
if (child == -1) {
perror("forkpty");
return EXIT_FAILURE;
}
if (child == 0) {
execlp("sh", "sh", (char *)NULL);
perror("execlp");
_exit(127);
}
/* The parent can now read the shell's output and write terminal input
through master, using read(2), write(2), poll(2), or select(2). */
close(master);
return EXIT_SUCCESS;
}
Compile on a typical Linux system with:
cc pty_demo.c -o pty_demo -lutil
The parent-side program normally keeps the master open until the child exits, monitors it with poll() or select(), and uses waitpid() to collect the child. A production terminal proxy must also handle end-of-file, child termination, partial writes, terminal signals, and the PTY’s line-discipline behavior.
forkpty() versus openpty() plus manual setup
forkpty() is a convenience function. Calling openpty(), then fork(), then login_tty() yourself exposes each stage and gives you more opportunities to customize the sequence.
Rank #2
| Concern | forkpty() |
Separate calls |
|---|---|---|
| Setup code | One call performs PTY allocation, fork, and child terminal setup. | You manage openpty(), fork(), and login_tty() explicitly. |
| Fork and child sequencing | Uses the library’s combined sequence. | Lets you insert custom parent/child work between stages. |
| Master access | Parent receives the master through amaster. |
You retain the descriptors returned by openpty() and decide when to close or transfer them. |
| Initial terminal state | Pass termp and winp directly. |
Set attributes and window size as separate, visible steps. |
| Slave name | Optional name output, with an unspecified buffer-size requirement. |
You handle the name returned by openpty() under that API’s rules. |
| Error handling | Reports a combined operation failure as -1 with errno. |
You can identify which individual operation failed. |
| Portability | Convenient where the BSD interface is available. | Still depends on the same BSD terminal APIs, but can accommodate platform-specific sequencing. |
No documented performance advantage establishes one approach as faster. Choose forkpty() when its fixed setup matches your design; use the separate calls when you need fine-grained control.
Errors and failure handling
A return value of -1 means that setup failed and errno is set. The combined call can fail when its underlying openpty() or fork() operation fails. For example, openpty() can report ENOENT when no PTYs are available.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →- Always test the return value before treating
amasteras valid. - Use
perror()orstrerror(errno)immediately if you need to report the cause. - Do not assume that a failed call created a child or left a usable descriptor.
- In the child, report an
execfailure and terminate with_exit()rather than returning through parent-side code.
Portability and standards status
forkpty(), openpty(), and login_tty() are BSD interfaces; they are not standardized by POSIX. Linux systems commonly expose them through <pty.h> and libutil, but availability and feature-test requirements can differ among libc and BSD implementations. Code intended for multiple Unix families should isolate this API behind a portability layer and verify the target system’s headers and linker names.
Historical documentation records changes to the glibc prototype and describes UNIX 98 PTY allocation with a BSD fallback. Exact wording can vary by installed man-pages release: the indexed package listing identifies Linux man-pages 6.19 (25 August 2026), while the rendered page cited here is man-pages 6.18 with a 17 May 2025 page date.
Rank #4
When to use it
- Building a terminal emulator, expect-style controller, debugger front end, or remote interactive session.
- Launching a program that changes behavior when it detects a real terminal rather than a pipe.
- Applying initial termios settings and a window size at the moment the child terminal is created.
For simple non-interactive pipelines, ordinary pipes are usually a better fit. A PTY introduces terminal line discipline, signal generation, echo rules, and window-size semantics that a pipe does not provide.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




