1
0
Fork 0
mirror of https://github.com/pygos/init.git synced 2024-06-29 06:20:12 +02:00

Split bulk of split_argv out into helper function

Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
David Oberhollenzer 2018-04-11 15:57:01 +02:00
parent dca72a4c77
commit 4ee0ea9754
2 changed files with 75 additions and 52 deletions

View file

@ -99,14 +99,26 @@ int rdline(rdline_t *t);
*/ */
int unescape(char *src); int unescape(char *src);
/*
Replace spaces in 'str' with null bytes. Tread strings (started and
terminated with double-quotes which can be escaped) as a single block.
Such strings are run through unescap(). All elements are tightly
packed together and the function returns the number of consecutive
argument strings that are now inside 'str'.
Returns a negative value if unescape() fails, a string is not
termianted or two such strings touch each other without a white
space in between.
*/
int pack_argv(char *str);
/* /*
Split a space seperated string into a sequence of null-terminated Split a space seperated string into a sequence of null-terminated
strings. Return a NULL terminated array of strings pointing to the strings. Return a NULL terminated array of strings pointing to the
start of each sub string. start of each sub string.
If a double quote is encountered, the entire string up to to the next, It basically runs pack_argv on 'str' and then constructs the argv
unescaped double quite is interpreted as a single sub string and vector from that, with each entry pointing into 'str'.
fed through the unescape function.
The returned array must be freed with free(). The returned array must be freed with free().
*/ */

View file

@ -16,78 +16,89 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include "util.h" #include "util.h"
char **split_argv(char *str) int pack_argv(char *str)
{ {
size_t i = 0, cap = 0, new_cap; char *dst, *start;
char **argv = NULL, **new; int count = 0;
char *ptr;
ptr = str; dst = str;
for (;;) { for (;;) {
if (*ptr == ' ') { while (*str == ' ')
++ptr; ++str;
continue;
}
if (i == cap) { if (*str == '\0')
new_cap = cap ? cap * 2 : 16;
new = realloc(argv, sizeof(argv[0]) * new_cap);
if (new == NULL) {
free(argv);
errno = ENOMEM;
return NULL;
}
cap = new_cap;
argv = new;
}
if (*ptr == '\0') {
argv[i++] = NULL;
break; break;
}
argv[i++] = ptr; if (*str == '"') {
start = dst;
*(dst++) = *(str++);
if (*ptr == '"') { while (*str != '"') {
++ptr; if (*str == '\0')
while (*ptr != '\0' && *ptr != '"') { goto fail_str;
if (ptr[0] == '\\' && ptr[1] != '\0') if (str[0] == '\\' && str[1] != '\0')
++ptr; *(dst++) = *(str++);
*(dst++) = *(str++);
++ptr;
} }
if (*ptr == '"') *(dst++) = *(str++);
++ptr;
if (*ptr == ' ') { if (*str != ' ' && *str != '\0')
*(ptr++) = '\0';
} else if (*ptr != '\0') {
goto fail_str; goto fail_str;
} if (*str == ' ')
++str;
if (unescape(argv[i - 1])) *(dst++) = '\0';
if (unescape(start))
goto fail_str; goto fail_str;
dst = start + strlen(start) + 1;
} else { } else {
while (*ptr != '\0' && *ptr != ' ') while (*str != '\0' && *str != ' ')
++ptr; *(dst++) = *(str++);
if (*str == ' ') {
if (*ptr == ' ') ++str;
*(ptr++) = '\0'; *(dst++) = '\0';
}
} }
++count;
} }
return argv; *dst = '\0';
return count;
fail_str: fail_str:
free(argv);
errno = EINVAL; errno = EINVAL;
return NULL; return -1;
}
char **split_argv(char *str)
{
char **argv = NULL;
int i, count;
count = pack_argv(str);
if (count <= 0)
return NULL;
argv = malloc(sizeof(argv[0]) * (count + 1));
if (argv == NULL)
return NULL;
for (i = 0; i < count; ++i) {
argv[i] = str;
str += strlen(str) + 1;
}
argv[i] = NULL;
return argv;
} }