New module 'uname'.
[gnulib.git] / lib / uname.c
1 /* uname replacement.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 /* Specification.  */
20 #include <sys/utsname.h>
21
22 /* This file provides an implementation only for the native Windows API.  */
23 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
24
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <windows.h>
28
29 /* Mingw headers don't have latest processor codes.  */
30 #ifndef PROCESSOR_AMD_X8664
31 # define PROCESSOR_AMD_X8664 8664
32 #endif
33
34 int
35 uname (struct utsname *buf)
36 {
37   OSVERSIONINFO version;
38   BOOL have_version;
39   const char *super_version;
40
41   /* Fill in nodename.  */
42   if (gethostname (buf->nodename, sizeof (buf->nodename)) < 0)
43     strcpy (buf->nodename, "localhost");
44
45   /* Determine major-major Windows version.  */
46   version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
47   have_version = GetVersionEx (&version);
48   if (have_version)
49     {
50       if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
51         {
52           /* Windows NT or newer.  */
53           super_version = "NT";
54         }
55       else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
56         {
57           /* Windows 95/98/ME.  */
58           switch (version.dwMinorVersion)
59             {
60             case 0:
61               super_version = "95";
62               break;
63             case 10:
64               super_version = "98";
65               break;
66             case 90:
67               super_version = "ME";
68               break;
69             default:
70               super_version = "";
71               break;
72             }
73         }
74       else
75         super_version = "";
76     }
77   else
78     super_version = "";
79
80   /* Fill in sysname.  */
81 #ifdef __MINGW32__
82   /* Returns a string compatible with the MSYS uname.exe program,
83      so that no further changes are needed to GNU config.guess.
84      For example,
85        $ ./uname.exe -s      => MINGW32_NT-5.1
86    */
87   if (have_version)
88     sprintf (buf->sysname, "MINGW32_%s-%u.%u", super_version,
89              (unsigned int) version.dwMajorVersion,
90              (unsigned int) version.dwMinorVersion);
91   else
92     strcpy (buf->sysname, "MINGW32");
93 #else
94   if (have_version)
95     sprintf (buf->sysname, "Windows%s", super_version);
96   else
97     strcpy (buf->sysname, "Windows");
98 #endif
99
100   /* Fill in release, version.  */
101   /* The MSYS uname.exe programs uses strings from a modified Cygwin runtime:
102        $ ./uname.exe -r      => 1.0.11(0.46/3/2)
103        $ ./uname.exe -v      => 2008-08-25 23:40
104      There is no point in imitating this behaviour.  */
105   if (have_version)
106     {
107       if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
108         {
109           /* Windows NT or newer.  */
110           if (version.dwMajorVersion <= 4)
111             sprintf (buf->release, "Windows NT %u.%u",
112                      (unsigned int) version.dwMajorVersion,
113                      (unsigned int) version.dwMinorVersion);
114           else if (version.dwMajorVersion == 5)
115             switch (version.dwMinorVersion)
116               {
117               case 0:
118                 strcpy (buf->release, "Windows 2000");
119                 break;
120               case 1:
121                 strcpy (buf->release, "Windows XP");
122                 break;
123               case 2:
124                 strcpy (buf->release, "Windows Server 2003");
125                 break;
126               default:
127                 strcpy (buf->release, "Windows");
128                 break;
129               }
130           else if (version.dwMajorVersion == 6)
131             {
132               OSVERSIONINFOEX versionex;
133
134               versionex.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
135               if (GetVersionEx ((OSVERSIONINFO *) &versionex)
136                   && versionex.wProductType != VER_NT_WORKSTATION)
137                 strcpy (buf->release, "Windows Server 2008");
138               else
139                 switch (version.dwMinorVersion)
140                   {
141                   case 0:
142                     strcpy (buf->release, "Windows Vista");
143                     break;
144                   case 1:
145                   default: /* versions not yet known */
146                     strcpy (buf->release, "Windows 7");
147                     break;
148                   }
149             }
150           else
151             strcpy (buf->release, "Windows");
152         }
153       else
154         {
155           /* Windows 95/98/ME.  */
156           sprintf (buf->release, "Windows %s", super_version);
157         }
158       strcpy (buf->version, version.szCSDVersion);
159     }
160   else
161     {
162       strcpy (buf->release, "Windows");
163       strcpy (buf->version, "");
164     }
165
166   /* Fill in machine.  */
167   {
168     SYSTEM_INFO info;
169
170     GetSystemInfo (&info);
171     /* Check for Windows NT, since the info.wProcessorLevel is
172        garbage on Windows 95. */
173     if (have_version && version.dwPlatformId == VER_PLATFORM_WIN32_NT)
174       {
175         /* Windows NT or newer.  */
176         switch (info.wProcessorArchitecture)
177           {
178           case PROCESSOR_ARCHITECTURE_AMD64:
179             strcpy (buf->machine, "x86_64");
180             break;
181           case PROCESSOR_ARCHITECTURE_IA64:
182             strcpy (buf->machine, "ia64");
183             break;
184           case PROCESSOR_ARCHITECTURE_INTEL:
185             strcpy (buf->machine, "i386");
186             if (info.wProcessorLevel >= 3)
187               buf->machine[1] =
188                 '0' + (info.wProcessorLevel <= 6 ? info.wProcessorLevel : 6);
189             break;
190           default:
191             strcpy (buf->machine, "unknown");
192             break;
193           }
194       }
195     else
196       {
197         /* Windows 95/98/ME.  */
198         switch (info.dwProcessorType)
199           {
200           case PROCESSOR_AMD_X8664:
201             strcpy (buf->machine, "x86_64");
202             break;
203           case PROCESSOR_INTEL_IA64:
204             strcpy (buf->machine, "ia64");
205             break;
206           default:
207             if (info.dwProcessorType % 100 == 86)
208               sprintf (buf->machine, "i%u",
209                        (unsigned int) info.dwProcessorType);
210             else
211               strcpy (buf->machine, "unknown");
212             break;
213           }
214       }
215   }
216
217   return 0;
218 }
219
220 #endif