Bearsampp 2026.9.23
Loading...
Searching...
No Matches
Guess.php
Go to the documentation of this file.
1<?php
16
17// {{{ uname examples
18
19// php_uname() without args returns the same as 'uname -a', or a PHP-custom
20// string for Windows.
21// PHP versions prior to 4.3 return the uname of the host where PHP was built,
22// as of 4.3 it returns the uname of the host running the PHP code.
23//
24// PC RedHat Linux 7.1:
25// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
26//
27// PC Debian Potato:
28// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
29//
30// PC FreeBSD 3.3:
31// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386
32//
33// PC FreeBSD 4.3:
34// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386
35//
36// PC FreeBSD 4.5:
37// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386
38//
39// PC FreeBSD 4.5 w/uname from GNU shellutils:
40// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown
41//
42// HP 9000/712 HP-UX 10:
43// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
44//
45// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
46// HP-UX host B.10.10 A 9000/712 unknown
47//
48// IBM RS6000/550 AIX 4.3:
49// AIX host 3 4 000003531C00
50//
51// AIX 4.3 w/uname from GNU shellutils:
52// AIX host 3 4 000003531C00 unknown
53//
54// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
55// IRIX64 host 6.5 01091820 IP19 mips
56//
57// SGI Onyx IRIX 6.5:
58// IRIX64 host 6.5 01091820 IP19
59//
60// SparcStation 20 Solaris 8 w/uname from GNU shellutils:
61// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
62//
63// SparcStation 20 Solaris 8:
64// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
65//
66// Mac OS X (Darwin)
67// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh
68//
69// Mac OS X early versions
70//
71
72// }}}
73
74/* TODO:
75 * - define endianness, to allow matchSignature("bigend") etc.
76 */
77
94{
97 var $cpu;
99 var $extra;
100
101 function __construct($uname = null)
102 {
103 list($this->sysname,
104 $this->release,
105 $this->cpu,
106 $this->extra,
107 $this->nodename) = $this->parseSignature($uname);
108 }
109
110 function parseSignature($uname = null)
111 {
112 static $sysmap = array(
113 'HP-UX' => 'hpux',
114 'IRIX64' => 'irix',
115 );
116 static $cpumap = array(
117 'i586' => 'i386',
118 'i686' => 'i386',
119 'ppc' => 'powerpc',
120 );
121 if ($uname === null) {
122 $uname = php_uname();
123 }
124 $parts = preg_split('/\s+/', trim($uname));
125 $n = count($parts);
126
127 $release = $machine = $cpu = '';
128 $sysname = $parts[0];
129 $nodename = $parts[1];
130 $cpu = $parts[$n-1];
131 $extra = '';
132 if ($cpu == 'unknown') {
133 $cpu = $parts[$n - 2];
134 }
135
136 switch ($sysname) {
137 case 'AIX' :
138 $release = "$parts[3].$parts[2]";
139 break;
140 case 'Windows' :
141 $release = $parts[1];
142 if ($release == '95/98') {
143 $release = '9x';
144 }
145 $cpu = 'i386';
146 break;
147 case 'Linux' :
148 $extra = $this->_detectGlibcVersion();
149 // use only the first two digits from the kernel version
150 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
151 break;
152 case 'Mac' :
153 $sysname = 'darwin';
154 $nodename = $parts[2];
155 $release = $parts[3];
156 $cpu = $this->_determineIfPowerpc($cpu, $parts);
157 break;
158 case 'Darwin' :
159 $cpu = $this->_determineIfPowerpc($cpu, $parts);
160 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
161 break;
162 default:
163 $release = preg_replace('/-.*/', '', $parts[2]);
164 break;
165 }
166
167 if (isset($sysmap[$sysname])) {
168 $sysname = $sysmap[$sysname];
169 } else {
170 $sysname = strtolower($sysname);
171 }
172 if (isset($cpumap[$cpu])) {
173 $cpu = $cpumap[$cpu];
174 }
175 return array($sysname, $release, $cpu, $extra, $nodename);
176 }
177
178 function _determineIfPowerpc($cpu, $parts)
179 {
180 $n = count($parts);
181 if ($cpu == 'Macintosh' && $parts[$n - 2] == 'Power') {
182 $cpu = 'powerpc';
183 }
184 return $cpu;
185 }
186
188 {
189 static $glibc = false;
190 if ($glibc !== false) {
191 return $glibc; // no need to run this multiple times
192 }
193 $major = $minor = 0;
194 include_once "System.php";
195
196 // Let's try reading possible libc.so.6 symlinks
197 $libcs = array(
198 '/lib64/libc.so.6',
199 '/lib/libc.so.6',
200 '/lib/i386-linux-gnu/libc.so.6'
201 );
202 $versions = array();
203 foreach ($libcs as $file) {
204 $versions = $this->_readGlibCVersionFromSymlink($file);
205 if ($versions != []) {
206 list($major, $minor) = $versions;
207 break;
208 }
209 }
210
211 // Use glibc's <features.h> header file to
212 // get major and minor version number:
213 if (!($major && $minor)) {
214 $versions = $this->_readGlibCVersionFromFeaturesHeaderFile();
215 }
216 if (is_array($versions) && $versions != []) {
217 list($major, $minor) = $versions;
218 }
219
220 if (!($major && $minor)) {
221 return $glibc = '';
222 }
223
224 return $glibc = "glibc{$major}.{$minor}";
225 }
226
228 {
229 $versions = array();
230 if (@is_link($file)
231 && (preg_match('/^libc-(.*)\.so$/', basename(readlink($file)), $matches))
232 ) {
233 $versions = explode('.', $matches[1]);
234 }
235 return $versions;
236 }
237
238
240 {
241 $features_header_file = '/usr/include/features.h';
242 if (!(@file_exists($features_header_file)
243 && @is_readable($features_header_file))
244 ) {
245 return array();
246 }
247 if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
248 return $this->_parseFeaturesHeaderFile($features_header_file);
249 } // no cpp
250
251 return $this->_fromGlibCTest();
252 }
253
254 function _parseFeaturesHeaderFile($features_header_file)
255 {
256 $features_file = fopen($features_header_file, 'rb');
257 while (!feof($features_file)) {
258 $line = fgets($features_file, 8192);
259 if (!$this->_IsADefinition($line)) {
260 continue;
261 }
262 if (strpos($line, '__GLIBC__')) {
263 // major version number #define __GLIBC__ version
264 $line = preg_split('/\s+/', $line);
265 $glibc_major = trim($line[2]);
266 if (isset($glibc_minor)) {
267 break;
268 }
269 continue;
270 }
271
272 if (strpos($line, '__GLIBC_MINOR__')) {
273 // got the minor version number
274 // #define __GLIBC_MINOR__ version
275 $line = preg_split('/\s+/', $line);
276 $glibc_minor = trim($line[2]);
277 if (isset($glibc_major)) {
278 break;
279 }
280 }
281 }
282 fclose($features_file);
283 if (!isset($glibc_major) || !isset($glibc_minor)) {
284 return array();
285 }
286 return array(trim($glibc_major), trim($glibc_minor));
287 }
288
289 function _IsADefinition($line)
290 {
291 if ($line === false) {
292 return false;
293 }
294 return strpos(trim($line), '#define') !== false;
295 }
296
297 function _fromGlibCTest()
298 {
299 $major = null;
300 $minor = null;
301
302 $tmpfile = System::mktemp("glibctest");
303 $fp = fopen($tmpfile, "w");
304 fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
305 fclose($fp);
306 $cpp = popen("/usr/bin/cpp $tmpfile", "r");
307 while ($line = fgets($cpp, 1024)) {
308 if ($line[0] == '#' || trim($line) == '') {
309 continue;
310 }
311
312 if (list($major, $minor) = explode(' ', trim($line))) {
313 break;
314 }
315 }
316 pclose($cpp);
317 unlink($tmpfile);
318 if ($major !== null && $minor !== null) {
319 return [$major, $minor];
320 }
321 }
322
323 function getSignature()
324 {
325 if (empty($this->extra)) {
326 return "{$this->sysname}-{$this->release}-{$this->cpu}";
327 }
328 return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
329 }
330
331 function getSysname()
332 {
333 return $this->sysname;
334 }
335
336 function getNodename()
337 {
338 return $this->nodename;
339 }
340
341 function getCpu()
342 {
343 return $this->cpu;
344 }
345
346 function getRelease()
347 {
348 return $this->release;
349 }
350
351 function getExtra()
352 {
353 return $this->extra;
354 }
355
356 function matchSignature($match)
357 {
358 $fragments = is_array($match) ? $match : explode('-', $match);
359 $n = count($fragments);
360 $matches = 0;
361 if ($n > 0) {
362 $matches += $this->_matchFragment($fragments[0], $this->sysname);
363 }
364 if ($n > 1) {
365 $matches += $this->_matchFragment($fragments[1], $this->release);
366 }
367 if ($n > 2) {
368 $matches += $this->_matchFragment($fragments[2], $this->cpu);
369 }
370 if ($n > 3) {
371 $matches += $this->_matchFragment($fragments[3], $this->extra);
372 }
373 return ($matches == $n);
374 }
375
376 function _matchFragment($fragment, $value)
377 {
378 if (strcspn($fragment, '*?') < strlen($fragment)) {
379 $expression = str_replace(
380 array('*', '?', '/'),
381 array('.*', '.', '\\/'),
382 $fragment
383 );
384 $reg = '/^' . $expression . '\\z/';
385 return preg_match($reg, $value);
386 }
387 return ($fragment == '*' || !strcasecmp($fragment, $value));
388 }
389}
390/*
391 * Local Variables:
392 * indent-tabs-mode: nil
393 * c-basic-offset: 4
394 * End:
395 */
_readGlibCVersionFromFeaturesHeaderFile()
Definition Guess.php:239
_determineIfPowerpc($cpu, $parts)
Definition Guess.php:178
_matchFragment($fragment, $value)
Definition Guess.php:376
getSysname()
Definition Guess.php:331
getSignature()
Definition Guess.php:323
_parseFeaturesHeaderFile($features_header_file)
Definition Guess.php:254
_readGlibCVersionFromSymlink($file)
Definition Guess.php:227
$nodename
Definition Guess.php:96
matchSignature($match)
Definition Guess.php:356
getExtra()
Definition Guess.php:351
_fromGlibCTest()
Definition Guess.php:297
parseSignature($uname=null)
Definition Guess.php:110
__construct($uname=null)
Definition Guess.php:101
getRelease()
Definition Guess.php:346
_detectGlibcVersion()
Definition Guess.php:187
getNodename()
Definition Guess.php:336
_IsADefinition($line)
Definition Guess.php:289
getCpu()
Definition Guess.php:341