openpty(3)

πŸ’– openpty(3) β€” the terminal utility functions, bestie edition πŸ’–

okay so this is openpty(3) from the Library Functions Manual, and it's genuinely one of those pages that looks scary and is actually just three little functions that make pseudoterminals happen. pty girlies rise 🫢


🌸 NAME 🌸

openpty, login_tty, forkpty β€” the terminal utility functions. three besties, one header, infinite pty slay πŸ’…


πŸ“š LIBRARY πŸ“š

System utilities library (libutil, link it with -lutil). don't forget the flag or you'll be crying at the linker, no cap 😭


✨ SYNOPSIS ✨

#include <pty.h>

int openpty(int *amaster, int *aslave, char *name,
              const struct termios *termp,
              const struct winsize *winp);
pid_t forkpty(int *amaster, char *name,
              const struct termios *termp,
              const struct winsize *winp);

#include <utmp.h>

int login_tty(int fd);

two different headers, keep up πŸ’€ openpty and forkpty live in <pty.h>, login_tty needs <utmp.h>. iconic of them to be split like that.


πŸŽ€ DESCRIPTION πŸŽ€

openpty() β€” the pty matchmaker πŸ’ž

so openpty() goes and finds an available pseudoterminal for u (she's doing the work so u don't have to) and hands u back the file descriptors for both sides: the master lands in amaster and the slave lands in aslave. two fds, one glow-up.

  • if name is not NULL, the filename of the slave gets returned in name.
  • if termp is not NULL, the terminal parameters of the slave get set to whatever's in termp. custom vibes only.
  • if winp is not NULL, the window size of the slave gets set from winp. size matters and she will respect it ✨

login_tty() β€” the main character setup 🎬

login_tty() gets everything prepped for a login on the terminal referred to by the file descriptor fd. and fd can be either a real terminal device or the slave of a pseudoterminal (like the one openpty() just gave u, iykyk).

she does a whole little routine, in order:

  1. creates a new session
  2. makes fd the controlling terminal for the calling process
  3. sets fd to be the standard input, output, and error streams of the current process
  4. closes fd

that's a full transformation arc, honestly πŸ’…

forkpty() β€” the combo meal πŸ“

forkpty() is literally openpty(), fork(2), and login_tty() combined together to spin up a new process operating inside a pseudoterminal. one call, three functions, zero effort from u. ate.

  • a file descriptor referring to the master side of the pseudoterminal gets returned in amaster
  • if name is not NULL, the buffer it points to is used to return the filename of the slave
  • the termp and winp arguments, if not NULL, determine the terminal attributes and window size of the slave side of the pseudoterminal

πŸ”₯ RETURN VALUE πŸ”₯

if a call to openpty(), login_tty(), or forkpty() isn't successful, -1 comes back and errno is set to tell u what went wrong. classic.

otherwise:

  • openpty() returns 0
  • login_tty() returns 0
  • the child process of forkpty() returns 0
  • the parent process of forkpty() returns the process ID of the child process

so yes, forkpty() gives different answers depending on who's asking. very main character of her πŸ‘‘


😭 ERRORS 😭

openpty() fails if:

  • ENOENT β€” There are no available terminals. (she looked. there are none. tragic.)

login_tty() fails if ioctl(2) fails to set fd to the controlling terminal of the calling process.

forkpty() fails if either openpty() or fork(2) fails. two ways to break, one function πŸ’€


🌈 ATTRIBUTES 🌈

the whole rundown on the terms in this section lives in attributes(7), go read it if u want the deep lore. here's the tea for these three:

  • forkpty(), openpty() β€” Thread safety β€” MT-Safe locale
  • login_tty() β€” Thread safety β€” MT-Unsafe race:ttyname
not me pointing out that login_tty() is the one with a race condition. she's still great, she's just built different πŸ™ˆ

πŸ¦‹ STANDARDS πŸ¦‹

BSD. that's it. that's the whole section. periodt.


πŸ‘‘ HISTORY πŸ‘‘

  • The const modifiers were added to the structure pointer arguments of openpty() and forkpty() in glibc 2.8.
  • Before glibc 2.0.92, openpty() returns file descriptors for a BSD pseudoterminal pair.
  • Since glibc 2.0.92, it first attempts to open a UNIX 98 pseudoterminal pair, and falls back to opening a BSD pseudoterminal pair if that fails.

she tries the new thing first and gracefully settles for the old thing. adaptability queen 🌸


πŸ’€ BUGS πŸ’€

Nobody knows how much space should be reserved for name. So, calling openpty() or forkpty() with a non-NULL name may not be secure.

fr fr, this is a real one β€” if u pass a name, u are guessing at the buffer size and guessing is not a security strategy bestie 😭


πŸ’œ SEE ALSO πŸ’œ


and that's the whole page!! this one came straight out of Linux man-pages 6.20, dated 2025-05-17 β€” so if u ever need to cite ur sources, that's the receipt 🧚 go forth and pty responsibly, bestie πŸ’–βœ¨

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: BSD-3-Clause
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms