Assume version info is available.
[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 latest processor codes.  */
31 #ifndef PROCESSOR_AMD_X8664
32 # define PROCESSOR_AMD_X8664 8664
33 #endif
34
35 int
36 uname (struct utsname *buf)
37 {
38   OSVERSIONINFO 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   if (!GetVersionEx (&version))
48     abort ();
49   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
50     {
51       /* Windows NT or newer.  */
52       super_version = "NT";
53     }
54   else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
55     {
56       /* Windows 95/98/ME.  */
57       switch (version.dwMinorVersion)
58         {
59         case 0:
60           super_version = "95";
61           break;
62         case 10:
63           super_version = "98";
64           break;
65         case 90:
66           super_version = "ME";
67           break;
68         default:
69           super_version = "";
70           break;
71         }
72     }
73   else
74     super_version = "";
75
76   /* Fill in sysname.  */
77 #ifdef __MINGW32__
78   /* Returns a string compatible with the MSYS uname.exe program,
79      so that no further changes are needed to GNU config.guess.
80      For example,
81        $ ./uname.exe -s      => MINGW32_NT-5.1
82    */
83   sprintf (buf->sysname, "MINGW32_%s-%u.%u", super_version,
84            (unsigned int) version.dwMajorVersion,
85            (unsigned int) version.dwMinorVersion);
86 #else
87   sprintf (buf->sysname, "Windows%s", super_version);
88 #endif
89
90   /* Fill in release, version.  */
91   /* The MSYS uname.exe programs uses strings from a modified Cygwin runtime:
92        $ ./uname.exe -r      => 1.0.11(0.46/3/2)
93        $ ./uname.exe -v      => 2008-08-25 23:40
94      There is no point in imitating this behaviour.  */
95   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
96     {
97       /* Windows NT or newer.  */
98       if (version.dwMajorVersion <= 4)
99         sprintf (buf->release, "Windows NT %u.%u",
100                  (unsigned int) version.dwMajorVersion,
101                  (unsigned int) version.dwMinorVersion);
102       else if (version.dwMajorVersion == 5)
103         switch (version.dwMinorVersion)
104           {
105           case 0:
106             strcpy (buf->release, "Windows 2000");
107             break;
108           case 1:
109             strcpy (buf->release, "Windows XP");
110             break;
111           case 2:
112             strcpy (buf->release, "Windows Server 2003");
113             break;
114           default:
115             strcpy (buf->release, "Windows");
116             break;
117           }
118       else if (version.dwMajorVersion == 6)
119         {
120           OSVERSIONINFOEX versionex;
121
122           versionex.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
123           if (GetVersionEx ((OSVERSIONINFO *) &versionex)
124               && versionex.wProductType != VER_NT_WORKSTATION)
125             strcpy (buf->release, "Windows Server 2008");
126           else
127             switch (version.dwMinorVersion)
128               {
129               case 0:
130                 strcpy (buf->release, "Windows Vista");
131                 break;
132               case 1:
133               default: /* versions not yet known */
134                 strcpy (buf->release, "Windows 7");
135                 break;
136               }
137         }
138       else
139         strcpy (buf->release, "Windows");
140     }
141   else
142     {
143       /* Windows 95/98/ME.  */
144       sprintf (buf->release, "Windows %s", super_version);
145     }
146   strcpy (buf->version, version.szCSDVersion);
147
148   /* Fill in machine.  */
149   {
150     SYSTEM_INFO info;
151
152     GetSystemInfo (&info);
153     /* Check for Windows NT, since the info.wProcessorLevel is
154        garbage on Windows 95. */
155     if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
156       {
157         /* Windows NT or newer.  */
158         switch (info.wProcessorArchitecture)
159           {
160           case PROCESSOR_ARCHITECTURE_AMD64:
161             strcpy (buf->machine, "x86_64");
162             break;
163           case PROCESSOR_ARCHITECTURE_IA64:
164             strcpy (buf->machine, "ia64");
165             break;
166           case PROCESSOR_ARCHITECTURE_INTEL:
167             strcpy (buf->machine, "i386");
168             if (info.wProcessorLevel >= 3)
169               buf->machine[1] =
170                 '0' + (info.wProcessorLevel <= 6 ? info.wProcessorLevel : 6);
171             break;
172           default:
173             strcpy (buf->machine, "unknown");
174             break;
175           }
176       }
177     else
178       {
179         /* Windows 95/98/ME.  */
180         switch (info.dwProcessorType)
181           {
182           case PROCESSOR_AMD_X8664:
183             strcpy (buf->machine, "x86_64");
184             break;
185           case PROCESSOR_INTEL_IA64:
186             strcpy (buf->machine, "ia64");
187             break;
188           default:
189             if (info.dwProcessorType % 100 == 86)
190               sprintf (buf->machine, "i%u",
191                        (unsigned int) info.dwProcessorType);
192             else
193               strcpy (buf->machine, "unknown");
194             break;
195           }
196       }
197   }
198
199   return 0;
200 }
201
202 #endif