summaryrefslogtreecommitdiff
path: root/modules/computer/os.c
diff options
context:
space:
mode:
authorLeandro Pereira <leandro@hardinfo.org>2017-07-09 12:16:04 -0700
committerLeandro Pereira <leandro@hardinfo.org>2017-07-09 12:24:49 -0700
commit42151ffb60e0f7b61041e4150bf5ca2c55ef5ae9 (patch)
treea3314f25c2fd2355f4423b9b99c69bef2c4ae0a6 /modules/computer/os.c
parente90fd9382e0ab43e9112ce464bb7a085ccd32fd0 (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.c90
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;
}