ttyname(3)
β¨ ttyname(3) β¨
okay bestie so this one lives in the Library Functions Manual (that's the 3 in ttyname(3), iykyk) β it's a libc situation, specifically Standard C library (that's libc, aka -lc if you're out here linking by hand like a menace). no cap. π
πΈ NAME πΈ
ttyname, ttyname_r β return name of a terminal
like, the whole vibe is "which terminal am I, actually?" π
π¦ LIBRARY π¦
Standard C library β libc, -lc
β¨ SYNOPSIS β¨
#include <unistd.h>
char *ttyname(int fd);
int ttyname_r(size_t size;
int fd, char buf[size], size_t size);
(yeah that second one has a lil semicolon situation going on in the signature. we copy it exactly. no notes, that's just how it is, periodt π)
π DESCRIPTION π
okay so! ttyname() hands you back a pointer to the null-terminated pathname of the terminal device that's open on the file descriptor fd. π
or, if things go sideways, it returns NULL β for example when fd isn't even connected to a terminal. rude of it but okay. π
β οΈ big one bestie: the return value may point to static data β and that static data can get overwritten by the next call. so don't go holding onto that pointer like it's a forever thing. it is not. it's giving borrowed, not owned.
meanwhile ttyname_r() is the respectful one π«Ά β it takes that pathname and stores it in the buffer buf, which is size bytes big.
π RETURN VALUE π
ttyname()β slays on success and returns a pointer to a pathname. on error it returnsNULLand setserrnoto indicate the error. πttyname_r()β returns0on success, and an error number when it's an error.
π ERRORS π
EBADFβ Bad file descriptor. (bestie. that fd is not fd-ing. π« )ENODEVβfdrefers to a slave pseudoterminal device but the corresponding pathname could not be found (peep NOTES for the whole saga).ENOTTYβfddoes not refer to a terminal device. nope, not a terminal, go home. π«ERANGE(only fromttyname_r()) βsizewas way too small to allow storing the pathname. the buffer said "no room, ma'am." π
β ATTRIBUTES β
for the whole explanation of what these terms even mean, see attributes(7). the receipts:
ttyname()- Attribute: Thread safety
- Value: MT-Unsafe race:ttyname π₯
ttyname_r()- Attribute: Thread safety
- Value: MT-Safe π
so yeah if you're threading, ttyname_r() is the main character and ttyname() is out here racing. pick wisely.
π§ STANDARDS π§
POSIX.1-2008.
π HISTORY π
POSIX.1-2001, 4.2BSD. she's been around. vintage. iconic. β¨
π NOTES π
okay this part is lowkey important so listen up. π«Ά
a process that keeps a file descriptor referring to a pts(4) device open while switching to another mount namespace that uses a different /dev/ptmx instance may still accidentally find that a device path of the same name exists for that file descriptor.
but bestie. that device path refers to a different device β so it can't be used to access the device that the file descriptor actually refers to. π like, the name matches but it's a whole different person. catfished by a pathname.
and calling ttyname() or ttyname_r() on that file descriptor in the new mount namespace will make these functions return NULL and set errno to ENODEV. so that's why that error exists. mystery solved, we ate. π
π SEE ALSO π
and that's the whole page, bestie!! go read your terminals. πΈ
this lil gem comes from Linux man-pages 6.20, dated 2026-02-08 β yes queen, 2026, she's fresh. π¦π
π¦ 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: GPL-2.0-or-later
- Copyright 1995, James R. Van Zandt <jrv@vanzandt.mv.com>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms