system-info.c 24.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* -*- mode: C; c-file-style: "stroustrup"; indent-tabs-mode: nil; -*- */

#include "system-info.h"

#include <glib.h>
#include <string.h>

#include "config.h"

struct _GbbSystemInfo {
    GObject parent;

    /* Hardware*/
    /*  Product */
    char *sys_vendor;
    char *product_version;
    char *product_name;

    /*  BIOS */
    char *bios_version;
    char *bios_date;
    char *bios_vendor;

24
25
26
27
    /*  CPU*/
    guint cpu_number;
    GStrv cpu_info;

28
29
    guint64 mem_total;

30
31
32
    /* GPU/Renderer */
    char *renderer;

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    /* Software */

    /* OS */
    char *os_type;
    char *os_kernel;

    /*  GNOME */
    char *gnome_version;
    char *gnome_distributor;
    char *gnome_date;
};

enum {
    PROP_0,

    PROP_SYS_VENDOR,
    PROP_PRODUCT_VERSION,
    PROP_PRODUCT_NAME,

    PROP_BIOS_VERSION,
    PROP_BIOS_VENDOR,
    PROP_BIOS_DATE,

56
57
    PROP_CPU_NUMBER,
    PROP_CPU_INFO,
58
    PROP_MEM_TOTAL,
59

60
61
    PROP_RENDERER,

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    PROP_OS_TYPE,
    PROP_OS_KERNEL,

    PROP_GNOME_VERSION,
    PROP_GNOME_DISTRIBUTOR,
    PROP_GNOME_DATE,

    PROP_LAST
};

G_DEFINE_TYPE (GbbSystemInfo, gbb_system_info, G_TYPE_OBJECT);

/* prototypes  */

static gboolean    load_gnome_version (char **version,
                                       char **distributor,
                                       char **date);
static char       *get_os_type        (void);
/*  */

static void
gbb_system_info_finalize(GbbSystemInfo *info)
{
    g_free(info->sys_vendor);
    g_free(info->product_version);
    g_free(info->product_name);

    g_free(info->bios_version);
    g_free(info->bios_date);
    g_free(info->bios_vendor);

93
94
    g_strfreev(info->cpu_info);

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    g_free(info->os_type);
    g_free(info->os_kernel);

    g_free(info->gnome_version);
    g_free(info->gnome_distributor);
    g_free(info->gnome_date);

    G_OBJECT_CLASS(gbb_system_info_parent_class)->finalize(G_OBJECT (info));
}

static void
gbb_system_info_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
    GbbSystemInfo *info = GBB_SYSTEM_INFO(object);

    switch (prop_id) {
    case PROP_SYS_VENDOR:
        g_value_set_string(value, info->sys_vendor);
        break;

    case PROP_PRODUCT_VERSION:
        g_value_set_string(value, info->product_version);
        break;

    case PROP_PRODUCT_NAME:
        g_value_set_string(value, info->product_name);
        break;

    case PROP_BIOS_VERSION:
        g_value_set_string(value, info->bios_version);
        break;

    case PROP_BIOS_DATE:
        g_value_set_string(value, info->bios_date);
        break;

    case PROP_BIOS_VENDOR:
        g_value_set_string(value, info->bios_vendor);
        break;

135
136
137
138
139
140
141
142
    case PROP_CPU_NUMBER:
        g_value_set_uint(value, info->cpu_number);
        break;

    case PROP_CPU_INFO:
        g_value_set_boxed(value, info->cpu_info);
        break;

143
144
145
146
    case PROP_MEM_TOTAL:
        g_value_set_uint64(value, info->mem_total);
        break;

147
148
149
150
    case PROP_RENDERER:
        g_value_set_string(value, info->renderer);
        break;

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    case PROP_OS_TYPE:
        g_value_set_string(value, info->os_type);
        break;

    case PROP_OS_KERNEL:
        g_value_set_string(value, info->os_kernel);
        break;

    case PROP_GNOME_VERSION:
        g_value_set_string(value, info->gnome_version);
        break;

    case PROP_GNOME_DISTRIBUTOR:
        g_value_set_string(value, info->gnome_distributor);
        break;

    case PROP_GNOME_DATE:
        g_value_set_string(value, info->gnome_date);
        break;
    }

}

