mirror of
https://github.com/sheumann/hush.git
synced 2025-01-10 16:29:44 +00:00
Implement our own version of execvp for GNO, which quotes arguments containing spaces or tabs.
This should allow most typical cases of arguments with spaces to work correctly, although it will still break down in some cases. We can't do this perfectly, because we're ultimately dependent on the argument parsing code in the target application, and at least the code generated by ORCA/C doesn't give us a way to make an arbitrary string be treated as a single argument.
This commit is contained in:
parent
5c972aa397
commit
2eedd5e9b3
63
shell/hush.c
63
shell/hush.c
@ -6676,6 +6676,69 @@ static void exec_builtin(char ***to_free,
|
||||
}
|
||||
|
||||
|
||||
#ifdef __GNO__
|
||||
/* We use our own implementation of execvp because we need to
|
||||
* do some things that libc's version doesn't:
|
||||
* 1) Quote arguments containing spaces or tabs
|
||||
* 2) Execute shell scripts in a shell (TODO)
|
||||
*/
|
||||
#define execvp execvp_gno
|
||||
static int execvp_gno(const char *file, char *const argv[])
|
||||
{
|
||||
int result;
|
||||
char *args;
|
||||
char *path;
|
||||
|
||||
size_t argslen = 0;
|
||||
int i;
|
||||
char *nextarg;
|
||||
|
||||
path = buildPath(file);
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; argv[i] != NULL; i++) {
|
||||
/* 3 bytes extra for space (or terminating 0) and possible quotes */
|
||||
argslen += strlen(argv[i]) + 3;
|
||||
}
|
||||
|
||||
nextarg = args = malloc(argslen);
|
||||
if (args == NULL) {
|
||||
free(path);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy arguments into a single string, quoting ones that contain spaces
|
||||
* or tabs. This approach won't give the right result in all cases
|
||||
* (e.g. when the argument starts with " or contains both spaces and "),
|
||||
* but it's about the best we can do, since we're dependent on the
|
||||
* argument-parsing code in the target program.
|
||||
*/
|
||||
for (i = 0; argv[i] != NULL; i++) {
|
||||
bool has_space = (strpbrk(argv[i], " \t") != NULL);
|
||||
|
||||
if (has_space)
|
||||
*nextarg++ = '"';
|
||||
strcpy(nextarg, argv[i]);
|
||||
nextarg += strlen(argv[i]);
|
||||
if (has_space)
|
||||
*nextarg++ = '"';
|
||||
*nextarg++ = ' ';
|
||||
}
|
||||
*(nextarg - 1) = 0;
|
||||
|
||||
result = _execve(path, args);
|
||||
|
||||
/* error case */
|
||||
free(path);
|
||||
free(args);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void execvp_or_die(char **argv) NORETURN;
|
||||
static void execvp_or_die(char **argv)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user