Add support for Windows CE and various non-x86 CPU types.
[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 <stdlib.h>
27 #include <unistd.h>
28 #include <windows.h>
29
30 /* Mingw headers don't have all the platform codes.  */
31 #ifndef VER_PLATFORM_WIN32_CE
32 # define VER_PLATFORM_WIN32_CE 3
33 #endif
34
35 /* Some headers don't have all the processor architecture codes.  */
36 #ifndef PROCESSOR_ARCHITECTURE_AMD64
37 # define PROCESSOR_ARCHITECTURE_AMD64 9
38 #endif
39 #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
40 # define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
41 #endif
42
43 /* Mingw headers don't have the latest processor codes.  */
44 #ifndef PROCESSOR_AMD_X8664
45 # define PROCESSOR_AMD_X8664 8664
46 #endif
47
48 int
49 uname (struct utsname *buf)
50 {
51   OSVERSIONINFO version;
52   const char *super_version;
53
54   /* Fill in nodename.  */
55   if (gethostname (buf->nodename, sizeof (buf->nodename)) < 0)
56     strcpy (buf->nodename, "localhost");
57
58   /* Determine major-major Windows version.  */
59   version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
60   if (!GetVersionEx (&version))
61     abort ();
62   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
63     {
64       /* Windows NT or newer.  */
65       super_version = "NT";
66     }
67   else if (version.dwPlatformId == VER_PLATFORM_WIN32_CE)
68     {
69       /* Windows CE or Embedded CE.  */
70       super_version = "CE";
71     }
72   else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
73     {
74       /* Windows 95/98/ME.  */
75       switch (version.dwMinorVersion)
76         {
77         case 0:
78           super_version = "95";
79           break;
80         case 10:
81           super_version = "98";
82           break;
83         case 90:
84           super_version = "ME";
85           break;
86         default:
87           super_version = "";
88           break;
89         }
90     }
91   else
92     super_version = "";
93
94   /* Fill in sysname.  */
95 #ifdef __MINGW32__
96   /* Returns a string compatible with the MSYS uname.exe program,
97      so that no further changes are needed to GNU config.guess.
98      For example,
99        $ ./uname.exe -s      => MINGW32_NT-5.1
100    */
101   sprintf (buf->sysname, "MINGW32_%s-%u.%u", super_version,
102            (unsigned int) version.dwMajorVersion,
103            (unsigned int) version.dwMinorVersion);
104 #else
105   sprintf (buf->sysname, "Windows%s", super_version);
106 #endif
107
108   /* Fill in release, version.  */
109   /* The MSYS uname.exe programs uses strings from a modified Cygwin runtime:
110        $ ./uname.exe -r      => 1.0.11(0.46/3/2)
111        $ ./uname.exe -v      => 2008-08-25 23:40
112      There is no point in imitating this behaviour.  */
113   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
114     {
115       /* Windows NT or newer.  */
116       if (version.dwMajorVersion <= 4)
117         sprintf (buf->release, "Windows NT %u.%u",
118                  (unsigned int) version.dwMajorVersion,
119                  (unsigned int) version.dwMinorVersion);
120       else if (version.dwMajorVersion == 5)
121         switch (version.dwMinorVersion)
122           {
123           case 0:
124             strcpy (buf->release, "Windows 2000");
125             break;
126           case 1:
127             strcpy (buf->release, "Windows XP");
128             break;
129           case 2:
130             strcpy (buf->release, "Windows Server 2003");
131             break;
132           default:
133             strcpy (buf->release, "Windows");
134             break;
135           }
136       else if (version.dwMajorVersion == 6)
137         {
138           OSVERSIONINFOEX versionex;
139
140           versionex.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
141           if (GetVersionEx ((OSVERSIONINFO *) &versionex)
142               && versionex.wProductType != VER_NT_WORKSTATION)
143             strcpy (buf->release, "Windows Server 2008");
144           else
145             switch (version.dwMinorVersion)
146               {
147               case 0:
148                 strcpy (buf->release, "Windows Vista");
149                 break;
150               case 1:
151               default: /* versions not yet known */
152                 strcpy (buf->release, "Windows 7");
153                 break;
154               }
155         }
156       else
157         strcpy (buf->release, "Windows");
158     }
159   else if (version.dwPlatformId == VER_PLATFORM_WIN32_CE)
160     {
161       /* Windows CE or Embedded CE.  */
162       sprintf (buf->release, "Windows CE %u.%u",
163                (unsigned int) version.dwMajorVersion,
164                (unsigned int) version.dwMinorVersion);
165     }
166   else
167     {
168       /* Windows 95/98/ME.  */
169       sprintf (buf->release, "Windows %s", super_version);
170     }
171   strcpy (buf->version, version.szCSDVersion);
172
173   /* Fill in machine.  */
174   {
175     SYSTEM_INFO info;
176
177     GetSystemInfo (&info);
178     /* Check for Windows NT or CE, since the info.wProcessorLevel is
179        garbage on Windows 95. */
180     if (version.dwPlatformId == VER_PLATFORM_WIN32_NT
181         || version.dwPlatformId == VER_PLATFORM_WIN32_CE)
182       {
183         /* Windows NT or newer, or Windows CE or Embedded CE.  */
184         switch (info.wProcessorArchitecture)
185           {
186           case PROCESSOR_ARCHITECTURE_AMD64:
187             strcpy (buf->machine, "x86_64");
188             break;
189           case PROCESSOR_ARCHITECTURE_IA64:
190             strcpy (buf->machine, "ia64");
191             break;
192           case PROCESSOR_ARCHITECTURE_INTEL:
193             strcpy (buf->machine, "i386");
194             if (info.wProcessorLevel >= 3)
195               buf->machine[1] =
196                 '0' + (info.wProcessorLevel <= 6 ? info.wProcessorLevel : 6);
197             break;
198           case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
199             strcpy (buf->machine, "i686");
200             break;
201           case PROCESSOR_ARCHITECTURE_MIPS:
202             strcpy (buf->machine, "mips");
203             break;
204           case PROCESSOR_ARCHITECTURE_ALPHA:
205           case PROCESSOR_ARCHITECTURE_ALPHA64:
206             strcpy (buf->machine, "alpha");
207             break;
208           case PROCESSOR_ARCHITECTURE_PPC:
209             strcpy (buf->machine, "powerpc");
210             break;
211           case PROCESSOR_ARCHITECTURE_SHX:
212             strcpy (buf->machine, "sh");
213             break;
214           case PROCESSOR_ARCHITECTURE_ARM:
215             strcpy (buf->machine, "arm");
216             break;
217           default:
218             strcpy (buf->machine, "unknown");
219             break;
220           }
221       }
222     else
223       {
224         /* Windows 95/98/ME.  */
225         switch (info.dwProcessorType)
226           {
227           case PROCESSOR_AMD_X8664:
228             strcpy (buf->machine, "x86_64");
229             break;
230           case PROCESSOR_INTEL_IA64:
231             strcpy (buf->machine, "ia64");
232             break;
233           default:
234             if (info.dwProcessorType % 100 == 86)
235               sprintf (buf->machine, "i%u",
236                        (unsigned int) info.dwProcessorType);
237             else
238               strcpy (buf->machine, "unknown");
239             break;
240           }
241       }
242   }
243
244   return 0;
245 }
246
247 #endif