Use GLib to spawn browser and dmenu

This commit is contained in:
Benedikt Heine 2018-10-05 22:59:56 +02:00
parent 778a6857d8
commit fe7d82380e

View File

@ -107,44 +107,40 @@ void open_browser(const char *in)
return; return;
} }
char *url = NULL; char *url, *end;
// If any, remove leading [ linktext ] from URL // If any, remove leading [ linktext ] from URL
const char *end = strstr(in, "] "); if (*in == '[' && (end = strstr(in, "] ")))
if (*in == '[' && end)
url = g_strdup(end + 2); url = g_strdup(end + 2);
else else
url = g_strdup(in); url = g_strdup(in);
int browser_pid1 = fork(); int argc = 2+g_strv_length(settings.browser_cmd);
char **argv = g_malloc_n(argc, sizeof(char*));
if (browser_pid1) { memcpy(argv, settings.browser_cmd, argc * sizeof(char*));
g_free(url); argv[argc-2] = url;
int status; argv[argc-1] = NULL;
waitpid(browser_pid1, &status, 0);
} else {
int browser_pid2 = fork();
if (browser_pid2) {
exit(0);
} else {
int argc = 2+g_strv_length(settings.browser_cmd);
char **argv = g_malloc_n(argc, sizeof(char*));
memcpy(argv, settings.browser_cmd, argc * sizeof(char*)); GError *err = NULL;
argv[argc-2] = url; g_spawn_async(NULL,
argv[argc-1] = NULL; argv,
NULL,
G_SPAWN_DEFAULT
| G_SPAWN_SEARCH_PATH
| G_SPAWN_STDOUT_TO_DEV_NULL
| G_SPAWN_STDERR_TO_DEV_NULL,
NULL,
NULL,
NULL,
&err);
execvp(argv[0], argv); if (err) {
g_free(argv); LOG_C("Cannot spawn browser: %s", err->message);
g_error_free(err);
// execvp won't return if it's successful
// so, if we're here, it's definitely an error
fprintf(stderr, "Warning: failed to execute '%s': %s\n",
settings.browser,
strerror(errno));
exit(EXIT_FAILURE);
}
} }
g_free(argv);
g_free(url);
} }
/* /*
@ -226,57 +222,45 @@ char *invoke_dmenu(const char *dmenu_input)
if (!dmenu_input || *dmenu_input == '\0') if (!dmenu_input || *dmenu_input == '\0')
return NULL; return NULL;
char buf[1024] = {0}; gint dunst_to_dmenu;
int child_io[2]; gint dmenu_to_dunst;
int parent_io[2]; GError *err = NULL;
if (pipe(child_io) != 0) { char buf[1024];
LOG_W("pipe(): error in child: %s", strerror(errno)); char *ret = NULL;
return NULL;
}
if (pipe(parent_io) != 0) {
LOG_W("pipe(): error in parent: %s", strerror(errno));
return NULL;
}
int pid = fork();
if (pid == 0) { g_spawn_async_with_pipes(NULL,
close(child_io[1]); settings.dmenu_cmd,
close(parent_io[0]); NULL,
close(0); G_SPAWN_DEFAULT
if (dup(child_io[0]) == -1) { | G_SPAWN_SEARCH_PATH,
LOG_W("dup(): error in child: %s", strerror(errno)); NULL,
exit(EXIT_FAILURE); NULL,
} NULL,
close(1); &dunst_to_dmenu,
if (dup(parent_io[1]) == -1) { &dmenu_to_dunst,
LOG_W("dup(): error in parent: %s", strerror(errno)); NULL,
exit(EXIT_FAILURE); &err);
}
execvp(settings.dmenu_cmd[0], settings.dmenu_cmd); if (err) {
fprintf(stderr, "Warning: failed to execute '%s': %s\n", LOG_C("Cannot spawn dmenu: %s", err->message);
settings.dmenu, g_error_free(err);
strerror(errno));
exit(EXIT_FAILURE);
} else { } else {
close(child_io[0]);
close(parent_io[1]);
size_t wlen = strlen(dmenu_input); size_t wlen = strlen(dmenu_input);
if (write(child_io[1], dmenu_input, wlen) != wlen) { if (write(dunst_to_dmenu, dmenu_input, wlen) != wlen) {
LOG_W("write(): error: %s", strerror(errno)); LOG_W("Cannot feed dmenu with input: %s", strerror(errno));
} }
close(child_io[1]); close(dunst_to_dmenu);
size_t len = read(parent_io[0], buf, 1023); ssize_t rlen = read(dmenu_to_dunst, buf, sizeof(buf));
close(dmenu_to_dunst);
waitpid(pid, NULL, 0); if (rlen > 0)
ret = g_strndup(buf, rlen);
if (len == 0) { else
return NULL; LOG_W("Didn't receive input from dmenu.");
}
} }
close(parent_io[0]);
return g_strdup(buf); return ret;
} }
/* /*