Portable way to get user name

6.4k views Asked by At

For C/C++ there seems to be no portable function to get the user name in Linux/Posix and Windows. What would be the least cumbersome and yet robust portable code to achieve this ?

In Linux the USER environment variable seems always to be defined, whereas Windows seems to define the USERNAME variable. Relying on getenv one could avoid including windows.h and minimize preprocessor statements:

char * user_name = getenv("USER");
if (!user_name) {
     user_name = getenv("USERNAME");
}

But is this approach halfway robust ? Or am I ignorant to another solution ? And I was also ignorant towards iOS ...

4

There are 4 answers

1
James Kanze On BEST ANSWER

There is no portable solution.

Under Linux (and Unix in general), a "user" is a number, and can have several different names. Use getuid to get the id, then getpwuid to get one of the names. Or use getlogin to get the name the user used to login (but this will only work if the process has a controlling terminal). If you want to get all of the names the user is known under, you'll have to iterate using getpwent, checking the pw_uid field for each entry returned.

The use of an environment variable is not guaranteed. In many contexts, the environment variable won't be set, and even if it is, it's not guaranteed to be correct.

Windows has a function GetUserName; I don't know too much about it, however.

1
Michał Walenciak On

You are right - there is no portable way to do it. There are two solutions for that: use proper set of ifdef's to use one code on window, and another on linux.

the other way is to do it with factory which would return you an abstract object or pointer to function which would be system specific. Factory should detect system and return proper function/class

1
Mats Petersson On

Using environment variables to find the username is very unreliable:

I expanded your code to this:

#include <iostream>

int main()
{
    char * user_name = getenv("USER");
    std::cout << user_name << std::endl;
}

and did this:

$ whoami
MatsP
$ g++ -Wall -std=c++0x getenv.cpp 
$ ./a.out
MatsP
$ export USER=DonaldDuck
$ ./a.out
DonaldDuck

So, I would definitely suggest that if the username is of any importance to your code, then you should use a system-specific function to get the username. If it's not important to your code, ask at install time or some such, and don't try to use any system function to fetch the username.

(In answer to your actual question, yes, I would think that an iOS has the same functionality of a USER environment variable - although I'm not sure there is a meaningful user on an iPhone).

0
mvw On

The user concept is related to the operating system or even system, not the language.

As there are a myriad of different systems around, the only feasable approach is to limit yourself to a list of systems you want to support.

There exists software that can help you to achieve portability, like the GNU autotools for Unix like systems (and to a certain degree Windows).