/* Copyright (C) ABRT Team Copyright (C) RedHat inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include "problem_utils.h" char * problem_get_argv0 (const char *cmdline) { char *ret; char **items; items = g_strsplit (cmdline, " ", -1); ret = g_strdup (items[0]); g_strfreev (items); return ret; } static void remove_quotes (char **args) { guint i; for (i = 0; args[i] != NULL; i++) { char **items; char *str; items = g_strsplit (args[i], "\"", -1); str = g_strjoinv (NULL, items); g_strfreev (items); g_free (args[i]); args[i] = str; } } static gboolean _is_it_file_arg (const char *s) { if (s == NULL) return FALSE; if (*s == '-') return FALSE; return TRUE; } static gboolean _is_it_url (const char *s) { if (s == NULL) return FALSE; if (strstr (s, "://")) return TRUE; return FALSE; } static gboolean compare_args (char **cmdargs, char **dcmdargs) { guint cargi, dargi; gboolean ret; /* Start at 1, as we already compared the binaries */ cargi = dargi = 1; while (dargi < g_strv_length(dcmdargs)) { if (g_str_equal (dcmdargs[dargi], "%f")) { if (cargi >= g_strv_length(cmdargs) || _is_it_file_arg(cmdargs[cargi])) { return FALSE; } else { dargi++; cargi++; } } else if (g_str_equal (dcmdargs[dargi], "%F")) { if (cargi >= g_strv_length(cmdargs) || _is_it_file_arg(cmdargs[cargi])) dargi++; else cargi++; } else if (g_str_equal (dcmdargs[dargi], "%u")) { if (cargi >= g_strv_length(cmdargs) || (!_is_it_url(cmdargs[cargi]) && !_is_it_file_arg(cmdargs[cargi]))) { return FALSE; } else { cargi++; dargi++; } } else if (g_str_equal (dcmdargs[dargi], "%U")) { if (cargi >= g_strv_length(cmdargs) || (!_is_it_url(cmdargs[cargi]) && !_is_it_file_arg(cmdargs[cargi]))) { dargi++; } else { cargi++; } } else if (g_str_equal (dcmdargs[dargi], "%i")) { //logging.debug("Unsupported Exec key %i"); dargi++; cargi += 2; } else if (g_str_equal (dcmdargs[dargi], "%c") || g_str_equal (dcmdargs[dargi], "%k")) { //logging.debug("Unsupported Exec key %s", dcmdargs[dargi]); dargi++; cargi++; } else { if (cargi >= g_strv_length(cmdargs) || !g_str_equal (dcmdargs[dargi], cmdargs[cargi])) return FALSE; dargi++; cargi++; } } ret = (cargi == g_strv_length(cmdargs) && dargi == g_strv_length(dcmdargs)); return ret; } static gboolean compare_binaries (char *cmd, const char *dcmd) { char *basename, *dbasename; gboolean ret = FALSE; if (g_strcmp0 (cmd, dcmd) == 0) return TRUE; basename = g_path_get_basename (cmd); dbasename = g_path_get_basename (dcmd); if (g_strcmp0 (basename, dbasename) == 0) ret = TRUE; g_free (basename); g_free (dbasename); return ret; } GAppInfo * problem_create_app_from_cmdline (const char *cmdline) { GAppInfo *app; GList *apps, *l; GList *shortlist; char *binary; char **cmdargs; binary = problem_get_argv0(cmdline); apps = g_app_info_get_all (); shortlist = NULL; app = NULL; for (l = apps; l != NULL; l = l->next) { GAppInfo *a = l->data; if (!g_app_info_should_show(a)) continue; if (!compare_binaries (binary, g_app_info_get_executable (a))) continue; shortlist = g_list_prepend (shortlist, a); } if (shortlist == NULL) { g_list_free_full (apps, g_object_unref); return NULL; } cmdargs = g_strsplit (cmdline, " ", -1); remove_quotes (cmdargs); for (l = shortlist; l != NULL; l = l->next) { GAppInfo *a = l->data; char **dcmdargs; const char *commandline = g_app_info_get_commandline (a); if (commandline == NULL) continue; dcmdargs = g_strsplit (commandline, " ", -1); remove_quotes (dcmdargs); if (compare_args (cmdargs, dcmdargs)) app = g_object_ref (a); g_strfreev (dcmdargs); if (app != NULL) break; } g_list_free (shortlist); g_list_free_full (apps, g_object_unref); return app; } #define GIO_LAUNCHED_DESKTOP_FILE_PREFIX "GIO_LAUNCHED_DESKTOP_FILE=" #define GIO_LAUNCHED_DESKTOP_FILE_PID_PREFIX "GIO_LAUNCHED_DESKTOP_FILE_PID=" GAppInfo * problem_create_app_from_env (const char **envp, pid_t pid) { GDesktopAppInfo *app; guint i; const char *desktop, *epid; if (envp == NULL) return NULL; if (pid < 0) return NULL; desktop = epid = NULL; for (i = 0; envp[i] != NULL; i++) { if (g_str_has_prefix (envp[i], GIO_LAUNCHED_DESKTOP_FILE_PREFIX)) desktop = envp[i] + strlen (GIO_LAUNCHED_DESKTOP_FILE_PREFIX); else if (g_str_has_prefix (envp[i], GIO_LAUNCHED_DESKTOP_FILE_PID_PREFIX)) epid = envp[i] + strlen (GIO_LAUNCHED_DESKTOP_FILE_PID_PREFIX); if (desktop && epid) break; } if (!desktop || !epid) return NULL; /* Verify PID */ if (atoi (epid) != pid) return NULL; if (*desktop == '/') app = g_desktop_app_info_new_from_filename (desktop); else app = g_desktop_app_info_new (desktop); return (GAppInfo *) app; }