// Compare given libc name and version number to system name and version. // Returns // - 0 if the libc name matches is at least the minimum version (if given). // - 1 if the libc name doesn't match or the version is lower than requested. // - 2 if the requested libc name isn't recognised. // - 3 if there was a usage error (it also prints an error message). #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __GLIBC__ #include <gnu/libc-version.h> #endif #define False 0 #define True 1 typedef int Bool; /* Assumes the versions are x.y.z, with y and z optional. */ static __attribute__((unused)) Bool matches_version(char *min_version) { int a1=0, a2=0, a3=0, g1=0, g2=0, g3=0; // 'a' = actual; 'g' = given const char *aversion; if (min_version == NULL) return True; // no version specified // get actual version number #ifdef __GLIBC__ aversion = gnu_get_libc_version(); #else aversion = "unknown"; #endif // We expect at least one number. if (sscanf(aversion, "%d.%d.%d", &a1, &a2, &a3) < 1) return False; // parse given version number. if (sscanf(min_version, "%d.%d.%d", &g1, &g2, &g3) < 1) return False; if (a1 > g1) return True; if (a1 < g1) return False; if (a2 > g2) return True; if (a2 < g2) return False; if (a3 >= g3) return True; return False; } static Bool go(char* libc, char *min_version) { #ifdef __GLIBC__ if ( 0 == strcmp( libc, "glibc" ) && matches_version( min_version )) return True; #endif return False; } //--------------------------------------------------------------------------- // main //--------------------------------------------------------------------------- int main(int argc, char **argv) { if ( argc < 2 ) { fprintf( stderr, "usage: libc_test <libc-name> [<min-version>]\n" ); exit(3); // Usage error. } if (go( argv[1], argv[2] )) { return 0; // Matched. } if ( 0 == strcmp ( argv[1], "glibc" ) ) { return 1; // Requested libc name known, but this isn't it. // Or it wasn't the minimum requested version. } return 2; // Didn't match any known libc name. }