Nidhoegger Nidhoegger - 3 months ago 12
Linux Question

C/Linux: How to get users login name without `getlogin`

I need to retrieve the users username in a C program. I know about

getlogin
and
getlogin_r
. But my program has a redirected stdin (because of some
forks
).

The Problem I face is stated in the manpage:


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).


Is there any other way I could retrieve the username?

Answer

Use getresuid(2) or some of the more specific id retrieval functions to get the id you want (real, effective, or saved-set) (you probably want RUID, if you want to emulate getlogin, in which case you can simply call getuid and forget about the effective and saved-set uid), and then use getpwuid(3) or its reentrant counterpart to translate that to a user id string.

getenv("USER") might give you the same result, but you can't rely on it if you want real security.

Technically, all these may be different from the result obtained by getlogin when stdin is your controlling terminal. If you really need the same answer as what getlogin would get you, you can temporarily make your fd 0 point to your controlling terminal again, then call getlogin, and then restore your fd 0:

int saved_fd0;
if(0>(saved_fd0 = dup(0))
       /*handle error*/;
close(0);

/*open always gets the lowest possible fd number == now 0*/
/*"/dev/tty" is always your current processes's controlling terminal*/
if(0>open("/dev/tty", O_RDONLY))
    /*handle error*/;
/*
getlogin()
..
*/
/*restore saved_fd0*/
if(0>dup2(saved_fd0, 0))
       /*handle error*/;
Comments