29

I am developing an application. One of the methods needs to capture the computer name and user logged on the machine, then display both to the user. I need it to run on both Windows and Linux. What is the best way to do this?

Keith M
  • 853
  • 10
  • 28
Mrdk
  • 413
  • 1
  • 4
  • 10
  • 1
    Another thing to consider. If the user runs the application on the Windows Terminal Server, which of two computers name he has to get? – Arioch 'The Jul 31 '18 at 10:42

6 Answers6

28

Windows

You can try to use GetComputerName and GetUserName, here is a example:

#define INFO_BUFFER_SIZE 32767
TCHAR  infoBuf[INFO_BUFFER_SIZE];
DWORD  bufCharCount = INFO_BUFFER_SIZE;

// Get and display the name of the computer.
if( !GetComputerName( infoBuf, &bufCharCount ) )
  printError( TEXT("GetComputerName") ); 
_tprintf( TEXT("\nComputer name:      %s"), infoBuf ); 

// Get and display the user name.
if( !GetUserName( infoBuf, &bufCharCount ) )
  printError( TEXT("GetUserName") ); 
_tprintf( TEXT("\nUser name:          %s"), infoBuf );

see: GetComputerName and GetUserName

Linux

Use gethostname to get computer name(see gethostname), and getlogin_r to get login username. You can look more information at man page of getlogin_r. Simple usage as follows:

#include <unistd.h>
#include <limits.h>

char hostname[HOST_NAME_MAX];
char username[LOGIN_NAME_MAX];
gethostname(hostname, HOST_NAME_MAX);
getlogin_r(username, LOGIN_NAME_MAX);
pezy
  • 1,022
  • 2
  • 8
  • 27
  • 2
    About [HOST_NAME_MAX](http://stackoverflow.com/questions/30084116/host-name-max-undefined-after-include-limits-h). – Antonio Aug 03 '16 at 09:03
  • 2
    32 KB? You only need exactly MAX_COMPUTERNAME_LENGTH+1 characters... Considering the former is only 15, 32 KB is a giant waste... – atlaste May 02 '18 at 18:50
25

If you can use Boost, you can do this to easily get the host name:

#include <boost/asio/ip/host_name.hpp>
// ... whatever ...
const auto host_name = boost::asio::ip::host_name();
Software Craftsman
  • 2,999
  • 2
  • 31
  • 47
10

On POSIX systems you can use the gethostname and getlogin functions, both declared in unistd.h.

/*
   This is a C program (I've seen the C++ tag too late).  Converting
   it to a pretty C++ program is left as an exercise to the reader.
*/

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main()
{
  char hostname[HOST_NAME_MAX];
  char username[LOGIN_NAME_MAX];
  int result;
  result = gethostname(hostname, HOST_NAME_MAX);
  if (result)
    {
      perror("gethostname");
      return EXIT_FAILURE;
    }
  result = getlogin_r(username, LOGIN_NAME_MAX);
  if (result)
    {
      perror("getlogin_r");
      return EXIT_FAILURE;
    }
  result = printf("Hello %s, you are logged in to %s.\n",
                  username, hostname);
  if (result < 0)
    {
      perror("printf");
      return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}

Possible output:

Hello 5gon12eder, you are logged in to example.com.

This seems safer than relying on environment variables which are not always present.

I'm withdrawing that last statement because

  • the man page of getlogin actually discourages its usage in favour of getenv("LOGIN") and
  • the getlogin_r call in the above program fails with ENOTTY when I run the program from within Emacs instead of an interactive terminal while getenv("USER") would have worked in both situations.
5gon12eder
  • 24,280
  • 5
  • 45
  • 92
7

Use gethostname() to get computer name, support both windows and linux.

whoan
  • 8,143
  • 4
  • 39
  • 48
Keven
  • 71
  • 1
5

Regarding Denis's answer, note that getenv("HOSTNAME") for Linux may not always work because the environment variables may not be exported to the program.

Multi-platform C++ code example to fetch just the computer name (this is what worked for my Win7 and CentOS machines):

    char *temp = 0;
    std::string computerName;

#if defined(WIN32) || defined(_WIN32) || defined(_WIN64)
    temp = getenv("COMPUTERNAME");
    if (temp != 0) {
        computerName = temp;
        temp = 0;
    }
#else
    temp = getenv("HOSTNAME");
    if (temp != 0) {
        computerName = temp;
        temp = 0;
    } else {
        temp = new char[512];
        if (gethostname(temp, 512) == 0) { // success = 0, failure = -1
            computerName = temp;
        }
        delete []temp;
        temp = 0;
    }
#endif
Keith M
  • 853
  • 10
  • 28
  • 1
    Not only will it not always be available to the program, but there are [other deficiencies](https://stackoverflow.com/questions/27914311/get-computer-name-and-logged-user-name#comment95239774_27914342) with using it as well. Using `gethostname()` is unequivocally the better answer for Linux/POSIX. – villapx Jan 15 '19 at 20:48
0

in Linux you can also use the following using Posix library to retrieve the real user that owns the process: getuid() returns the real user ID of the calling process. see getuid man page

#include <pwd.h>
string userName = "unknownUser";
// Structure to store user info
struct passwd p;
// Get user ID of the application
uid_t uid = getuid();

// Buffer that contains password additional information
char pwdBuffer[ourPwdBufferSize];
// Temporary structure for reentrant function
struct passwd* tempPwdPtr;

if ((getpwuid_r(uid, &p, pwdBuffer, sizeof(pwdBuffer),
        &tempPwdPtr)) == 0) {
    userName = p.pw_name;
}