static void
gbb_system_info_class_init (GbbSystemInfoClass *klass)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
    gobject_class->finalize = (GObjectFinalizeFunc) gbb_system_info_finalize;
    gobject_class->get_property = gbb_system_info_get_property;

    g_object_class_install_property (gobject_class,
                                     PROP_SYS_VENDOR,
                                     g_param_spec_string ("sys-vendor",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_PRODUCT_VERSION,
                                     g_param_spec_string ("product-version",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_PRODUCT_NAME,
                                     g_param_spec_string ("product-name",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_BIOS_VERSION,
                                     g_param_spec_string ("bios-version",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_BIOS_DATE,
                                     g_param_spec_string ("bios-date",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_BIOS_VENDOR,
                                     g_param_spec_string ("bios-vendor",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
217
218
219
220
221
222
223
224
225
226
227
228
    g_object_class_install_property (gobject_class,
                                     PROP_CPU_NUMBER,
                                     g_param_spec_uint ("cpu-number",
                                                        NULL, NULL,
                                                        0, G_MAXUINT, 0,
                                                        G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_CPU_INFO,
                                     g_param_spec_boxed("cpu-info",
                                                        NULL, NULL,
                                                        G_TYPE_STRV,
                                                        G_PARAM_READABLE));
229
230
231
232
233
234
    g_object_class_install_property (gobject_class,
                                     PROP_MEM_TOTAL,
                                     g_param_spec_uint64 ("mem-total",
                                                          NULL, NULL,
                                                          0, G_MAXUINT64, 0,
                                                          G_PARAM_READABLE));
235
236
237
238
239
240
    g_object_class_install_property (gobject_class,
                                     PROP_RENDERER,
                                     g_param_spec_string ("renderer",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    g_object_class_install_property (gobject_class,
                                     PROP_OS_KERNEL,
                                     g_param_spec_string ("os-kernel",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_OS_TYPE,
                                     g_param_spec_string ("os-type",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_GNOME_VERSION,
                                     g_param_spec_string ("gnome-version",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_GNOME_DISTRIBUTOR,
                                     g_param_spec_string ("gnome-distributor",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
    g_object_class_install_property (gobject_class,
                                     PROP_GNOME_DATE,
                                     g_param_spec_string ("gnome-date",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_READABLE));
}

static char *
read_sysfs_string(const char *node)
{
    gboolean ok;
    char *contents = NULL;
    GError *error = NULL;
    gsize len;

    ok = g_file_get_contents (node,
                              &contents,
                              &len,
                              &error);

    if (!ok) {
        g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
                          "MESSAGE_ID", "3a2690a163c5465bb9ba0cab229bf3cf",
                          "MESSAGE", "Reading sys file '%s' failed: %s.",
                          node, error->message);
        g_error_free(error);
        return g_strdup("Unknown");
    }

    if (len > 1 && contents[len-1] == '\n') {
        contents[len-1] = '\0';
    }

    return contents;
}

static void
read_dmi_info(GbbSystemInfo *info)
{
    info->bios_version = read_sysfs_string("/sys/devices/virtual/dmi/id/bios_version");
    info->bios_date = read_sysfs_string("/sys/devices/virtual/dmi/id/bios_date");
    info->bios_vendor = read_sysfs_string("/sys/devices/virtual/dmi/id/bios_vendor");

    info->product_name = read_sysfs_string("/sys/devices/virtual/dmi/id/product_name");
    info->product_version = read_sysfs_string("/sys/devices/virtual/dmi/id/product_version");

    info->sys_vendor = read_sysfs_string("/sys/devices/virtual/dmi/id/sys_vendor");
}

static char *
read_kernel_version(void)
{
    g_autofree char *data = read_sysfs_string("/proc/version");
    g_auto(GStrv) comps = NULL;

    if (data == NULL) {
        return g_strdup("Unknown");
    }

    comps = g_strsplit(data, " ", 4);
    if (g_strv_length (comps) < 3) {
        char *tmp = data;
        data = NULL;
        return tmp;
    }

    return g_strdup(comps[2]);
}

335
336
337
338
339
340
341
342
343
static void
report_format_error(const char *filename, const char *message)
{
    g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
                      "MESSAGE_ID", "3a2690a163c5465bb9ba0cab229bf3cf",
                      "MESSAGE", "Format error: while parsing '%s': %s.",
                      filename, message);
}

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
static GStrv
read_cpu_info(guint *ncpus)
{
    g_autofree char *data = read_sysfs_string("/proc/cpuinfo");
    g_autoptr(GHashTable) cpus = NULL;
    g_auto(GStrv) kv = NULL;
    GStrv models = NULL;
    gsize i, n = 0;
    gpointer key, val;
    GHashTableIter iter;

    if (data == NULL) {
        models = g_new(char *, 2);
        models[0] = g_strdup("Unknown");
        models[1] = NULL;
        *ncpus = 1;
        return models;
    }

    cpus = g_hash_table_new (g_str_hash, g_str_equal);

    kv = g_strsplit(data, "\n", -1);
    for (i = 0; i < g_strv_length(kv); i++) {
        const char *entry = kv[i];
        const char *pos;
        if (!g_str_has_prefix(entry, "model name")) {
            continue;
        }

        pos = g_strstr_len(entry, -1, ":");
        if (pos == NULL) {
375
376
            report_format_error("/proc/cpuinfo", "expected a ':'");
            continue;
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
        }
        pos++;

        while (*pos == ' ' && *pos != '\n') {
            pos++;
        }

        val = g_hash_table_lookup(cpus, pos);
        if (val == NULL) {
            g_hash_table_insert(cpus, (gpointer) pos, GINT_TO_POINTER(1));
        } else {
            val = GINT_TO_POINTER(GPOINTER_TO_INT(val) + 1);
            g_hash_table_replace(cpus, (gpointer) pos, val);
        }
    }

    n = i = 0;
    g_hash_table_iter_init (&iter, cpus);
    models = (GStrv) g_new(char *, g_hash_table_size(cpus) + 1);
    while (g_hash_table_iter_next (&iter, &key, &val)) {
        int k = GPOINTER_TO_INT(val);
        models[i] = g_strdup_printf("%s [%d]", (char *) key, k);
        n += k;
        i++;
    }
    models[i] = NULL;
    *ncpus = n;
    return models;
}
406

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
static guint64
read_mem_info(void)
{
    g_autofree char *data = read_sysfs_string("/proc/meminfo");
    g_auto(GStrv) kv = NULL;
    const char *total = NULL;
    const char *pos;
    char *endptr;
    guint64 res;
    guint i;

    if (data == NULL) {
        return 0;
    }

    kv = g_strsplit(data, "\n", -1);
    for (i = 0; i < g_strv_length(kv); i++) {
        if (g_str_has_prefix(kv[i], "MemTotal:")) {
            total = kv[i];
            break;
        }
    }

    if (total == NULL) {
        report_format_error("/proc/meminfo", "'MemTotal' not found");
        return 0;
    }

    pos = g_strstr_len(total, -1, ":");
    if (pos == NULL) {
        report_format_error("/proc/meminfo", "MemTotal: expected a ':'");
        return 0;
    }

    do {
        pos++;
    } while (*pos != '\0' && *pos == ' ');

    res = g_ascii_strtoull(pos, &endptr, 10);

    if (pos == endptr) {
        report_format_error("/proc/meminfo", "MemTotal: could not parse number");
        return 0;
    }

    return res;
}

455
456
457
static char *
get_renderer_info (void)
{
458
    g_autoptr(GDBusProxy) proxy = NULL;
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
    g_autoptr(GVariant) var = NULL;
    g_autoptr(GError) error = NULL;
    const char *renderer = "Unknown";

    proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION,
                                          G_DBUS_PROXY_FLAGS_NONE,
                                          NULL,
                                          "org.gnome.SessionManager",
                                          "/org/gnome/SessionManager",
                                          "org.gnome.SessionManager",
                                          NULL, &error);

    if (error != NULL) {
        g_warning("Failed to connect to org.gnome.SessionManager: %s",
                  error->message);
        goto out;
    }

    var = g_dbus_proxy_get_cached_property(proxy, "Renderer");
    if (!var) {
        g_warning("Failed to obtain 'Renderer' property from org.gnome.SessionManager");
        goto out;
    }

    renderer = g_variant_get_string(var, NULL);

out:
    return g_strstrip(g_strdup(renderer));
}


490
491
492
493
494
495
496
497
static void gbb_system_info_init (GbbSystemInfo *info)
{
    read_dmi_info(info);
    load_gnome_version(&info->gnome_version,
                       &info->gnome_distributor,
                       &info->gnome_date);
    info->os_type = get_os_type();
    info->os_kernel = read_kernel_version();
498
    info->cpu_info = read_cpu_info(&info->cpu_number);
499
    info->mem_total = read_mem_info();
500
    info->renderer = get_renderer_info();
501
502
503
504
505
506
507
508
509
510
}

GbbSystemInfo *
gbb_system_info_acquire ()
{
    GbbSystemInfo *info;
    info = (GbbSystemInfo *) g_object_new(GBB_TYPE_SYSTEM_INFO, NULL);
    return info;
}

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
void
gbb_system_info_to_json (const GbbSystemInfo *info, JsonBuilder *builder)
{
    json_builder_begin_object(builder);
    json_builder_set_member_name(builder, "hardware");
    {
        json_builder_begin_object(builder);
        json_builder_set_member_name(builder, "vendor");
        json_builder_add_string_value(builder, info->sys_vendor);
        json_builder_set_member_name(builder, "version");
        json_builder_add_string_value(builder, info->product_version);
        json_builder_set_member_name(builder, "name");
        json_builder_add_string_value(builder, info->product_name);

        json_builder_set_member_name(builder, "bios");
        {
            json_builder_begin_object(builder);
            json_builder_set_member_name(builder, "version");
            json_builder_add_string_value(builder, info->bios_version);
            json_builder_set_member_name(builder, "date");
            json_builder_add_string_value(builder, info->bios_date);
            json_builder_set_member_name(builder, "vendor");
            json_builder_add_string_value(builder, info->bios_vendor);
            json_builder_end_object(builder);
        }
536
537
538
539
540
541
542
543
544
545
546
547
548
549

        json_builder_set_member_name(builder, "cpu");
        {
            json_builder_begin_object(builder);
            json_builder_set_member_name(builder, "number");
            json_builder_add_int_value(builder, info->cpu_number);
            json_builder_set_member_name(builder, "info");
            json_builder_begin_array(builder);
            for (int i = 0; i < g_strv_length(info->cpu_info); i++) {
                json_builder_add_string_value(builder, info->cpu_info[i]);
            }
            json_builder_end_array(builder);
            json_builder_end_object(builder);
        }
550

551
552
553
        json_builder_set_member_name(builder, "renderer");
        json_builder_add_string_value(builder, info->renderer);

554
555
556
557
558
559
560
561
        json_builder_set_member_name(builder, "memory");
        {
            json_builder_begin_object(builder);
            json_builder_set_member_name(builder, "total");
            json_builder_add_int_value(builder, info->mem_total);
            json_builder_end_object(builder);
        }

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
        json_builder_end_object(builder);
    }
    json_builder_set_member_name(builder, "software");
    {
        json_builder_begin_object(builder);
        json_builder_set_member_name(builder, "os");
        {
            json_builder_begin_object(builder);
            json_builder_set_member_name(builder, "type");
            json_builder_add_string_value(builder, info->os_type);
            json_builder_set_member_name(builder, "kernel");
            json_builder_add_string_value(builder, info->os_kernel);
            json_builder_end_object(builder);
        }
        json_builder_set_member_name(builder, "gnome");
        {
            json_builder_begin_object(builder);
            json_builder_set_member_name(builder, "version");
            json_builder_add_string_value(builder, info->gnome_version);
            json_builder_set_member_name(builder, "distributor");
            json_builder_add_string_value(builder, info->gnome_distributor);
            json_builder_set_member_name(builder, "date");
            json_builder_add_string_value(builder, info->gnome_date);
            json_builder_end_object(builder);
        }
        json_builder_end_object(builder);
    }
    json_builder_end_object(builder);
}

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
/* GNOME system info */
/* Everything below has been mostly borrowed from
 * gnome-control-center/panels/info/cc-info-panel.c
 * with some minor modifications, and reformatting.
 * License: GPLv2+
 * Copyright (C) 2010 Red Hat, Inc
 * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
 */
typedef struct {
    char *major;
    char *minor;
    char *micro;
    char *distributor;
    char *date;
    char **current;
} VersionData;

static void
version_start_element_handler (GMarkupParseContext      *ctx,
                               const char               *element_name,
                               const char              **attr_names,
                               const char              **attr_values,
                               gpointer                  user_data,
                               GError                  **error)
{
    VersionData *data = user_data;

    if (g_str_equal (element_name, "platform"))
        data->current = &data->major;
    else if (g_str_equal (element_name, "minor"))
        data->current = &data->minor;
    else if (g_str_equal (element_name, "micro"))
        data->current = &data->micro;
    else if (g_str_equal (element_name, "distributor"))
        data->current = &data->distributor;
    else if (g_str_equal (element_name, "date"))
        data->current = &data->date;
    else
        data->current = NULL;
}

static void
version_end_element_handler (GMarkupParseContext      *ctx,
                             const char               *element_name,
                             gpointer                  user_data,
                             GError                  **error)
{
    VersionData *data = user_data;
    data->current = NULL;
}

static void
version_text_handler (GMarkupParseContext *ctx,
                      const char          *text,
                      gsize                text_len,
                      gpointer             user_data,
                      GError             **error)
{
    VersionData *data = user_data;
    if (data->current != NULL)
        *data->current = g_strstrip (g_strdup (text));
}

static gboolean
load_gnome_version (char **version,
                    char **distributor,
                    char **date)
{
    GMarkupParser version_parser = {
        version_start_element_handler,
        version_end_element_handler,
        version_text_handler,
        NULL,
        NULL,
    };
    GError              *error;
    GMarkupParseContext *ctx;
    char                *contents;
    gsize                length;
    VersionData         *data;
    gboolean             ret;

674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
    ret = FALSE;

    error = NULL;
    if (!g_file_get_contents (DATADIR "/gnome/gnome-version.xml",
                              &contents,
                              &length,
                              &error))
        return FALSE;

    data = g_new0 (VersionData, 1);
    ctx = g_markup_parse_context_new (&version_parser, 0, data, NULL);

    if (!g_markup_parse_context_parse (ctx, contents, length, &error)) {
        g_warning ("Invalid version file: '%s'", error->message);
    } else {
        if (version != NULL)
            *version = g_strdup_printf ("%s.%s.%s", data->major, data->minor, data->micro);
        if (distributor != NULL)
            *distributor = g_strdup (data->distributor);
        if (date != NULL)
            *date = g_strdup (data->date);

        ret = TRUE;
697
698
    }

699
700
701
702
703
704
705
706
    g_markup_parse_context_free (ctx);
    g_free (data->major);
    g_free (data->minor);
    g_free (data->micro);
    g_free (data->distributor);
    g_free (data->date);
    g_free (data);
    g_free (contents);
707

708
    return ret;
709
710
711
712
713
};

static GHashTable*
get_os_info (void)
{
714
715
716
717
718
    GHashTable *hashtable = NULL;
    g_autofree gchar *buffer = NULL;
    g_auto(GStrv) lines = NULL;
    g_autoptr(GError) error = NULL;
    gint i;
719

720
721
722
723
    if (! g_file_get_contents ("/etc/os-release", &buffer, NULL, &error)) {
        g_warning("Failed to read '/etc/os-release': %s", error->message);
        return NULL;
    }
724

725
    lines = g_strsplit (buffer, "\n", -1);
726

727
728
    for (i = 0; lines[i] != NULL; i++) {
        gchar *delimiter, *key, *value;
729

730
731
732
        /* Initialize the hash table if needed */
        if (!hashtable)
            hashtable = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
733

734
735
736
        delimiter = strstr (lines[i], "=");
        value = NULL;
        key = NULL;
737

738
739
        if (delimiter != NULL) {
            gint size;
740

741
            key = g_strndup (lines[i], delimiter - lines[i]);
742

743
744
            /* Jump the '=' */
            delimiter += strlen ("=");
745

746
747
748
            /* Eventually jump the ' " ' character */
            if (g_str_has_prefix (delimiter, "\""))
                delimiter += strlen ("\"");
749

750
            size = strlen (delimiter);
751

752
753
754
            /* Don't consider the last ' " ' too */
            if (g_str_has_suffix (delimiter, "\""))
                size -= strlen ("\"");
755

756
            value = g_strndup (delimiter, size);
757

758
            g_hash_table_insert (hashtable, key, value);
759
760
761
762
763
764
765
766
767
768
769
        }
    }

    return hashtable;
}

static char *
get_os_type (void)
{
    GHashTable *os_info;
    gchar *name, *result, *build_id;
770
    char base[255];
771
772
773
774
775
776
777
778
779
780
    int bits;

    os_info = get_os_info ();

    if (!os_info)
        return NULL;

    name = g_hash_table_lookup (os_info, "PRETTY_NAME");
    build_id = g_hash_table_lookup (os_info, "BUILD_ID");

781
782
783
784
    bits = GLIB_SIZEOF_VOID_P == 8 ? 64 : 32;

    if (name)
        g_snprintf(base, sizeof(base), "%s %d-bit", name, bits);
785
    else
786
        g_snprintf(base, sizeof(base), "%d-bit", bits);
787
788

    if (build_id) {
789
790
791
        char idstr[255];
        g_snprintf(idstr, sizeof(idstr), " (Build ID: %s)", build_id);
        result = g_strconcat(base, idstr, NULL);
792
    } else {
793
        result = g_strdup(base);
794
795
796
797
798
799
    }

    g_clear_pointer (&os_info, g_hash_table_destroy);

    return result;
}