diff options
author | Leandro Pereira <leandro@hardinfo.org> | 2017-07-09 12:16:04 -0700 |
---|---|---|
committer | Leandro Pereira <leandro@hardinfo.org> | 2017-07-09 12:24:49 -0700 |
commit | 42151ffb60e0f7b61041e4150bf5ca2c55ef5ae9 (patch) | |
tree | a3314f25c2fd2355f4423b9b99c69bef2c4ae0a6 /modules/computer/os.c | |
parent | e90fd9382e0ab43e9112ce464bb7a085ccd32fd0 (diff) |
Use g_spawn_command_line_sync() to detect libc version
No need to invoke the shell using popen(), and have it redirect
output from stderr to stdout in the diet libc case. This also
hides possible errors during detection.
Diffstat (limited to 'modules/computer/os.c')
-rw-r--r-- | modules/computer/os.c | 90 |
1 files changed, 52 insertions, 38 deletions
diff --git a/modules/computer/os.c b/modules/computer/os.c index 0de41a57..26427c38 100644 --- a/modules/computer/os.c +++ b/modules/computer/os.c @@ -24,50 +24,64 @@ static gchar * get_libc_version(void) { - FILE *testp; - gchar buf[256], *p, *ver_str = NULL, *ret = NULL; - - struct { - const char *test_cmd; - const char *match_str; - const char *lib_name; - int try_ver_str; + static const struct { + const char *test_cmd; + const char *match_str; + const char *lib_name; + gboolean try_ver_str; + gboolean use_stderr; } libs[] = { - { "ldconfig -V", "GLIBC", "GNU C Library", 1 }, - { "ldconfig -v", "uClibc", "uClibc or uClibc-ng", 0 }, - { "diet 2>&1", "diet version", "diet libc", 1 }, - { NULL, NULL, NULL, 0 }, + { "ldconfig -V", "GLIBC", "GNU C Library", TRUE, FALSE}, + { "ldconfig -V", "GNU libc", "GNU C Library", TRUE, FALSE}, + { "ldconfig -v", "uClibc", "uClibc or uClibc-ng", FALSE, FALSE}, + { "diet", "diet version", "diet libc", TRUE, TRUE}, + { NULL, NULL, NULL, 0}, }; - int i = 0; - while (libs[i].test_cmd != NULL) { - memset(buf, 0, 256); - testp = popen(libs[i].test_cmd, "r"); - if (testp) { - (void)fgets(buf, 255, testp); - pclose(testp); - - /* limit to first line */ - p = strstr(buf, "\n"); if (p) *p = 0; - - if ( strstr(buf, libs[i].match_str) ) { - if (libs[i].try_ver_str) { - ver_str = strstr(buf, " "); /* skip the first word, likely "ldconfig" or name of utility */ - if (ver_str) ver_str++; - } - break; - } + gchar *ver_str = NULL, *to_free = NULL, *ret; + int i; + + for (i = 0; libs[i].test_cmd; i++) { + gboolean spawned; + gchar *out, *err, *p; + + spawned = g_spawn_command_line_sync(libs[i].test_cmd, + &out, &err, NULL, NULL); + if (!spawned) + continue; + + if (libs[i].use_stderr) { + p = strend(err, '\n'); + g_free(out); + to_free = err; + } else { + p = strend(out, '\n'); + g_free(err); + to_free = out; + } + + if (!strstr(p, libs[i].match_str)) { + g_free(to_free); + continue; + } + + if (libs[i].try_ver_str) { + /* skip the first word, likely "ldconfig" or name of utility */ + ver_str = strstr(p, " "); + if (ver_str) + ver_str++; } - i++; + + break; } if (libs[i].try_ver_str && ver_str) - ret = g_strdup_printf("%s / %s", libs[i].lib_name, ver_str ); - else { - if (libs[i].lib_name != NULL) - ret = g_strdup(libs[i].lib_name); - else - ret = g_strdup(_("Unknown")); - } + ret = g_strdup_printf("%s / %s", libs[i].lib_name, ver_str); + else if (libs[i].lib_name) + ret = g_strdup(libs[i].lib_name); + else + ret = g_strdup(_("Unknown")); + + g_free(to_free); return ret; } |