Ejemplo n.º 1
0
void gfire_process_list_update(gfire_process_list *p_list)
{
    if(!p_list)
        return;

    gfire_process_list_clear(p_list);

    acquirePrivileges();

    PROCESSENTRY32 pe;
    memset(&pe, 0, sizeof(pe));

    pe.dwSize = sizeof(pe);

    HANDLE hProcSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(!hProcSnapShot)
        return;

    if(!Process32First(hProcSnapShot, &pe))
    {
        CloseHandle(hProcSnapShot);
        return;
    }

    do
    {
        if(pe.th32ProcessID > 0)
        {
#ifdef DEBUG
            purple_debug_info("gfire", "detection: probing %s\n", pe.szExeFile);
#endif // DEBUG

            gchar *cmdline = NULL;
            gchar *executable_file = NULL;
            if(!get_process_cmdline(pe.th32ProcessID, &executable_file, &cmdline))
                continue;

#ifdef DEBUG
            purple_debug_info("gfire", "executable file: %s\n", executable_file);
            purple_debug_info("gfire", "cmdline: %s\n", cmdline);
#endif // DEBUG

            // Extract the args from the command line
            gchar *args = strstr(g_strstrip(cmdline), pe.szExeFile);
            if(args)
            {
                args += strlen(pe.szExeFile);
                if(args[0] == 0)
                    args = NULL;
                // If the first char behind the process' name is ", strip it
                else if(args[0] == '\"')
                {
                    args++;
                    if(args[0] == 0)
                        args = NULL;
                }
            }

            if(args)
            {
                g_strstrip(args);
#ifdef DEBUG
                purple_debug_info("gfire", "args: %s\n", args);
#endif // DEBUG
            }

            // Add the process
            process_info *info = gfire_process_info_new(executable_file, pe.th32ProcessID, args);
            g_free(cmdline);
            g_free(executable_file);

            p_list->processes = g_list_append(p_list->processes, info);
        }
    } while(Process32Next(hProcSnapShot, &pe));

    CloseHandle(hProcSnapShot);
}
void gfire_process_list_update(gfire_process_list *p_list)
{
	if(!p_list)
		return;

#ifdef DEBUG_VERBOSE
	purple_debug_info("gfire", "gfire_process_list_update: TRACE\n");
#endif // DEBUG_VERBOSE

	gfire_process_list_clear(p_list);

	DIR *proc = opendir("/proc");
	struct dirent *proc_dirent;

	if(!proc)
	{
		purple_debug_error("gfire", "gfire_process_list_update: opendir() failed\n");
		return;
	}

	while((proc_dirent = readdir(proc)))
	{
#ifdef DEBUG_VERBOSE
		purple_debug_info("gfire", "gfire_process_list_update: checking: \"%s\"\n", proc_dirent->d_name);
#endif // DEBUG_VERBOSE

		// Check if we got a valid process dir
		gboolean dir_valid = TRUE;
		int i = 0;
		for(; i < strlen(proc_dirent->d_name); i++)
		{
			if(!g_ascii_isdigit(proc_dirent->d_name[i]))
			{
				dir_valid = FALSE;
				break;
			}
		}
		if(!dir_valid)
		{
#ifdef DEBUG_VERBOSE
			purple_debug_error("gfire", "gfire_process_list_update: \"%s\" is no valid process directory\n",
							   proc_dirent->d_name);
#endif // DEBUG_VERBOSE
			continue;
		}

		gchar *proc_path = g_strdup_printf("/proc/%s", proc_dirent->d_name);

		// Check if it is a directory and owned by the current user
		struct stat process_stat;
		if(stat(proc_path, &process_stat) == -1)
		{
#ifdef DEBUG
			purple_debug_error("gfire", "gfire_process_list_update: stat(\"%s\") failed\n", proc_path);
#endif // DEBUG
			g_free(proc_path);
			continue;
		}

		// Don't check current process if not owned
		if(geteuid() != process_stat.st_uid || !S_ISDIR(process_stat.st_mode))
		{
#ifdef DEBUG_VERBOSE
			purple_debug_error("gfire", "gfire_process_list_update: \"%s\" is not owned by current user\n",
							   proc_dirent->d_name);
#endif // DEBUG_VERBOSE
			g_free(proc_path);
			continue;
		}

		// Get process id
		guint32 process_id;
		sscanf(proc_dirent->d_name, "%u", &process_id);

		// Get process exe
		const gchar *process_exe = get_proc_exe(proc_path);
		if(!process_exe)
		{
			g_free(proc_path);
			continue;
		}

		// Get process' command line
		gchar *process_cmd = NULL;
		gchar *process_args = NULL;
		get_proc_cmdline(&process_cmd, &process_args, proc_path);

		gchar *process_real_exe = NULL;
		// Different behaviour for Wine processes
		if(strstr(process_exe, "wine-preloader"))
		{
#ifdef DEBUG_VERBOSE
			purple_debug_misc("gfire", "gfire_process_list_update: WINE game! Starting WINE based detection...\n");
#endif // DEBUG_VERBOSE

			// Get Wine prefix for winepath
			GHashTable *environ = get_environ(proc_path);
			const gchar *prefix = NULL;
			if(environ)
				prefix = g_hash_table_lookup(environ, "WINEPREFIX");

#ifdef DEBUG_VERBOSE
			if(prefix)
				purple_debug_misc("gfire", "gfire_process_list_update: WINEPREFIX=\"%s\"\n", prefix);
			else
				purple_debug_misc("gfire", "gfire_process_list_update: no WINEPREFIX set\n");
#endif // DEBUG_VERBOSE

			// Get process name using winepath
			const gchar *real_path = get_winepath(prefix, process_cmd);

			// Some error occured
			if(!real_path)
			{
				g_hash_table_destroy(environ);
				g_free(process_cmd);
				g_free(process_args);
				g_free(proc_path);
				continue;
			}

#ifdef DEBUG_VERBOSE
			purple_debug_misc("gfire", "gfire_process_list_update: Canonicalizing path: \"%s\"\n", real_path);
#endif // DEBUG_VERBOSE

			// Get the physical path
#ifdef GF_OS_BSD
			gchar phys_path_buf[PATH_MAX];
			gchar *phys_path = realpath(real_path, phys_path_buf);
#else
			gchar *phys_path = canonicalize_file_name(real_path);
#endif // GF_OS_BSD

			// We might have only the executables name, try with adding the CWD
			if(!phys_path)
			{
#ifdef DEBUG_VERBOSE
				purple_debug_misc("gfire", "gfire_process_list_update: No such file :'( Trying to prepend the CWD...\n");
#endif // DEBUG_VERBOSE
				const gchar *cwd = get_proc_cwd(environ, proc_path);
				// Okay, we really can't do anything about it
				if(!cwd)
				{
					g_hash_table_destroy(environ);
					g_free(process_cmd);
					g_free(process_args);
					g_free(proc_path);
					continue;
				}

				gchar *full_cmd = g_strdup_printf("%s/%s", cwd, process_cmd);
				g_free(process_cmd);

#ifdef DEBUG_VERBOSE
				purple_debug_misc("gfire", "gfire_process_list_update: Trying the following path: \"%s\"\n", full_cmd);
#endif // DEBUG_VERBOSE

				real_path = get_winepath(prefix, full_cmd);
				g_free(full_cmd);
				g_hash_table_destroy(environ);

				// Again some error :'(
				if(!real_path)
				{
					g_free(process_args);
					g_free(proc_path);
					continue;
				}

#ifdef DEBUG_VERBOSE
			purple_debug_misc("gfire", "gfire_process_list_update: Canonicalizing path: \"%s\"\n", real_path);
#endif // DEBUG_VERBOSE

				// Try again
#ifdef GF_OS_BSD
				phys_path = realpath(real_path, phys_path_buf);
#else
				phys_path = canonicalize_file_name(real_path);
#endif // GF_OS_BSD

				// Okay...we lost
				if(!phys_path)
				{
#ifdef DEBUG_VERBOSE
					purple_debug_error("gfire", "gfire_process_list_update: No such file, we give up...\n");
#endif // DEBUG_VERBOSE
					g_free(process_args);
					g_free(proc_path);
					continue;
				}
			}
			else
			{
				g_hash_table_destroy(environ);
				g_free(process_cmd);
			}

			process_real_exe = phys_path;
		}
		else
		{
			g_free(process_cmd);
			process_real_exe = g_strdup(process_exe);
		}

		// Add process to list
		process_info *info = gfire_process_info_new(process_real_exe, process_id, process_args);
#ifdef DEBUG_VERBOSE
		purple_debug_info("gfire", "gfire_process_list_update: added process: pid=%u exe=\"%s\" args=\"%s\"\n",
						  process_id, process_real_exe, process_args);
#endif // DEBUG_VERBOSE
		p_list->processes = g_list_append(p_list->processes, info);

#ifndef GF_OS_BSD
		g_free(process_real_exe);
#endif // !GF_OS_BSD
		g_free(process_args);
		g_free(proc_path);
	}

	closedir(proc);
}