/* * This file is part of Cockpit. * * Copyright (C) 2015 Red Hat, Inc. * * Cockpit is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * Cockpit is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Cockpit; If not, see . */ #include "cockpitsystem.h" #include #include #include #include #include #include #include #include /* Used to override from tests */ const gchar *cockpit_system_proc_base = "/proc"; static const gchar *os_release_fields[] = { "NAME", "VERSION", "ID", "VERSION_ID", "PRETTY_NAME", "VARIANT", "VARIANT_ID", "CPE_NAME", NULL }; const gchar ** cockpit_system_os_release_fields (void) { return os_release_fields; } GHashTable * cockpit_system_load_os_release (void) { GError *error = NULL; GHashTable *result = NULL; gchar *contents = NULL; gsize len; gchar **lines = NULL; guint n; gchar *line, *val; g_file_get_contents ("/etc/os-release", &contents, &len, &error); if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { g_clear_error (&error); g_file_get_contents ("/usr/lib/os-release", &contents, &len, &error); } if (error) { g_message ("error loading contents of os-release: %s", error->message); goto out; } result = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); lines = g_strsplit (contents, "\n", -1); for (n = 0; lines != NULL && lines[n] != NULL; n++) { line = lines[n]; val = strchr (line, '='); if (val) { *val = '\0'; val++; /* Remove quotes from value */ len = strlen (val); if (len && val[0] == '\"' && val[len - 1] == '\"') { val[len - 1] = '\0'; val++; } g_hash_table_replace (result, line, val); } else { g_free (line); } } out: g_clear_error (&error); g_free (lines); g_free (contents); return result; } guint64 cockpit_system_process_start_time (void) { GError *error = NULL; gchar *filename = NULL; gchar *contents = NULL; gchar **tokens = NULL; gchar *endp = NULL; size_t length; guint num_tokens; gchar *p; guint64 start_time = 0; filename = g_strdup_printf ("%s/%d/stat", cockpit_system_proc_base, getpid ()); if (!g_file_get_contents (filename, &contents, &length, &error)) { g_warning ("couldn't read start time: %s", error->message); goto out; } /* * Start time is the token at index 19 after the '(process name)' entry - since only this * field can contain the ')' character, search backwards for this */ p = strrchr (contents, ')'); if (p == NULL) { g_warning ("error parsing stat command: %s", filename); goto out; } p += 2; /* skip ') ' */ if (p - contents >= (int) length) { g_warning ("error parsing stat command: %s", filename); goto out; } tokens = g_strsplit (p, " ", 0); num_tokens = g_strv_length (tokens); if (num_tokens < 20) { g_warning ("error parsing stat tokens: %s", filename); goto out; } start_time = g_ascii_strtoull (tokens[19], &endp, 10); if (!endp || endp == tokens[19] || *endp) { start_time = 0; g_warning ("error parsing start time: %s'", filename); goto out; } out: if (error) g_error_free (error); g_strfreev (tokens); g_free (filename); g_free (contents); return start_time; } char * cockpit_system_session_id (void) { char *session_id; pid_t pid; int res; pid = getppid (); res = sd_pid_get_session (pid, &session_id); if (res == 0) { return session_id; } else { if (res != -ENODATA && res != -ENXIO) g_message ("could not look up session id for bridge process: %u: %s", pid, g_strerror (-res)); return NULL; } }