Open Journal Systems  3.3.0
Guess.php
1 <?php
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 
93 class OS_Guess
94 {
95  var $sysname;
96  var $nodename;
97  var $cpu;
98  var $release;
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  switch ($parts[1]) {
142  case '95/98':
143  $release = '9x';
144  break;
145  default:
146  $release = $parts[1];
147  break;
148  }
149  $cpu = 'i386';
150  break;
151  case 'Linux' :
152  $extra = $this->_detectGlibcVersion();
153  // use only the first two digits from the kernel version
154  $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
155  break;
156  case 'Mac' :
157  $sysname = 'darwin';
158  $nodename = $parts[2];
159  $release = $parts[3];
160  if ($cpu == 'Macintosh') {
161  if ($parts[$n - 2] == 'Power') {
162  $cpu = 'powerpc';
163  }
164  }
165  break;
166  case 'Darwin' :
167  if ($cpu == 'Macintosh') {
168  if ($parts[$n - 2] == 'Power') {
169  $cpu = 'powerpc';
170  }
171  }
172  $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
173  break;
174  default:
175  $release = preg_replace('/-.*/', '', $parts[2]);
176  break;
177  }
178 
179  if (isset($sysmap[$sysname])) {
180  $sysname = $sysmap[$sysname];
181  } else {
182  $sysname = strtolower($sysname);
183  }
184  if (isset($cpumap[$cpu])) {
185  $cpu = $cpumap[$cpu];
186  }
187  return array($sysname, $release, $cpu, $extra, $nodename);
188  }
189 
191  {
192  static $glibc = false;
193  if ($glibc !== false) {
194  return $glibc; // no need to run this multiple times
195  }
196  $major = $minor = 0;
197  include_once "System.php";
198 
199  if (@is_link('/lib64/libc.so.6')) {
200  // Let's try reading the libc.so.6 symlink
201  if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib64/libc.so.6')), $matches)) {
202  list($major, $minor) = explode('.', $matches[1]);
203  }
204  } else if (@is_link('/lib/libc.so.6')) {
205  // Let's try reading the libc.so.6 symlink
206  if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) {
207  list($major, $minor) = explode('.', $matches[1]);
208  }
209  }
210  // Use glibc's <features.h> header file to
211  // get major and minor version number:
212  if (!($major && $minor) &&
213  @file_exists('/usr/include/features.h') &&
214  @is_readable('/usr/include/features.h')) {
215  if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
216  $features_file = fopen('/usr/include/features.h', 'rb');
217  while (!feof($features_file)) {
218  $line = fgets($features_file, 8192);
219  if (!$line || (strpos($line, '#define') === false)) {
220  continue;
221  }
222  if (strpos($line, '__GLIBC__')) {
223  // major version number #define __GLIBC__ version
224  $line = preg_split('/\s+/', $line);
225  $glibc_major = trim($line[2]);
226  if (isset($glibc_minor)) {
227  break;
228  }
229  continue;
230  }
231 
232  if (strpos($line, '__GLIBC_MINOR__')) {
233  // got the minor version number
234  // #define __GLIBC_MINOR__ version
235  $line = preg_split('/\s+/', $line);
236  $glibc_minor = trim($line[2]);
237  if (isset($glibc_major)) {
238  break;
239  }
240  continue;
241  }
242  }
243  fclose($features_file);
244  if (!isset($glibc_major) || !isset($glibc_minor)) {
245  return $glibc = '';
246  }
247  return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
248  } // no cpp
249 
250  $tmpfile = System::mktemp("glibctest");
251  $fp = fopen($tmpfile, "w");
252  fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
253  fclose($fp);
254  $cpp = popen("/usr/bin/cpp $tmpfile", "r");
255  while ($line = fgets($cpp, 1024)) {
256  if ($line[0] == '#' || trim($line) == '') {
257  continue;
258  }
259 
260  if (list($major, $minor) = explode(' ', trim($line))) {
261  break;
262  }
263  }
264  pclose($cpp);
265  unlink($tmpfile);
266  } // features.h
267 
268  if (!($major && $minor)) {
269  return $glibc = '';
270  }
271 
272  return $glibc = "glibc{$major}.{$minor}";
273  }
274 
275  function getSignature()
276  {
277  if (empty($this->extra)) {
278  return "{$this->sysname}-{$this->release}-{$this->cpu}";
279  }
280  return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
281  }
282 
283  function getSysname()
284  {
285  return $this->sysname;
286  }
287 
288  function getNodename()
289  {
290  return $this->nodename;
291  }
292 
293  function getCpu()
294  {
295  return $this->cpu;
296  }
297 
298  function getRelease()
299  {
300  return $this->release;
301  }
302 
303  function getExtra()
304  {
305  return $this->extra;
306  }
307 
308  function matchSignature($match)
309  {
310  $fragments = is_array($match) ? $match : explode('-', $match);
311  $n = count($fragments);
312  $matches = 0;
313  if ($n > 0) {
314  $matches += $this->_matchFragment($fragments[0], $this->sysname);
315  }
316  if ($n > 1) {
317  $matches += $this->_matchFragment($fragments[1], $this->release);
318  }
319  if ($n > 2) {
320  $matches += $this->_matchFragment($fragments[2], $this->cpu);
321  }
322  if ($n > 3) {
323  $matches += $this->_matchFragment($fragments[3], $this->extra);
324  }
325  return ($matches == $n);
326  }
327 
328  function _matchFragment($fragment, $value)
329  {
330  if (strcspn($fragment, '*?') < strlen($fragment)) {
331  $reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/';
332  return preg_match($reg, $value);
333  }
334  return ($fragment == '*' || !strcasecmp($fragment, $value));
335  }
336 
337 }
338 /*
339  * Local Variables:
340  * indent-tabs-mode: nil
341  * c-basic-offset: 4
342  * End:
343  */
OS_Guess\$nodename
$nodename
Definition: Guess.php:96
OS_Guess\getNodename
getNodename()
Definition: Guess.php:288
OS_Guess\$extra
$extra
Definition: Guess.php:99
OS_Guess\__construct
__construct($uname=null)
Definition: Guess.php:101
OS_Guess\getExtra
getExtra()
Definition: Guess.php:303
OS_Guess\parseSignature
parseSignature($uname=null)
Definition: Guess.php:110
OS_Guess\$cpu
$cpu
Definition: Guess.php:97
OS_Guess\$sysname
$sysname
Definition: Guess.php:95
OS_Guess\getSysname
getSysname()
Definition: Guess.php:283
OS_Guess\_matchFragment
_matchFragment($fragment, $value)
Definition: Guess.php:328
OS_Guess\matchSignature
matchSignature($match)
Definition: Guess.php:308
OS_Guess\getRelease
getRelease()
Definition: Guess.php:298
OS_Guess\_detectGlibcVersion
_detectGlibcVersion()
Definition: Guess.php:190
OS_Guess
Definition: Guess.php:93
OS_Guess\$release
$release
Definition: Guess.php:98
OS_Guess\getSignature
getSignature()
Definition: Guess.php:275
OS_Guess\getCpu
getCpu()
Definition: Guess.php:293
System\mktemp
static mktemp($args=null)
Definition: System.php:395