`int getlogin_r(char *buf, size_t len)` broken
Please use the following bug reporting template to help produce actionable and reproducible issues:
- A brief description Attempting to use the function to get the login id of the user running the executable returns garbled strings, with a different return value each time.
- Expected results
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
size_t len = 10;
char buf[len];
size_t ret = getlogin_r(buf, len);
puts(buf);
return 0;
}
should print out my username, with ret set to 0 to indicate success.
- Actual results (with terminal output if applicable)
The value of ret is 2, indicating an error. Depending on the C compiler used, it outputs garbage strings. If compiled with GCC or Clang, it prints out a single "unknown char" box. If compiled with TCC, it prints out a string the size of one's username, composed of aforementioned boxes and random numbers, letters, and symbols.
- Your Windows build number
14393
- Steps / commands required to reproduce the error
gcc test.c -o test && ./test
- Strace of the failing command
Command doesn't fail in this sense.
- Required packages and commands to install
sudo apt-get install build-essential

Can confirm that the above sample doesn't work on WSL. Tried on a personal Ubuntu Linux Server box, it worked. Tried on WSL, and it didn't. I would also like to note that ret is set to 0 on linux, and 2 on WSL.
Compiling the program on a build slave (Ubuntu 15.10) and transferring it to WSL results in the same garbage output. It works just fine on aforementioned Ubuntu instance.

It's in the strace. WSL has no /proc/self/loginuid.
open("/proc/self/loginuid", O_RDONLY) = -1 ENOENT (No such file or directory)
WSL doesn't have /proc/self/loginuid as mentioned above, but also doesn't have /var/run/utmp, to which getlogin_r(3) will fall back in the absence of the former. This is all part-in-parcel of #352 and #573. As a workaround in the absence of those two issues being addressed:
$ sudo touch /var/run/utmp
Then:
C:\ wsl.exe sudo login -f someuser
The test case in the Summer 2016 OP is basically equivalent to logname(1), which will now succeed.
$ logname
ken
I still have this issue. The thing is, it returns \0 for debug "-O0" builds and some garbage value for others.
EDIT: Nope. So it looks like in other systems where getlogin_r() is functioning, it writes the first few bytes with the username string. On WSL where this is not working, nothing is written. So, when the buffer is uninitialized and corrupted, it returns a garbage value. However, this is not an error condition according to the Manual page [getlogin_r(3)], so it returns success. I'm deciding to overwrite the first character of the buffer with '\0' where bufsize > 0, when the username is not available. Unfortunately getlogin_r(3) doesn't return the number of characters written, so this is tricky for me
The thing is, it returns \0 for debug "-O0" builds and some garbage value for others.
The contents of the buffer passed doesn't matter (initialized or otherwise). As was mentioned in the OP, on WSL getlogin_r() returns 2 (ie ENOENT). In practice you'd test !=0. In an abundance of caution, you can also test against ERANGE. Looks like:
int main() {
char buf[256];
if (getlogin_r(buf, sizeof(buf)) != 0) {
strncpy(buf, "<unknown>", sizeof(buf));
// or handle the error however you want
}
printf("user is: %s\n", buf);
return 0;
}
The thing is, it returns \0 for debug "-O0" builds and some garbage value for others.
The contents of the buffer passed doesn't matter (initialized or otherwise). As was mentioned in the OP, on WSL
getlogin_r()returns 2 (ieENOENT). In practice you'd test!=0. In an abundance of caution, you can also test againstERANGE. Looks like:int main() { char buf[256]; if (getlogin_r(buf, sizeof(buf)) != 0) { strncpy(buf, "<unknown>", sizeof(buf)); // or handle the error however you want } printf("user is: %s\n", buf); return 0; }
Thank you, @therealkenc . It does say it returns "nonzero" instead of -1 for error.
Still somewhat broken for me. I found this issue while using the python function os.getlogin()
The first wsl call that boots the distro opens a proper login shell and create the /var/run/utmp entries.
Every following wsl call directly opens a shell without being connected to a login session.
You can start a new login session with simply sudo login that will make the proper entry in the utmp file.
first powershell window
PS C:\Users\bigpet> wsl
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.146.1-microsoft-standard-WSL2 x86_64)
bigpet@Ubuntu:~$ python -c "import os; print(os.getlogin())"
bigpet
in another powershell window
PS C:\Users\bigpet> wsl
bigpet@Ubuntu:~$ python -c "import os; print(os.getlogin())"
Traceback (most recent call last):
File "<string>", line 1, in <module>
OSError: [Errno 6] No such device or address
bigpet@Ubuntu:~$ sudo login
[sudo] password for bigpet:
Ubuntu login: bigpet
Password:
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.146.1-microsoft-standard-WSL2 x86_64)
bigpet@Ubuntu:~$ python -c "import os; print(os.getlogin())"
bigpet
From a quick glance at the code it looks like the culprit might be this piece of code that creates the login only for the first time a uid creates a process:
https://github.com/microsoft/WSL/blob/1cea24b5bff2bb14e8cb6c2e26e138eb8ac220e0/src/linux/init/config.cpp#L429-L432
But that's mostly a wild guess. Might be completely unrelated
edit: looks like it's slightly related, but not the solution. The code after that does the actual login in a pty that it keeps open. But the pty connected to the terminal is then another one, not directly connected to the terminal presented by wsl.
But my testing is possibly not done with the same version of the code that I'm looking at in this repo
PS C:\Users\bigpet> wsl
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.146.1-microsoft-standard-WSL2 x86_64)
This message is shown once a day. To disable it please create the
/home/bigpet/.hushlogin file.
bigpet@myhost:/mnt/c/Users/bigpet$ python3 -c "import os; print(os.getlogin())"
Traceback (most recent call last):
File "<string>", line 1, in <module>
OSError: [Errno 6] No such device or address
bigpet@myhost:/mnt/c/Users/bigpet$ tty
/dev/pts/0
bigpet@myhost:/mnt/c/Users/bigpet$ who -u
bigpet pts/1 2025-05-21 07:37 . 1105
bigpet@myhost:/mnt/c/Users/bigpet$ exit
logout
PS C:\Users\bigpet> wsl --version
WSL version: 2.1.5.0
Kernel version: 5.15.146.1-2
WSLg version: 1.0.60
MSRDC version: 1.2.5105
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.19045.5737