mirror of
https://github.com/swaywm/sway.git
synced 2026-04-29 06:46:22 -04:00
Introduce shell_expand
This performs shell expansion without field splitting. This fixes issues with filenames containing spaces. This commit also cleans up complicated logic to join fields and to set XDG_CONFIG_HOME.
This commit is contained in:
parent
6acbe84fdd
commit
8389047b47
8 changed files with 121 additions and 114 deletions
|
|
@ -4,14 +4,15 @@ lib_sway_common = static_library(
|
||||||
'background-image.c',
|
'background-image.c',
|
||||||
'cairo.c',
|
'cairo.c',
|
||||||
'ipc-client.c',
|
'ipc-client.c',
|
||||||
|
'list.c',
|
||||||
'log.c',
|
'log.c',
|
||||||
'loop.c',
|
'loop.c',
|
||||||
'list.c',
|
|
||||||
'pango.c',
|
'pango.c',
|
||||||
'readline.c',
|
'readline.c',
|
||||||
|
'shexp.c',
|
||||||
'stringop.c',
|
'stringop.c',
|
||||||
'unicode.c',
|
'unicode.c',
|
||||||
'util.c'
|
'util.c',
|
||||||
),
|
),
|
||||||
dependencies: [
|
dependencies: [
|
||||||
cairo,
|
cairo,
|
||||||
|
|
|
||||||
51
common/shexp.c
Normal file
51
common/shexp.c
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <wordexp.h>
|
||||||
|
#include "shexp.h"
|
||||||
|
|
||||||
|
static const char escaped_quote[] = "'\"'\"'";
|
||||||
|
|
||||||
|
static char *escape(const char *str) {
|
||||||
|
size_t escaped_len = 2; // quotes at the begining and end
|
||||||
|
for (size_t i = 0; str[i] != '\0'; ++i) {
|
||||||
|
if (str[i] == '\'') {
|
||||||
|
escaped_len += strlen(escaped_quote);
|
||||||
|
} else {
|
||||||
|
++escaped_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *escaped = malloc(escaped_len + 1);
|
||||||
|
escaped[0] = '\'';
|
||||||
|
size_t j = 1;
|
||||||
|
for (size_t i = 0; str[i] != '\0'; ++i) {
|
||||||
|
if (str[i] == '\'') {
|
||||||
|
memcpy(&escaped[j], escaped_quote, strlen(escaped_quote));
|
||||||
|
j += strlen(escaped_quote);
|
||||||
|
} else {
|
||||||
|
escaped[j] = str[i];
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
escaped[j] = '\'';
|
||||||
|
escaped[j + 1] = '\0';
|
||||||
|
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shell_expand(char **path) {
|
||||||
|
char *escaped_path = escape(*path);
|
||||||
|
|
||||||
|
wordexp_t p;
|
||||||
|
bool ret = false;
|
||||||
|
if (wordexp(escaped_path, &p, WRDE_UNDEF) == 0) {
|
||||||
|
free(*path);
|
||||||
|
*path = strdup(p.we_wordv[0]);
|
||||||
|
wordfree(&p);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(escaped_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
14
include/shexp.h
Normal file
14
include/shexp.h
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef _SWAY_SHEXP_H
|
||||||
|
#define _SWAY_SHEXP_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a pointer to a string and reallocates it with the result of its shell
|
||||||
|
* expansion. Undefined environment variables are considered as errors. Returns
|
||||||
|
* true if it succeeds, otherwise returns false, leaving the original string
|
||||||
|
* unchanged.
|
||||||
|
*/
|
||||||
|
bool shell_expand(char **path);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#define _POSIX_C_SOURCE 200809
|
#define _POSIX_C_SOURCE 200809
|
||||||
|
#include <errno.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wordexp.h>
|
#include "log.h"
|
||||||
#include <errno.h>
|
#include "shexp.h"
|
||||||
|
#include "stringop.h"
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
#include "sway/swaynag.h"
|
#include "sway/swaynag.h"
|
||||||
#include "log.h"
|
|
||||||
#include "stringop.h"
|
|
||||||
|
|
||||||
static const char *bg_options[] = {
|
static const char *bg_options[] = {
|
||||||
"stretch",
|
"stretch",
|
||||||
|
|
@ -61,28 +61,10 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
||||||
"Missing background scaling mode.");
|
"Missing background scaling mode.");
|
||||||
}
|
}
|
||||||
|
|
||||||
wordexp_t p = {0};
|
|
||||||
char *src = join_args(argv, j);
|
char *src = join_args(argv, j);
|
||||||
while (strstr(src, " ")) {
|
if (!shell_expand(&src)) {
|
||||||
src = realloc(src, strlen(src) + 2);
|
return cmd_results_new(CMD_INVALID, "output",
|
||||||
char *ptr = strstr(src, " ") + 1;
|
|
||||||
memmove(ptr + 1, ptr, strlen(ptr) + 1);
|
|
||||||
*ptr = '\\';
|
|
||||||
}
|
|
||||||
if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
|
|
||||||
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID, "output",
|
|
||||||
"Invalid syntax (%s)", src);
|
"Invalid syntax (%s)", src);
|
||||||
free(src);
|
|
||||||
wordfree(&p);
|
|
||||||
return cmd_res;
|
|
||||||
}
|
|
||||||
free(src);
|
|
||||||
src = join_args(p.we_wordv, p.we_wordc);
|
|
||||||
wordfree(&p);
|
|
||||||
if (!src) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to duplicate string");
|
|
||||||
return cmd_results_new(CMD_FAILURE, "output",
|
|
||||||
"Unable to allocate resource");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->reading && *src != '/') {
|
if (config->reading && *src != '/') {
|
||||||
|
|
@ -154,4 +136,3 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
||||||
config->handler_context.leftovers.argv = argv;
|
config->handler_context.leftovers.argv = argv;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,40 @@
|
||||||
#define _XOPEN_SOURCE 600 // for realpath
|
#define _XOPEN_SOURCE 600 // for realpath
|
||||||
#include <stdio.h>
|
#include <dirent.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <wordexp.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <dirent.h>
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wordexp.h>
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
#elif __FreeBSD__
|
#elif __FreeBSD__
|
||||||
#include <dev/evdev/input-event-codes.h>
|
#include <dev/evdev/input-event-codes.h>
|
||||||
#endif
|
#endif
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
#include "sway/input/input-manager.h"
|
#include "cairo.h"
|
||||||
#include "sway/input/seat.h"
|
#include "list.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "pango.h"
|
||||||
|
#include "readline.h"
|
||||||
|
#include "shexp.h"
|
||||||
|
#include "stringop.h"
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
#include "sway/criteria.h"
|
#include "sway/criteria.h"
|
||||||
|
#include "sway/input/input-manager.h"
|
||||||
|
#include "sway/input/seat.h"
|
||||||
#include "sway/swaynag.h"
|
#include "sway/swaynag.h"
|
||||||
#include "sway/tree/arrange.h"
|
#include "sway/tree/arrange.h"
|
||||||
#include "sway/tree/root.h"
|
#include "sway/tree/root.h"
|
||||||
#include "sway/tree/workspace.h"
|
#include "sway/tree/workspace.h"
|
||||||
#include "cairo.h"
|
|
||||||
#include "pango.h"
|
|
||||||
#include "readline.h"
|
|
||||||
#include "stringop.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
struct sway_config *config = NULL;
|
struct sway_config *config = NULL;
|
||||||
|
|
||||||
|
|
@ -321,16 +322,12 @@ static char *get_config_path(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
|
for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
|
||||||
wordexp_t p;
|
char *path = strdup(config_paths[i]);
|
||||||
if (wordexp(config_paths[i], &p, WRDE_UNDEF) == 0) {
|
if (shell_expand(&path) && file_exists(path)) {
|
||||||
char *path = strdup(p.we_wordv[0]);
|
|
||||||
wordfree(&p);
|
|
||||||
if (file_exists(path)) {
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -545,17 +542,14 @@ bool load_include_configs(const char *path, struct sway_config *config,
|
||||||
}
|
}
|
||||||
|
|
||||||
wordexp_t p;
|
wordexp_t p;
|
||||||
|
if (wordexp(path, &p, WRDE_UNDEF) < 0) {
|
||||||
if (wordexp(path, &p, 0) < 0) {
|
|
||||||
free(parent_path);
|
free(parent_path);
|
||||||
free(wd);
|
free(wd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char **w = p.we_wordv;
|
for (size_t i = 0; i < p.we_wordc; ++i) {
|
||||||
size_t i;
|
load_include_config(p.we_wordv[i], parent_dir, config, swaynag);
|
||||||
for (i = 0; i < p.we_wordc; ++i) {
|
|
||||||
load_include_config(w[i], parent_dir, config, swaynag);
|
|
||||||
}
|
}
|
||||||
free(parent_path);
|
free(parent_path);
|
||||||
wordfree(&p);
|
wordfree(&p);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wordexp.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,17 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <wordexp.h>
|
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "swaylock/seat.h"
|
|
||||||
#include "swaylock/swaylock.h"
|
|
||||||
#include "background-image.h"
|
#include "background-image.h"
|
||||||
#include "pool-buffer.h"
|
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
|
#include "pool-buffer.h"
|
||||||
#include "readline.h"
|
#include "readline.h"
|
||||||
|
#include "shexp.h"
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
|
#include "swaylock/seat.h"
|
||||||
|
#include "swaylock/swaylock.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
|
#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
|
||||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||||
|
|
@ -375,12 +375,7 @@ static void load_image(char *arg, struct swaylock_state *state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bash doesn't replace the ~ with $HOME if the output name is supplied
|
// Bash doesn't replace the ~ with $HOME if the output name is supplied
|
||||||
wordexp_t p;
|
shell_expand(&image->path);
|
||||||
if (wordexp(image->path, &p, 0) == 0) {
|
|
||||||
free(image->path);
|
|
||||||
image->path = strdup(p.we_wordv[0]);
|
|
||||||
wordfree(&p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the actual image
|
// Load the actual image
|
||||||
image->cairo_surface = load_background_image(image->path);
|
image->cairo_surface = load_background_image(image->path);
|
||||||
|
|
@ -771,32 +766,18 @@ static char *get_config_path(void) {
|
||||||
SYSCONFDIR "/swaylock/config",
|
SYSCONFDIR "/swaylock/config",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!getenv("XDG_CONFIG_HOME")) {
|
char *config_home = getenv("XDG_CONFIG_HOME");
|
||||||
char *home = getenv("HOME");
|
if (config_home == NULL || config_home[0] == '\0') {
|
||||||
char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
|
config_paths[1] = "$HOME/.config/swaylock/config";
|
||||||
if (!config_home) {
|
|
||||||
wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
|
|
||||||
} else {
|
|
||||||
strcpy(config_home, home);
|
|
||||||
strcat(config_home, "/.config");
|
|
||||||
setenv("XDG_CONFIG_HOME", config_home, 1);
|
|
||||||
wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
|
|
||||||
free(config_home);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wordexp_t p;
|
|
||||||
char *path;
|
|
||||||
for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
|
for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
|
||||||
if (wordexp(config_paths[i], &p, 0) == 0) {
|
char *path = strdup(config_paths[i]);
|
||||||
path = strdup(p.we_wordv[0]);
|
if (shell_expand(&path) && file_exists(path)) {
|
||||||
wordfree(&p);
|
|
||||||
if (file_exists(path)) {
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wordexp.h>
|
|
||||||
#include "log.h"
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "log.h"
|
||||||
#include "readline.h"
|
#include "readline.h"
|
||||||
|
#include "shexp.h"
|
||||||
#include "swaynag/swaynag.h"
|
#include "swaynag/swaynag.h"
|
||||||
#include "swaynag/types.h"
|
#include "swaynag/types.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
@ -306,32 +306,18 @@ char *swaynag_get_config_path(void) {
|
||||||
SYSCONFDIR "/swaynag/config",
|
SYSCONFDIR "/swaynag/config",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!getenv("XDG_CONFIG_HOME")) {
|
char *config_home = getenv("XDG_CONFIG_HOME");
|
||||||
char *home = getenv("HOME");
|
if (config_home == NULL || config_home[0] == '\0') {
|
||||||
char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
|
config_paths[1] = "$HOME/.config/swaynag/config";
|
||||||
if (!config_home) {
|
|
||||||
wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
|
|
||||||
} else {
|
|
||||||
strcpy(config_home, home);
|
|
||||||
strcat(config_home, "/.config");
|
|
||||||
setenv("XDG_CONFIG_HOME", config_home, 1);
|
|
||||||
wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
|
|
||||||
free(config_home);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wordexp_t p;
|
|
||||||
char *path;
|
|
||||||
for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
|
for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
|
||||||
if (wordexp(config_paths[i], &p, 0) == 0) {
|
char *path = strdup(config_paths[i]);
|
||||||
path = strdup(p.we_wordv[0]);
|
if (shell_expand(&path) && file_exists(path)) {
|
||||||
wordfree(&p);
|
|
||||||
if (file_exists(path)) {
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue