1// Compare given libc name and version number to system name and version.
2
3// Returns
4// - 0 if the libc name matches is at least the minimum version (if given).
5// - 1 if the libc name doesn't match or the version is lower than requested.
6// - 2 if the requested libc name isn't recognised.
7// - 3 if there was a usage error (it also prints an error message).
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#ifdef __GLIBC__
14#include <gnu/libc-version.h>
15#endif
16
17#define False  0
18#define True   1
19typedef int    Bool;
20
21/* Assumes the versions are x.y.z, with y and z optional. */
22static __attribute__((unused)) Bool matches_version(char *min_version) {
23   int a1=0, a2=0, a3=0, g1=0, g2=0, g3=0;  // 'a' = actual;  'g' = given
24   const char *aversion;
25
26   if (min_version == NULL)  return True;  // no version specified
27
28   // get actual version number
29#ifdef __GLIBC__
30   aversion = gnu_get_libc_version();
31#else
32   aversion = "unknown";
33#endif
34   // We expect at least one number.
35   if (sscanf(aversion, "%d.%d.%d", &a1, &a2, &a3) < 1) return False;
36
37   // parse given version number.
38   if (sscanf(min_version, "%d.%d.%d", &g1, &g2, &g3) < 1) return False;
39
40   if (a1 > g1) return True;
41   if (a1 < g1) return False;
42   if (a2 > g2) return True;
43   if (a2 < g2) return False;
44   if (a3 >= g3) return True;
45
46   return False;
47}
48
49static Bool go(char* libc, char *min_version)
50{
51#ifdef __GLIBC__
52   if ( 0 == strcmp( libc, "glibc" )
53	&& matches_version( min_version ))
54      return True;
55#endif
56
57   return False;
58}
59
60//---------------------------------------------------------------------------
61// main
62//---------------------------------------------------------------------------
63int main(int argc, char **argv)
64{
65   if ( argc < 2 ) {
66      fprintf( stderr, "usage: libc_test <libc-name> [<min-version>]\n" );
67      exit(3);             // Usage error.
68   }
69   if (go( argv[1], argv[2] )) {
70      return 0;            // Matched.
71   }
72
73   if ( 0 == strcmp ( argv[1], "glibc" ) ) {
74     return 1;             // Requested libc name known, but this isn't it.
75                           // Or it wasn't the minimum requested version.
76   }
77   return 2;               // Didn't match any known libc name.
78}
79