mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-03 06:46:38 -04:00
Harden session launch command recovery
This commit is contained in:
parent
818f80c068
commit
e2b63a06d7
3 changed files with 380 additions and 83 deletions
|
|
@ -82,10 +82,14 @@ idleinhibit_ignore_visible=0
|
||||||
# Disabled by default to preserve Mango's current behavior.
|
# Disabled by default to preserve Mango's current behavior.
|
||||||
# Minimized restore is currently unsupported.
|
# Minimized restore is currently unsupported.
|
||||||
# Restore expects target outputs to already exist before clients map.
|
# Restore expects target outputs to already exist before clients map.
|
||||||
|
# Mango only restores from a trusted session file owned by the current user
|
||||||
|
# and not writable by group or others.
|
||||||
session_restore=0
|
session_restore=0
|
||||||
# Relaunch mapping used when Mango cannot infer a launch command from a client.
|
# Optional relaunch override used when Mango cannot recover a suitable launcher.
|
||||||
# Format: session_launch=app_id|command
|
# Format: session_launch=app_id|command
|
||||||
# or: session_launch=app_id|title|command
|
# or: session_launch=app_id|title|command
|
||||||
|
# Mango prefers exact Mango-owned spawn commands, then normalized desktop/Flatpak
|
||||||
|
# launchers, then raw process argv before consulting session_launch.
|
||||||
# session_launch=foot|foot
|
# session_launch=foot|foot
|
||||||
# session_launch=foot|gamma|foot -a foot -T gamma -e sh -lc "sleep 600"
|
# session_launch=foot|gamma|foot -a foot -T gamma -e sh -lc "sleep 600"
|
||||||
# session_launch=org.kde.dolphin|dolphin .
|
# session_launch=org.kde.dolphin|dolphin .
|
||||||
|
|
|
||||||
426
src/mango.c
426
src/mango.c
|
|
@ -775,6 +775,7 @@ void mango_session_remember_client_launch_command(Client *c,
|
||||||
static char *mango_session_recover_process_command(pid_t pid);
|
static char *mango_session_recover_process_command(pid_t pid);
|
||||||
static void mango_session_attach_process_command(Client *c);
|
static void mango_session_attach_process_command(Client *c);
|
||||||
static char *mango_session_find_desktop_exec(const char *app_id);
|
static char *mango_session_find_desktop_exec(const char *app_id);
|
||||||
|
static char *mango_session_find_flatpak_command(const char *app_id);
|
||||||
static char *mango_session_normalize_launch_command(Client *c, pid_t pid);
|
static char *mango_session_normalize_launch_command(Client *c, pid_t pid);
|
||||||
static void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
static void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
int32_t sx, int32_t sy, void *data);
|
int32_t sx, int32_t sy, void *data);
|
||||||
|
|
@ -1207,42 +1208,112 @@ static void mango_session_trim_newline(char *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *mango_session_strip_exec_field_codes(const char *exec) {
|
static char *mango_session_strip_exec_field_codes(const char *exec) {
|
||||||
char *copy, *token, *saveptr = NULL, *result;
|
char **tokens = NULL;
|
||||||
|
char *current = NULL;
|
||||||
|
char *result = NULL;
|
||||||
|
size_t token_count = 0, token_capacity = 0;
|
||||||
|
size_t current_len = 0, current_capacity = 0;
|
||||||
|
bool in_single_quotes = false;
|
||||||
|
bool in_double_quotes = false;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
if (!exec || exec[0] == '\0')
|
if (!exec || exec[0] == '\0')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
copy = strdup(exec);
|
for (p = exec; *p != '\0'; ++p) {
|
||||||
if (!copy)
|
char ch = *p;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
result = strdup("");
|
if (!in_single_quotes && !in_double_quotes &&
|
||||||
for (token = strtok_r(copy, " \t", &saveptr); token != NULL;
|
(ch == ' ' || ch == '\t')) {
|
||||||
token = strtok_r(NULL, " \t", &saveptr)) {
|
if (current_len > 0) {
|
||||||
char *next;
|
char **next_tokens;
|
||||||
|
|
||||||
if (token[0] == '%' && token[1] != '\0')
|
if (token_count + 1 > token_capacity) {
|
||||||
|
size_t next_capacity =
|
||||||
|
token_capacity == 0 ? 8 : token_capacity * 2;
|
||||||
|
|
||||||
|
next_tokens =
|
||||||
|
realloc(tokens, next_capacity * sizeof(*tokens));
|
||||||
|
if (!next_tokens)
|
||||||
|
goto cleanup;
|
||||||
|
tokens = next_tokens;
|
||||||
|
token_capacity = next_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
current[current_len] = '\0';
|
||||||
|
tokens[token_count++] = current;
|
||||||
|
current = NULL;
|
||||||
|
current_len = 0;
|
||||||
|
current_capacity = 0;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(token, "%%") == 0)
|
}
|
||||||
token = "%";
|
|
||||||
|
|
||||||
next = result[0] == '\0' ? string_printf("%s", token)
|
if (!in_double_quotes && ch == '\'') {
|
||||||
: string_printf("%s %s", result, token);
|
in_single_quotes = !in_single_quotes;
|
||||||
free(result);
|
continue;
|
||||||
result = next;
|
}
|
||||||
if (!result) {
|
if (!in_single_quotes && ch == '"') {
|
||||||
free(copy);
|
in_double_quotes = !in_double_quotes;
|
||||||
return NULL;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == '\\' && p[1] != '\0') {
|
||||||
|
ch = *++p;
|
||||||
|
} else if (ch == '%' && p[1] != '\0') {
|
||||||
|
if (p[1] == '%') {
|
||||||
|
ch = '%';
|
||||||
|
++p;
|
||||||
|
} else {
|
||||||
|
++p;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(copy);
|
if (current_len + 2 > current_capacity) {
|
||||||
|
size_t next_capacity = current_capacity == 0 ? 32 : current_capacity * 2;
|
||||||
|
char *next_current = realloc(current, next_capacity);
|
||||||
|
|
||||||
if (result[0] == '\0') {
|
if (!next_current)
|
||||||
|
goto cleanup;
|
||||||
|
current = next_current;
|
||||||
|
current_capacity = next_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
current[current_len++] = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_len > 0) {
|
||||||
|
char **next_tokens;
|
||||||
|
|
||||||
|
if (token_count + 1 > token_capacity) {
|
||||||
|
size_t next_capacity = token_capacity == 0 ? 8 : token_capacity * 2;
|
||||||
|
|
||||||
|
next_tokens = realloc(tokens, next_capacity * sizeof(*tokens));
|
||||||
|
if (!next_tokens)
|
||||||
|
goto cleanup;
|
||||||
|
tokens = next_tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
current[current_len] = '\0';
|
||||||
|
tokens[token_count++] = current;
|
||||||
|
current = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mango_session_join_argv(tokens, token_count);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(current);
|
||||||
|
if (tokens) {
|
||||||
|
for (size_t i = 0; i < token_count; ++i)
|
||||||
|
free(tokens[i]);
|
||||||
|
free(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result || result[0] == '\0') {
|
||||||
free(result);
|
free(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1251,43 +1322,211 @@ static bool mango_session_path_exists(const char *path) {
|
||||||
return path && stat(path, &st) == 0;
|
return path && stat(path, &st) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mango_session_desktop_matches(const char *desktop_path,
|
typedef struct {
|
||||||
const char *app_id,
|
char *path;
|
||||||
char **exec_out) {
|
char *exec_value;
|
||||||
|
char *startup_wm_class;
|
||||||
|
char *flatpak_id;
|
||||||
|
} MangoSessionDesktopEntry;
|
||||||
|
|
||||||
|
static void mango_session_free_desktop_entry(MangoSessionDesktopEntry *entry) {
|
||||||
|
if (!entry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
free(entry->path);
|
||||||
|
free(entry->exec_value);
|
||||||
|
free(entry->startup_wm_class);
|
||||||
|
free(entry->flatpak_id);
|
||||||
|
memset(entry, 0, sizeof(*entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mango_session_append_search_dir(char ***dirs, size_t *count,
|
||||||
|
size_t *capacity,
|
||||||
|
const char *dir) {
|
||||||
|
char **next_dirs;
|
||||||
|
|
||||||
|
if (!dirs || !count || !capacity || !dir || dir[0] == '\0')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (*count > 0 && strcmp((*dirs)[*count - 1], dir) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (*count + 1 >= *capacity) {
|
||||||
|
size_t next_capacity = *capacity == 0 ? 8 : *capacity * 2;
|
||||||
|
|
||||||
|
next_dirs = realloc(*dirs, next_capacity * sizeof(**dirs));
|
||||||
|
if (!next_dirs)
|
||||||
|
return false;
|
||||||
|
*dirs = next_dirs;
|
||||||
|
*capacity = next_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*dirs)[*count] = strdup(dir);
|
||||||
|
if (!(*dirs)[*count])
|
||||||
|
return false;
|
||||||
|
(*count)++;
|
||||||
|
(*dirs)[*count] = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mango_session_append_data_home_applications(char ***dirs, size_t *count,
|
||||||
|
size_t *capacity) {
|
||||||
|
const char *xdg_data_home = getenv("XDG_DATA_HOME");
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
char *applications_dir = NULL;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
if (xdg_data_home && xdg_data_home[0] != '\0')
|
||||||
|
applications_dir = string_printf("%s/applications", xdg_data_home);
|
||||||
|
else if (home && home[0] != '\0')
|
||||||
|
applications_dir = string_printf("%s/.local/share/applications", home);
|
||||||
|
|
||||||
|
if (!applications_dir)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ok = mango_session_append_search_dir(dirs, count, capacity, applications_dir);
|
||||||
|
free(applications_dir);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mango_session_append_data_dirs_applications(char ***dirs, size_t *count,
|
||||||
|
size_t *capacity) {
|
||||||
|
const char *xdg_data_dirs = getenv("XDG_DATA_DIRS");
|
||||||
|
const char *cursor;
|
||||||
|
|
||||||
|
if (!xdg_data_dirs || xdg_data_dirs[0] == '\0')
|
||||||
|
xdg_data_dirs = "/usr/local/share:/usr/share";
|
||||||
|
|
||||||
|
for (cursor = xdg_data_dirs; cursor && cursor[0] != '\0';) {
|
||||||
|
const char *separator = strchr(cursor, ':');
|
||||||
|
size_t len = separator ? (size_t)(separator - cursor) : strlen(cursor);
|
||||||
|
char *base_dir;
|
||||||
|
char *applications_dir;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
cursor = separator ? separator + 1 : NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_dir = strndup(cursor, len);
|
||||||
|
if (!base_dir)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
applications_dir = string_printf("%s/applications", base_dir);
|
||||||
|
free(base_dir);
|
||||||
|
if (!applications_dir)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ok = mango_session_append_search_dir(dirs, count, capacity,
|
||||||
|
applications_dir);
|
||||||
|
free(applications_dir);
|
||||||
|
if (!ok)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cursor = separator ? separator + 1 : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **mango_session_desktop_search_dirs(void) {
|
||||||
|
char **dirs = NULL;
|
||||||
|
size_t count = 0, capacity = 0;
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
char *user_flatpak_dir = NULL;
|
||||||
|
|
||||||
|
if (!mango_session_append_data_home_applications(&dirs, &count, &capacity) ||
|
||||||
|
!mango_session_append_data_dirs_applications(&dirs, &count, &capacity))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!mango_session_append_search_dir(&dirs, &count, &capacity,
|
||||||
|
"/var/lib/flatpak/exports/share/applications"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (home && home[0] != '\0') {
|
||||||
|
user_flatpak_dir = string_printf(
|
||||||
|
"%s/.local/share/flatpak/exports/share/applications", home);
|
||||||
|
if (!user_flatpak_dir)
|
||||||
|
goto fail;
|
||||||
|
if (!mango_session_append_search_dir(&dirs, &count, &capacity,
|
||||||
|
user_flatpak_dir))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(user_flatpak_dir);
|
||||||
|
return dirs;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(user_flatpak_dir);
|
||||||
|
if (dirs) {
|
||||||
|
for (size_t i = 0; i < count; ++i)
|
||||||
|
free(dirs[i]);
|
||||||
|
free(dirs);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mango_session_free_search_dirs(char **dirs) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!dirs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; dirs[i] != NULL; ++i)
|
||||||
|
free(dirs[i]);
|
||||||
|
free(dirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mango_session_load_desktop_entry(const char *desktop_path,
|
||||||
|
MangoSessionDesktopEntry *entry) {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char line[2048];
|
char line[2048];
|
||||||
char *exec_value = NULL;
|
|
||||||
char *startup_wm_class = NULL;
|
|
||||||
char *flatpak_id = NULL;
|
|
||||||
char *desktop_id = NULL;
|
|
||||||
bool matched = false;
|
|
||||||
const char *basename;
|
|
||||||
char *dot;
|
|
||||||
|
|
||||||
if (!desktop_path || !app_id || app_id[0] == '\0')
|
if (!desktop_path || !entry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memset(entry, 0, sizeof(*entry));
|
||||||
|
entry->path = strdup(desktop_path);
|
||||||
|
if (!entry->path)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
f = fopen(desktop_path, "r");
|
f = fopen(desktop_path, "r");
|
||||||
if (!f)
|
if (!f) {
|
||||||
|
mango_session_free_desktop_entry(entry);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
mango_session_trim_newline(line);
|
mango_session_trim_newline(line);
|
||||||
if (strncmp(line, "Exec=", 5) == 0) {
|
if (strncmp(line, "Exec=", 5) == 0) {
|
||||||
free(exec_value);
|
free(entry->exec_value);
|
||||||
exec_value = strdup(line + 5);
|
entry->exec_value = strdup(line + 5);
|
||||||
} else if (strncmp(line, "StartupWMClass=", 15) == 0) {
|
} else if (strncmp(line, "StartupWMClass=", 15) == 0) {
|
||||||
free(startup_wm_class);
|
free(entry->startup_wm_class);
|
||||||
startup_wm_class = strdup(line + 15);
|
entry->startup_wm_class = strdup(line + 15);
|
||||||
} else if (strncmp(line, "X-Flatpak=", 10) == 0) {
|
} else if (strncmp(line, "X-Flatpak=", 10) == 0) {
|
||||||
free(flatpak_id);
|
free(entry->flatpak_id);
|
||||||
flatpak_id = strdup(line + 10);
|
entry->flatpak_id = strdup(line + 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
basename = strrchr(desktop_path, '/');
|
return true;
|
||||||
basename = basename ? basename + 1 : desktop_path;
|
}
|
||||||
|
|
||||||
|
static bool mango_session_desktop_entry_matches(
|
||||||
|
const MangoSessionDesktopEntry *entry, const char *app_id) {
|
||||||
|
const char *basename;
|
||||||
|
char *desktop_id;
|
||||||
|
char *dot;
|
||||||
|
bool matched = false;
|
||||||
|
|
||||||
|
if (!entry || !entry->path || !app_id || app_id[0] == '\0')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basename = strrchr(entry->path, '/');
|
||||||
|
basename = basename ? basename + 1 : entry->path;
|
||||||
desktop_id = strdup(basename);
|
desktop_id = strdup(basename);
|
||||||
if (desktop_id) {
|
if (desktop_id) {
|
||||||
dot = strrchr(desktop_id, '.');
|
dot = strrchr(desktop_id, '.');
|
||||||
|
|
@ -1298,30 +1537,28 @@ static bool mango_session_desktop_matches(const char *desktop_path,
|
||||||
free(desktop_id);
|
free(desktop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!matched && startup_wm_class && strcmp(startup_wm_class, app_id) == 0)
|
if (!matched && entry->startup_wm_class &&
|
||||||
|
strcmp(entry->startup_wm_class, app_id) == 0)
|
||||||
matched = true;
|
matched = true;
|
||||||
if (!matched && flatpak_id && strcmp(flatpak_id, app_id) == 0)
|
if (!matched && entry->flatpak_id && strcmp(entry->flatpak_id, app_id) == 0)
|
||||||
matched = true;
|
matched = true;
|
||||||
|
|
||||||
if (matched && exec_value && exec_out)
|
|
||||||
*exec_out = mango_session_strip_exec_field_codes(exec_value);
|
|
||||||
|
|
||||||
free(exec_value);
|
|
||||||
free(startup_wm_class);
|
|
||||||
free(flatpak_id);
|
|
||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *mango_session_find_desktop_exec(const char *app_id) {
|
static bool mango_session_find_desktop_entry(const char *app_id,
|
||||||
const char *dirs[] = {
|
MangoSessionDesktopEntry *result) {
|
||||||
"/home/kenn/.local/share/applications",
|
char **dirs = mango_session_desktop_search_dirs();
|
||||||
"/etc/profiles/per-user/kenn/share/applications",
|
bool found = false;
|
||||||
"/run/current-system/sw/share/applications",
|
|
||||||
"/var/lib/flatpak/exports/share/applications",
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; dirs[i] != NULL; ++i) {
|
if (!result)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memset(result, 0, sizeof(*result));
|
||||||
|
if (!dirs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; dirs[i] != NULL && !found; ++i) {
|
||||||
DIR *dir = opendir(dirs[i]);
|
DIR *dir = opendir(dirs[i]);
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
|
|
@ -1329,27 +1566,66 @@ static char *mango_session_find_desktop_exec(const char *app_id) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
MangoSessionDesktopEntry candidate;
|
||||||
char *path;
|
char *path;
|
||||||
char *exec_value = NULL;
|
|
||||||
bool matched;
|
|
||||||
|
|
||||||
if (!strstr(entry->d_name, ".desktop"))
|
if (!strstr(entry->d_name, ".desktop"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
path = string_printf("%s/%s", dirs[i], entry->d_name);
|
path = string_printf("%s/%s", dirs[i], entry->d_name);
|
||||||
matched = mango_session_desktop_matches(path, app_id, &exec_value);
|
if (!path)
|
||||||
free(path);
|
|
||||||
if (!matched)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
closedir(dir);
|
if (!mango_session_load_desktop_entry(path, &candidate)) {
|
||||||
return exec_value;
|
free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
if (!mango_session_desktop_entry_matches(&candidate, app_id)) {
|
||||||
|
mango_session_free_desktop_entry(&candidate);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = candidate;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mango_session_free_search_dirs(dirs);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *mango_session_find_desktop_exec(const char *app_id) {
|
||||||
|
MangoSessionDesktopEntry entry;
|
||||||
|
char *exec_value;
|
||||||
|
|
||||||
|
if (!mango_session_find_desktop_entry(app_id, &entry))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
exec_value = entry.exec_value
|
||||||
|
? mango_session_strip_exec_field_codes(entry.exec_value)
|
||||||
|
: NULL;
|
||||||
|
mango_session_free_desktop_entry(&entry);
|
||||||
|
return exec_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *mango_session_find_flatpak_command(const char *app_id) {
|
||||||
|
MangoSessionDesktopEntry entry;
|
||||||
|
char *command = NULL;
|
||||||
|
|
||||||
|
if (!mango_session_find_desktop_entry(app_id, &entry))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (entry.flatpak_id && strcmp(entry.flatpak_id, app_id) == 0)
|
||||||
|
command = entry.exec_value ? mango_session_strip_exec_field_codes(entry.exec_value)
|
||||||
|
: NULL;
|
||||||
|
|
||||||
|
mango_session_free_desktop_entry(&entry);
|
||||||
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *mango_session_read_cmdline(pid_t pid, size_t *argc_out) {
|
static char *mango_session_read_cmdline(pid_t pid, size_t *argc_out) {
|
||||||
|
|
@ -1441,26 +1717,16 @@ static char *mango_session_recover_process_command(pid_t pid) {
|
||||||
|
|
||||||
static char *mango_session_normalize_launch_command(Client *c, pid_t pid) {
|
static char *mango_session_normalize_launch_command(Client *c, pid_t pid) {
|
||||||
const char *app_id;
|
const char *app_id;
|
||||||
|
char *flatpak_command;
|
||||||
char *desktop_exec;
|
char *desktop_exec;
|
||||||
char *raw_command;
|
char *raw_command;
|
||||||
|
|
||||||
app_id = c ? client_get_appid(c) : NULL;
|
app_id = c ? client_get_appid(c) : NULL;
|
||||||
if (app_id && app_id[0] != '\0' && strcmp(app_id, "broken") != 0) {
|
if (app_id && app_id[0] != '\0' && strcmp(app_id, "broken") != 0) {
|
||||||
char *flatpak_desktop = string_printf(
|
flatpak_command = mango_session_find_flatpak_command(app_id);
|
||||||
"/var/lib/flatpak/exports/share/applications/%s.desktop", app_id);
|
if (flatpak_command && flatpak_command[0] != '\0')
|
||||||
char *user_flatpak_desktop = string_printf(
|
return flatpak_command;
|
||||||
"%s/.local/share/flatpak/exports/share/applications/%s.desktop",
|
free(flatpak_command);
|
||||||
getenv("HOME") ? getenv("HOME") : "", app_id);
|
|
||||||
|
|
||||||
if ((flatpak_desktop && mango_session_path_exists(flatpak_desktop)) ||
|
|
||||||
(user_flatpak_desktop &&
|
|
||||||
mango_session_path_exists(user_flatpak_desktop))) {
|
|
||||||
free(flatpak_desktop);
|
|
||||||
free(user_flatpak_desktop);
|
|
||||||
return string_printf("flatpak run %s", app_id);
|
|
||||||
}
|
|
||||||
free(flatpak_desktop);
|
|
||||||
free(user_flatpak_desktop);
|
|
||||||
|
|
||||||
desktop_exec = mango_session_find_desktop_exec(app_id);
|
desktop_exec = mango_session_find_desktop_exec(app_id);
|
||||||
if (desktop_exec && desktop_exec[0] != '\0')
|
if (desktop_exec && desktop_exec[0] != '\0')
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,23 @@ static char *session_file_path(void) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool session_file_is_trusted(const char *path) {
|
||||||
|
struct stat st;
|
||||||
|
uid_t uid = getuid();
|
||||||
|
|
||||||
|
if (!path || stat(path, &st) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
return false;
|
||||||
|
if (st.st_uid != uid)
|
||||||
|
return false;
|
||||||
|
if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void free_pending_entries(void) {
|
static void free_pending_entries(void) {
|
||||||
free(pending_entries);
|
free(pending_entries);
|
||||||
pending_entries = NULL;
|
pending_entries = NULL;
|
||||||
|
|
@ -275,6 +292,16 @@ static bool load_pending_entries(void) {
|
||||||
if (!path)
|
if (!path)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (access(path, F_OK) != 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!session_file_is_trusted(path)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"mango session: refusing to restore from untrusted session file: %s\n",
|
||||||
|
path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
in = fopen(path, "r");
|
in = fopen(path, "r");
|
||||||
if (!in)
|
if (!in)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue