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:
emersion 2018-12-10 23:20:27 +01:00
parent 6acbe84fdd
commit 8389047b47
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
8 changed files with 121 additions and 114 deletions

View file

@ -4,14 +4,15 @@ lib_sway_common = static_library(
'background-image.c',
'cairo.c',
'ipc-client.c',
'list.c',
'log.c',
'loop.c',
'list.c',
'pango.c',
'readline.c',
'shexp.c',
'stringop.c',
'unicode.c',
'util.c'
'util.c',
),
dependencies: [
cairo,

51
common/shexp.c Normal file
View 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;
}