Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk4 min

forkpty(3) in the util-linux Library: PTY Creation, Compilation, and Usage

forkpty() allocates a PTY, forks, and makes the child’s slave a controlling terminal while the parent receives the master descriptor. Here is the API, compile command, error behavior, safety caveat, and portability guidance.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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

  • amaster receives 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Always test the return value before treating amaster as valid.
  • Use perror() or strerror(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 exec failure 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.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. Shenzhen desk3 min
    HONOR Expands Beyond Smartphones With Humanoid Robot RevealHONOR said it unveiled its first humanoid robot at MWC 2026 and named shopping assistance, workplace inspections, and supportive companionship as intended uses. Later Robotics D1 claims and a reported…
  2. Cupertino desk5 min
    Apple Unveils AirPods Max 2: The Upgrade That Should Have Happened Years AgoAirPods Max 2 adds H2-powered audio features and Apple claims up to 1.5× more effective ANC, but its design, Smart Case, and 20-hour battery rating are unchanged. Wired lossless audio…
  3. Cupertino desk4 min
    Apple’s OLED Touch MacBooks Are Coming—but the Dynamic Island Is the Real GambleApple has not announced an OLED touchscreen MacBook, but reports point to high-end models arriving in late 2026 or early 2027. The reported Mac Dynamic Island could be useful, but…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.