getlogin(3)

๐Ÿ’– getlogin(3) ๐Ÿ’–

okay bestie, so this one lives in the Library Functions Manual and it's all about who even are you โ€” as far as the system is concerned, anyway. It's giving "let me find your username" energy, and there are three little divas here: getlogin(), getlogin_r(), and the messy unreliable one, cuserid(). ๐ŸŽ€


โœจ NAME โœจ

getlogin, getlogin_r, cuserid โ€” get username ๐Ÿ‘‘


๐Ÿ“š LIBRARY ๐Ÿ“š

Standard C library (libc, -lc) ๐Ÿซถ


๐ŸŒธ SYNOPSIS ๐ŸŒธ

#include <unistd.h>

char *getlogin(void);
int getlogin_r(size_t bufsize;
               char buf[bufsize], size_t bufsize);

#include <stdio.h>

char *cuserid(char *string);

Feature Test Macro Requirements for glibc (go peek at feature_test_macros(7) if you need the lore):

getlogin_r():
    _POSIX_C_SOURCE >= 199506L

cuserid():
    Since glibc 2.24:
        (_XOPEN_SOURCE && ! (_POSIX_C_SOURCE >= 200112L)
            || _GNU_SOURCE
    Up to and including glibc 2.23:
        _XOPEN_SOURCE

๐ŸŒˆ DESCRIPTION ๐ŸŒˆ

getlogin() hands you back a pointer to a string with the name of the user who's logged in on the process's controlling terminal โ€” or a null pointer if it just can't figure that out. ๐Ÿ˜ญ Heads up though: that string is statically allocated, so it might get absolutely bodied and overwritten on later calls to this function or to cuserid().

getlogin_r() gives you that exact same username, except it drops it into the array buf of size bufsize. Reentrant queen behavior ๐Ÿ’…

cuserid() returns a pointer to a string holding a username associated with the effective user ID of the process. If string isn't a null pointer, it needs to be an array that can hold at least L_cuserid characters, and the string gets returned in that array. Otherwise you get a pointer to a string in a static area. And guess what โ€” that string is statically allocated too and might be overwritten by later calls to this function or to getlogin(). ๐Ÿ™ˆ

The macro L_cuserid is an integer constant that tells you how long an array you might need to store a username. L_cuserid is declared in <stdio.h>.

So what are these even for? They let your program positively identify the user who is running it (cuserid()) or the user who logged in this session (getlogin()). (Those two can be different when set-user-ID programs are involved ๐Ÿ‘€)

Real talk though: for most purposes it's way more useful to just use the environment variable LOGNAME to find out who the user is. It's more flexible precisely because the user can set LOGNAME to literally anything. So, y'know. Choose wisely.

๐Ÿฆ‹ RETURN VALUE ๐Ÿฆ‹

  • getlogin() โ€” returns a pointer to the username when successful, and NULL on failure, with errno set to indicate the error.
  • getlogin_r() โ€” returns 0 when successful, and nonzero on failure.

๐Ÿ’€ ERRORS ๐Ÿ’€

POSIX specifies these bad boys:

  • EMFILE โ€” The per-process limit on the number of open file descriptors has been reached.
  • ENFILE โ€” The system-wide limit on the total number of open files has been reached.
  • ENXIO โ€” The calling process has no controlling terminal. (no tty, no username, no service ๐Ÿ˜”)
  • ERANGE (getlogin_r) โ€” The length of the username, including the terminating null byte ('\0'), is larger than bufsize. Too long, didn't fit.

Linux/glibc also has:

  • ENOENT โ€” There was no corresponding entry in the utmp-file.
  • ENOMEM โ€” Insufficient memory to allocate passwd structure.
  • ENOTTY โ€” Standard input didn't refer to a terminal. (See BUGS.)

๐ŸŽ€ FILES ๐ŸŽ€

  • /etc/passwd โ€” password database file
  • /var/run/utmp โ€” (traditionally /etc/utmp; some libc versions used /var/adm/utmp)

โญ ATTRIBUTES โญ

For an explanation of the terms used in this section, see attributes(7).

  • getlogin() โ€” Thread safety: MT-Unsafe race:getlogin race:utent sig:ALRM timer locale
  • getlogin_r() โ€” Thread safety: MT-Unsafe race:utent sig:ALRM timer locale
  • cuserid() โ€” Thread safety: MT-Unsafe race:cuserid/!string locale

About that utent up in race:utent โ€” it means that if any of the functions setutent(3), getutent(3), or endutent(3) are used in parallel in different threads of a program, then data races could occur. ๐Ÿ˜ตโ€๐Ÿ’ซ getlogin() and getlogin_r() call those functions, so we write race:utent there to remind you. Consider this your reminder, bestie.


๐ŸŒŸ VERSIONS ๐ŸŒŸ

OpenBSD has getlogin() and setlogin(), plus a username associated with a session, even if that session has no controlling terminal. Look at them go ๐Ÿ’…


๐Ÿ‘‘ STANDARDS ๐Ÿ‘‘

  • getlogin()
  • getlogin_r() โ€” POSIX.1-2008.
  • cuserid() โ€” None.

๐Ÿ’œ STANDARDS (the sequel) ๐Ÿ’œ

  • getlogin()
  • getlogin_r() โ€” POSIX.1-2001. OpenBSD.
  • cuserid() โ€” System V, POSIX.1-1988. Removed in POSIX.1-1990. SUSv2. Removed in POSIX.1-2001.

System V has a cuserid() function which uses the real user ID rather than the effective user ID. Not the same thing, bestie.


๐Ÿ˜ญ BUGS ๐Ÿ˜ญ

Unfortunately, it is often rather easy to fool getlogin(). Sometimes it doesn't work at all, because some program messed up the utmp file. Often, it gives only the first 8 characters of the login name. And the user currently logged in on the controlling terminal of our program need not be the user who started it. ๐Ÿซ 

Avoid getlogin() for security-related purposes. No cap. This is not a drill.

Also note that glibc does not follow the POSIX specification and uses stdin instead of /dev/tty. A bug. (Other recent systems, like SunOS 5.8 and HP-UX 11.11 and FreeBSD 4.8, all return the login name also when stdin is redirected. So like, everyone else is doing it and glibc is just built different ๐Ÿ’€)

Nobody knows precisely what cuserid() does; avoid it in portable programs. Or avoid it altogether: use getpwuid(geteuid()) instead, if that is what you meant. Do not use cuserid(). Periodt.


๐Ÿงš SEE ALSO ๐Ÿงš

logname(1), geteuid(2), getuid(2), utmp(5)


okay that's the whole page, you're so welcome ๐Ÿฅฐ this came from Linux man-pages 6.20, dated 2026-02-08, and yes it's the getlogin(3) page, love her, fear her, probably don't use her for security. byeee ๐Ÿ’–โœจ๐Ÿฆ‹

๐Ÿ“ฆ 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: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms