16

I should write a function to get some information about the system (the most important information is the the architecture). I found the function uname which can be used including sys/utsname.h. Well, though I googled and I read the documentation, I couldn't find any example of the function and I don't understand how to use uname. Anyone can explain me how to use it? it would be great if you can write an example, too. Thanks in advance.

En_t8
  • 7,595
  • 5
  • 20
  • 14

4 Answers4

28

First, include the header:

#include <sys/utsname.h>

Then, define a utsname structure:

struct utsname unameData;

Then, call uname() with a pointer to the struct:

uname(&unameData); // Might check return value here (non-0 = failure)

After this, the struct will contain the info you want:

printf("%s", unameData.sysname);

http://opengroup.org/onlinepubs/007908775/xsh/sysutsname.h.html

Amber
  • 507,862
  • 82
  • 626
  • 550
  • Just remember to use `struct utsname` instead of `struct ustname` or you'll get a `error: storage size of ‘myVar’ isn’t known`. – vesperto Jun 01 '23 at 11:14
26

A fully working example is worth a thousand words. ;-)

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/utsname.h>

int main(void) {

   struct utsname buffer;

   errno = 0;
   if (uname(&buffer) < 0) {
      perror("uname");
      exit(EXIT_FAILURE);
   }

   printf("system name = %s\n", buffer.sysname);
   printf("node name   = %s\n", buffer.nodename);
   printf("release     = %s\n", buffer.release);
   printf("version     = %s\n", buffer.version);
   printf("machine     = %s\n", buffer.machine);

   #ifdef _GNU_SOURCE
      printf("domain name = %s\n", buffer.domainname);
   #endif

   return EXIT_SUCCESS;
}
tupiniquim
  • 401
  • 4
  • 5
  • 2
    Should use `perror` on failure. No need to handle the `EFAULT` specially (it won't happen in your code, since `buffer` is a valid address of a local variable) – Basile Starynkevitch Dec 24 '14 at 17:24
  • 1
    Thanks Basile. In fact `perror` is better than `switch (errno)` and I've edited the post to reflect that. The code was explicitly handling `EFAULT` because I wrote it with teaching in mind, but indeed this particular example would never get there. – tupiniquim Feb 13 '15 at 19:12
  • 2
    uname() may return 0 in case of success, code has to be changed to `uname(&buffer) < 0` – Étienne Apr 17 '20 at 09:00
  • it would be even more valuable to see the output on various machines/distros. Weird that nobody does that even though they went through the trouble of creating the code. – Andrew Robinson Mar 11 '23 at 13:00
9

From the documentation, it looks like you'd use it like so:

struct utsname my_uname;
if(uname(&my_uname) == -1)
   printf("uname call failed!");
else
   printf("System name: %s\nNodename:%s\nRelease:%s\nVersion:%s\nMachine:%s\n",
       my_uname.sysname, my_uname.nodename, my_uname.release,my_uname.version,my_uname.machine);
jkerian
  • 16,497
  • 3
  • 46
  • 59
6

The uname() function takes a pointer to the utsname structure that will store the result as input. Therefore, just make a temporary utsname instance, pass the address of it to uname, and read the content of this struct after the function succeed.

struct utsname retval;
if(uname(&retval) < 0) {     // <----
  perror("Failed to uname");
  // error handling...
} else {
  printf("System name = %s\n", retval.sysname);
  // print other info....
  // see http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/utsname.h.html
  //   for other members...
}
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005